Arrays and values#
ExactRef stores data as raw bits with a format, so every value it reads or returns is exact: bfloat16 and float8 values keep their encodings, and -0, infinities and NaN keep their identity. Its arrays are immutable, so an input cannot change during a calculation.
ExactRef holds data in Array (immutable) and MutableArray (editable): one
flat byte buffer plus a dtype, a shape and a byte order. asarray imports
data into them. A FloatValue or ComplexValue is the exact value of one
element. Data in and out walks through them with
examples.
At a glance#
To |
Use |
|---|---|
import data |
|
read values |
|
read exact values |
|
read raw bits |
|
read the layout |
|
change the layout |
|
build an array |
|
edit values |
|
test a bool array |
|
compare bit for bit |
|
asarray#
- asarray(obj, dtype: Format | str | None = None, *, rounding: Rounding | None = None, overflow: str | None = None) Array#
Import data as an immutable
Array.Accepted sources:
Array(returned as is) andMutableArray(frozen copy).Python scalars and nested lists or tuples. Without
dtype, bools becomebool, intsint64, floatsfloat64and complex numberscomplex128; a value the inferred format cannot hold exactly raises.Fraction,FloatValueandComplexValueneed an explicitdtype.Objects with the buffer protocol whose element format is known: NumPy arrays,
array.array,memoryview, andbytes(asuint8).CPU tensors with
__dlpack__(PyTorch, JAX, NumPy), including bfloat16 and float8. A PyTorch tensor's lazy conjugate and negative views are applied first, and one that requires grad is detached.
Data that carries its own format is imported exactly. When
dtypenames a different format, values are converted withroundingandoverflow. Following PyTorch, converting array data to an integer dtype wraps on overflow by default (liketensor.to), while Python values that do not fit raise (liketorch.tensor); other defaults are each format's own: in a format without infinity, a value past the largest rounds within the format's values (FloatFormat.encode). Converting toboolreads every nonzero value, NaN included, as True, as PyTorch does. To reinterpret raw bytes instead, useArray(dtype, shape, buffer).
Array#
- class Array(dtype: Format | str, shape, buffer, *, byteorder: str = 'little')#
An immutable array, suitable as a reference input.
Its storage is a
bytesobject that no caller can modify, so values cannot change during a calculation.- dtype#
The element format, a
Format.
- shape#
The shape, a tuple of ints.
- ndim#
The number of dimensions.
- nbytes#
The size of the buffer in bytes.
- byteorder#
"little"or"big".
- property buffer: bytes#
The underlying bytes, for bulk routines.
- mutable_copy() MutableArray#
Return a mutable array with independent storage.
- all() bool#
Whether every element is true: nonzero, as in PyTorch (NaN is true, a zero of either sign false). True for an empty array.
- any() bool#
Whether some element is true (nonzero, as
allreads it). False for an empty array.
- byte_offset(index=()) int#
Return the byte at which element
indexstarts.
- encoding(index=())#
Return the raw encoding of one element: an unsigned int, or a pair for complex.
- encodings() list#
Return every raw encoding in row-major order.
- classmethod from_encodings(dtype: Format | str, shape, encodings, *, byteorder: str = 'little')#
Build an array from raw encodings in row-major order.
- classmethod from_values(dtype: Format | str, shape, values, *, byteorder: str = 'little', **options)#
Build an array by encoding values in row-major order.
options(such asrounding) are passed todtype.encode.
- identical(other: _ArrayBase) bool#
Whether
otherhas the same dtype, shape and encodings (byte order ignored).
- scalar(index=())#
Return one element as an ordinary Python
float,intorbool.
- scalars() list#
Return every element as a Python scalar in row-major order.
- property size: int#
The number of elements.
- tolist()#
Return the elements as nested lists of Python scalars (a bare scalar for shape
()).
- value(index=())#
Return the exact value of one element (a
FloatValue,intorbool).
- values() list#
Return every exact value in row-major order.
MutableArray#
- class MutableArray(dtype: Format | str, shape, buffer, *, byteorder: str = 'little')#
An array whose elements can be set, for data being built or edited.
Writes go through the codec (
set_value) or checked bulk methods. Callfreeze()to obtain an immutableArray.- property buffer: memoryview#
A read-only view of the current bytes, for bulk routines.
- set_encoding(index, bits) None#
Store a raw encoding (an int, or a pair for complex) at one element.
- set_value(index, value, **options) None#
Encode a value and store it at one element.
options(such asrounding) are passed todtype.encode.
- set_encodings(encodings) None#
Replace every element with raw encodings in row-major order.
- set_values(values, **options) None#
Replace every element by encoding values in row-major order.
- set_bytes(data) None#
Replace the whole buffer with bytes of exactly the same length.
- copy() MutableArray#
Return a mutable array with independent storage.
MutableArray also has every reading method of Array.
FloatValue#
- class FloatValue(kind: str, negative: bool, significand: int = 0, exponent: int = 0)#
The exact value of one binary floating-point encoding.
A finite value equals
(-1)**negative * significand * 2**exponent. The pair is normalized (significandis odd, or zero withexponent == 0), so equal values have equal fields. UnlikeFraction, aFloatValuekeeps signed zeros, infinities and NaN.Equality is structural, not IEEE comparison: a NaN equals another NaN of the same sign, and
-0differs from+0. NaN payloads are not represented; read raw encodings when a payload must be preserved.- classmethod from_float(x: float) FloatValue#
Return the exact value of a Python float, including its sign.
- to_fraction() Fraction#
Return the exact rational value. The sign of zero is not preserved.
import exactref as er
# The exact value of the Python float 0.75, which is 3 * 2**-2
v = er.FloatValue.from_float(0.75)
print("value:", repr(v))
# The same value as an exact fraction
print("fraction:", repr(v.to_fraction()))
# Whether it is finite, and whether it is zero
print("finite:", v.is_finite)
print("zero:", v.is_zero)
# Negative infinity, a value a Fraction cannot hold
print("infinite:", er.FloatValue.infinity(negative=True).is_infinite)
value: FloatValue(kind='finite', negative=False, significand=3, exponent=-2)
fraction: Fraction(3, 4)
finite: True
zero: False
infinite: True
ComplexValue#
- class ComplexValue(real: FloatValue, imag: FloatValue)#
The exact value of one complex encoding: a pair of
FloatValueparts.- classmethod from_complex(z: complex) ComplexValue#
Return the exact value of a Python complex, including signed zeros.
# The exact value of the Python complex 1.5 - 2j: a FloatValue for each part
c = er.ComplexValue.from_complex(1.5 - 2j)
# Each part as an exact fraction
print("real:", repr(c.real.to_fraction()))
print("imag:", repr(c.imag.to_fraction()))
real: Fraction(3, 2)
imag: Fraction(-2, 1)