httk quickstart: vectors
httk-core provides exact vector types: FracVector for rational tensors
and SurdVector for values in the square-root field (needed for, e.g.,
hexagonal cells). All algebra is exact; floats appear only when you explicitly
ask for them.
Exact rational vectors
FracVector accepts nested lists of integers, fractions, strings,
and decimal numbers. A FracVector is stored as integer nominators over one
shared denominator, and is immutable and hashable:
from httk.core import FracVector
a = FracVector([["1/3", "2/3", 0], [0, "1/2", "1/2"], ["1/4", 0, "3/4"]])
print(a * 6)
print("det:", a.det().simplify())
print("inverse:", a.inv().simplify())
print("check:", (a * a.inv()).simplify())
Running this generates the output:
(1/12)*((24, 48, 0), (0, 36, 36), (18, 0, 54))
det: (1/24)*5
inverse: (1/5)*((9, -12, 8), (3, 6, -4), (-3, 4, 4))
check: (1/1)*((1, 0, 0), (0, 1, 0), (0, 0, 1))
Unlike floating point, exact arithmetic never accumulates rounding errors:
v = FracVector(["1/10", "2/10", "3/10"])
print((v + v + v).simplify())
print(0.1 + 0.2 + 0.3)
Running this generates the output:
(1/10)*(3, 6, 9)
0.6000000000000001
Floats are an explicit presentation boundary: a.to_floats() returns nested
plain-float lists, and exact scalars support float(...).
Exact square roots
exactmath holds exact and correctly-rounded transcendentals. By default it
returns a symbolically exact value whenever one exists: sqrt(3) is an exact
SurdScalar, and algebra in the square-root field stays exact:
from httk.core import exactmath
r3 = exactmath.sqrt(3)
print(r3 * r3)
print((1 + r3) * (1 - r3))
Running this generates the output:
3
-2
Rational results are exact Fraction values, exact=False asks for a
controlled rational approximation instead, and digits= gives correctly
rounded decimals to any precision:
from fractions import Fraction
print(exactmath.sqrt(Fraction(9, 4)))
print(exactmath.pi(digits=30))
Running this generates the output:
3/2
3.14159265358979323846264338328
Exact cells
This is what makes httk₂ structures exact: a hexagonal cell basis involves
sqrt(3), which the surd field represents without approximation:
from httk.atomistic import Cell
hexagonal = Cell([3, 3, 5, 90, 90, 120])
print(hexagonal.basis)
print("volume:", hexagonal.volume, "=", float(hexagonal.volume))
Running this generates the output:
(1/2)*((6, 0, 0), (-3, 0, 0), (0, 0, 10)) + sqrt(3)*(1/2)*((0, 0, 0), (0, 3, 0), (0, 0, 0))
volume: (45/2)*sqrt(3) = 38.97114317029974
More
See the httk-core vector details for the full vector family, including the zero-copy numpy views.