ExactArray and Enclosure#
The rounded answer is the best the output format can hold, but it is not the
exact value. When you need the exact value itself, for example to grade an
implementation that is more precise than the output format or to measure an
error exactly, use r.exact.
r.exact is an ExactArray: certified enclosures of the exact answer, one
per element (a pair per complex element), stored packed rather than as one
Python object each. Each element is a midpoint with a 128-bit significand and
a radius of at most one unit in its last place, 0 when the midpoint is the
exact value.
Stored magnitudes lie between 2**-(2**20) and 2**(2**20). A value beyond
them is stored as an infinity (too big) or a zero (too small) with its sign
and out_of_range set, which still decides its rounding to every supported
format.
- class ExactArray#
Certified exact values of one output, in packed storage (see the module docstring).
- value(index=())#
The enclosure of one element; a
(real, imaginary)pair for complex outputs.
- values() list#
Every element's enclosure in row-major order.
- reshape(shape) ExactArray#
The same elements in row-major order with a new shape of the same size.
- take(positions, shape) ExactArray#
The elements at row-major
positions, as an array ofshape; a negative position counts from the end, as intorch.take.
- paired(shape) ExactArray#
A real array's entries read in pairs (real part, imaginary part) as a complex array of
shape.
- class Enclosure(midpoint: FloatValue, radius: Fraction, out_of_range: bool = False)#
A certified value: the true value lies in
[midpoint - radius, midpoint + radius].radiusis 0 whenmidpointis the exact value, NaN or infinite. Without_of_range, the true value is finite and nonzero withmidpoint's sign, and its magnitude is at least2**LIMIT(midpointinfinite) or below2**-LIMIT(midpointzero).
Examples#
import exactref as er
# The float32 values nearest 0.1, 0.2 and 0.3
x = er.asarray([0.1, 0.2, 0.3], "float32")
# Their dot product with [1, 3, 7]: a matmul of two vectors has one element
r = er.matmul(x, er.asarray([1.0, 3.0, 7.0], "float32"))
# The enclosure of that element
e = r.exact.value()
# The midpoint as an exact fraction
print("midpoint:", repr(e.midpoint.to_fraction()))
# A radius of 0 means the midpoint is the exact value
print("radius:", repr(e.radius))
# out_of_range is True only for a value too big or too small to store
print("out of range:", e.out_of_range)
# Two complex64 arrays of one element each
u, w = er.asarray([1 + 2j], "complex64"), er.asarray([3 - 1j], "complex64")
# Their elementwise product: (1 + 2j) * (3 - 1j) is 5 + 5j
z = er.multiply(u, w)
# A complex element's enclosure is a (real, imaginary) pair
real, imag = z.exact.value((0,))
print("real midpoint:", repr(real.midpoint.to_fraction()))
print("imag midpoint:", repr(imag.midpoint.to_fraction()))
midpoint: Fraction(375809651, 134217728)
radius: Fraction(0, 1)
out of range: False
real midpoint: Fraction(5, 1)
imag midpoint: Fraction(5, 1)
Reading complicated tolerances uses enclosures to measure an error exactly.