httk.core.vectors

Exact-rational vectors (FracVector/FracScalar/MutableFracVector) and the Vector backend/view family that lets the same tensor data be viewed as the exact representation, plain nested sequences, or (optionally) numpy arrays.

The exact-math helpers live in the submodules httk.core.vectors.exactmath (type-preserving exact transcendentals on Fraction and Decimal) and httk.core.vectors.vectormath (functional math wrappers).

Submodules

Attributes

Classes

FracScalar

Represents the fractional number nom/denom. This is a subclass of FracVector with the

FracVector

FracVector is a general immutable N-dimensional vector (tensor) class for performing

LeafCodec

A leaf codec: a documented conversion of one exact fractions.Fraction leaf into a

MutableFracVector

Same as FracVector, only this version allows

SurdScalar

A scalar SurdVector (shape ()): a single field element

SurdVector

An immutable exact tensor over the squarefree-radical field

VectorAPI

Abstract base class for the canonical vector interface.

VectorBackend

Abstract base class for all backends of vector (tensor) data.

VectorFrac

Backend for a vector backed by an actual FracVector

VectorFracView

A view presenting an underlying vector backend as an exact

VectorNative

Backend for a vector backed by plain nested sequences.

VectorNativeView

A view presenting an underlying vector backend as nested tuples, with a selectable leaf codec.

VectorSurd

Backend for a vector backed by an exact SurdVector

VectorSurdView

A view presenting an underlying vector backend as an exact

VectorView

Abstract base class for all views of vector (tensor) data.

Functions

known_leaf_codecs(→ list[str])

Return the registered leaf-codec names, in registration order.

register_leaf_codec(→ None)

Register (or replace) a codec under its name.

numpy_available(→ bool)

Return whether the optional numpy dependency is available for the numeric helpers.

to_numeric(→ NumericVector)

Present obj as plain numpy numbers: a numpy.ndarray for a tensor, a float for a

to_numeric_scalar(→ float)

Convert a single scalar value to a plain float, deterministically.

Package Contents

class httk.core.vectors.FracScalar(nom: int, denom: int)[source]

Bases: FracVector

Represents the fractional number nom/denom. This is a subclass of FracVector with the purpose of making it clear when a scalar fracvector is needed/used.

noms
denom
classmethod create(noms: Any, denom: int | None = None, simplify: bool = True, chain: bool = False, min_accuracy: fractions.Fraction | None = fractions.Fraction(1, 10000)) Self[source]

Create a FracScalar.

FracScalar.create(something) where something may be any object that can be used in the constructor of the Python Fraction class (also works with strings!).

Note: for signature-compatibility with FracVector.create(), this accepts chain and min_accuracy, but (as in the legacy implementation) it ignores them and converts strings exactly via the Fraction constructor.

class httk.core.vectors.FracVector(noms: Noms, denom: int = 1)[source]

FracVector is a general immutable N-dimensional vector (tensor) class for performing linear algebra with fractional numbers.

A FracVector consists of a multidimensional tuple of integer nominators, and a single shared integer denominator.

Since FracVectors are immutable, every operation on a FracVector returns a new FracVector with the result of the operation. A created FracVector never changes. Hence, they are safe to use as keys in dictionaries, to use in sets, etc.

Note: most methods return FracVector results that are not simplified (i.e., the FracVector returned does not have the smallest possible integer denominator). To return a FracVector with the smallest possible denominator, just call simplify() at the last step.

nested_map: ClassVar[collections.abc.Callable[Ellipsis, Any]]
nested_map_fractions: ClassVar[collections.abc.Callable[Ellipsis, Any]]
noms: Noms
denom: int
classmethod use(old: Any) FracVector[source]

Make sure the variable is a FracVector, and if not, convert it.

classmethod create(noms: Any, denom: int | None = None, simplify: bool = True, chain: bool = False, min_accuracy: fractions.Fraction | None = fractions.Fraction(1, 10000)) Self[source]

Create a FracVector from various types of sequences.

Simplest use:

FracVector.create(some_kind_of_sequence)

where ‘some_kind_of_sequence’ can be any nested list or tuple of objects that can be used in the constructor of the Python Fraction class (also works with strings!). If any object found while traveling the items has a .to_fractions() method, it will be called and is expected to return a fraction or list or tuple of fractions.

Parameters:
  • noms – any nested sequence of Fraction-constructible objects.

  • denom – an optional common denominator to divide all nominators with.

  • simplify – if True, return a FracVector with the smallest possible denominator.

  • chain – if True, remove the outermost dimension and chain the sub-sequences. I.e., if input=[[1, 2, 3], [4, 5, 6]] then FracVector.create(input) gives [1, 2, 3, 4, 5, 6].

  • min_accuracy – the minimum accuracy assumed in string input. The default is 1/10000, i.e. 0.33 = 0.3300 = 33/100, whereas 0.3333 = 1/3. Set it to None to assume infinite accuracy, i.e. convert exactly whatever string is given (unless a standard deviation is given as a parenthesis after the string).

Note: FracVector itself implements .to_fractions(), and hence the same constructor allows stacking several FracVector objects like this:

vertical_fracvector = FracVector.create([[fracvector1], [fracvector2]])
horizontal_fracvector = FracVector.create([fracvector1, fracvector2], chain=True)
classmethod create_fast(noms: Any, common_denom: int = 1, max_denom: int | None = None, denom: int | None = None, simplify: bool = True, chain: bool = False) Self[source]

Optimized version of create() that takes advantage of the fact that the type of noms is a nested list of ints (of depth 2 or 3) over a single common_denom.

get_append(other: Any) Self[source]
get_extend(other: Any) Self[source]
get_insert(pos: int, other: Any) Self[source]
get_prepend(other: Any) Self[source]
get_prextend(other: Any) Self[source]
get_stacked(other: Any) Self[source]

Return a new FracVector with other stacked after self along a new leading axis.

self and other must have the same shape; the result gains one extra outermost dimension of size two (numpy stack-like). E.g. stacking the row [1, 2, 3] with [4, 5, 6] gives [[1, 2, 3], [4, 5, 6]]. (The legacy version wrapped other in a redundant extra list, producing a ragged, non-rectangular result.)

get_prestacked(other: Any) Self[source]

Return a new FracVector with other stacked before self along a new leading axis.

The mirror of get_stacked(): stacking [1, 2, 3] in front with [4, 5, 6] gives [[4, 5, 6], [1, 2, 3]].

get_stackedinsert(pos: int, other: Any) Self[source]
classmethod chain_vecs(vecs: Any) Self[source]

Optimized chaining of FracVectors.

Parameters:

vecs – a list (or tuple) of fracvectors that all share the same denominator.

Returns the same thing as FracVector.create(vecs, chain=True), i.e., removes the outermost dimension and chains the sub-sequences. If input=[[1, 2, 3], [4, 5, 6]] then it gives [1, 2, 3, 4, 5, 6], but this method assumes all vectors share the same denominator (it raises an exception if this is not true).

classmethod stack_vecs(vecs: Any) Self[source]

Optimized stacking of FracVectors.

Parameters:

vecs – a list (or tuple) of fracvectors that all share the same denominator.

Returns the same thing as FracVector.create(vecs), but only works if all vectors share the same denominator (raises an exception if this is not true).

classmethod eye(dims: tuple[int, Ellipsis]) Self[source]

Create a diagonal one-matrix with the given dimensions.

classmethod zeros(dims: tuple[int, Ellipsis]) Self[source]

Create a zero matrix with the given dimensions.

classmethod random(dims: tuple[int, Ellipsis], minnom: int = -100, maxnom: int = 100, denom: int = 100) Self[source]

Create a matrix with the given dimensions filled with random rational numbers.

classmethod from_tuple(t: tuple[int, Noms]) Self[source]

Return a FracVector created from the tuple representation (denom, noms), as returned by the to_tuple() method. from_tuple(v.to_tuple()) reconstructs v exactly.

classmethod from_floats(data: Any, resolution: int = 2**32) Self[source]

Create a FracVector from a (nested) list or tuple of floats. You can convert a numpy array with this method if you use A.tolist().

Parameters:
  • l – the (nested) list or tuple of floats.

  • resolution – the resolution used for interpreting the given floating point numbers. Default is 2**32.

classmethod create_cos(data: Any, degrees: bool = False, limit: bool = False, find_best_rational: bool = True, prec: fractions.Fraction = fractions.Fraction(1, 1000000)) Self[source]

Create a FracVector as the cosine of the argument data. If data is composed of strings, the standard deviation of the numbers is taken into account, and the best possible fractional approximation to the cosines of the data is returned within the standard deviation.

This is not the same as FracVector.create(data).cos(), which creates the best possible fractional approximations of data and then takes cos on that.

classmethod create_sin(data: Any, degrees: bool = False, limit: bool = False, prec: fractions.Fraction = fractions.Fraction(1, 1000000)) Self[source]

Create a FracVector as the sine of the argument data. If data is composed of strings, the standard deviation of the numbers is taken into account, and the best possible fractional approximation to the sines of the data is returned within the standard deviation.

This is not the same as FracVector.create(data).sin(), which creates the best possible fractional approximations of data and then takes sin on that.

classmethod create_exp(data: Any, prec: fractions.Fraction = fractions.Fraction(1, 1000000), limit: bool = False) Self[source]

Create a FracVector as the exponent of the argument data. If data is composed of strings, the standard deviation of the numbers is taken into account, and the best possible fractional approximation to the exponents of the data is returned within the standard deviation.

This is not the same as FracVector.create(data).exp(), which creates the best possible fractional approximations of data and then takes exp on that.

classmethod pi(prec: fractions.Fraction = fractions.Fraction(1, 1000000), limit: bool = False) Self[source]

Create a scalar FracVector with a rational approximation of pi to precision prec.

property dim: tuple[int, Ellipsis]

A tuple with the dimensionality of each dimension of the FracVector (the noms are assumed to be a nested list of rectangular shape).

property nom: int

Return the integer nominator of a scalar FracVector.

validate() bool[source]
to_tuple() tuple[int, Noms][source]

Return the FracVector on tuple representation (denom, ...noms...).

to_floats() Any[source]

Convert the FracVector to a (nested) list of floats.

to_float() float[source]

Convert a scalar FracVector to a single float.

to_fractions() Any[source]

Convert the FracVector to a (nested) list of fractions.

to_ints() Any[source]

Convert the FracVector to a (nested) list of integers, rounded off as best possible.

to_strings(accuracy: int = 8) Any[source]

Convert the FracVector to a (nested) list of strings.

to_string(accuracy: int = 8) str[source]

Convert a scalar FracVector to a single string.

to_fraction() fractions.Fraction[source]

Convert a scalar FracVector to a fraction.

to_int() int[source]

Convert a scalar FracVector to an integer (truncating as necessary).

flatten() Self[source]

Return a FracVector that has been flattened out to a single row vector.

classmethod set_common_denom(A: Any, B: Any) tuple[Self, Self, int][source]

Used internally to combine two different FracVectors.

Returns a tuple (A2, B2, denom) where A2 is numerically equal to A, and B2 is numerically equal to B, but A2 and B2 are both set on the same shared denominator denom, which is the product of the denominators of A and B.

sign() int[source]

Return the sign of the scalar FracVector: -1, 0 or 1.

T() Self[source]

Return the transpose, A^T.

det() Self[source]

Return the determinant of the FracVector as a scalar FracVector.

inv() Self[source]

Return the matrix inverse, A^-1.

simplify() Self[source]

Return a reduced FracVector. I.e., each element has the same numerical value but the new FracVector represents them using the smallest possible shared denominator.

simplify_fast(depth: int) Self[source]

Return a reduced FracVector, taking advantage of a known nesting depth. I.e., each element has the same numerical value but the new FracVector represents them using the smallest possible shared denominator.

set_denominator(set_denom: int = 1000000000) Self[source]

Return a FracVector of reduced resolution where every element is the closest numerical approximation using this denominator.

limit_denominator(max_denom: int = 1000000000) Self[source]

Return a FracVector of reduced resolution.

Each element in the returned FracVector is the closest numerical approximation that is allowed by a fraction with maximally this denominator. Note: since all elements must be put on a common denominator, the result may have a larger denominator than max_denom.

floor() int[source]

Return the integer that is equal to or just below the value stored in a scalar FracVector.

modf() tuple[FracVector, FracVector][source]

Return the fractional and integer parts of each element as the pair (fractional, integer) of exact FracVectors sharing this vector’s denominator.

Both parts carry the sign of the element and the integer part truncates toward zero, matching the conventions of math.modf() (e.g. the value -5/2 splits into -1/2 and -2).

ceil() int[source]

Return the integer that is equal to or just above the value stored in a scalar FracVector.

normalize() Self[source]

Add/remove an integer +/-N to each element to place it in the range [0, 1).

normalize_half() Self[source]

Add/remove an integer +/-N to each element to place it in the range [-1/2, 1/2).

This is useful to find the shortest vector C between two points A, B in a space with periodic boundary conditions [0, 1):

C = (A - B).normalize_half()
mul(other: Any) Self[source]

Return the result of multiplying the vector with other using matrix multiplication.

Note that for two 1D FracVectors, A.dot(B) is not the same as A.mul(B), but rather A.mul(B.T()).

dot(other: FracVector) Self[source]

Return the vector dot product of the 1D vector with the 1D vector other, i.e., A . B. The same as A * B.T().

lengthsqr() Self[source]

Return the square of the length of the vector. The same as A * A.T().

cross(other: FracVector) Self[source]

Return the vector cross product of the 3-element 1D vector with the 3-element 1D vector other, i.e., A x B.

reciprocal() Self[source]

Return the reciprocal matrix of a 3x3 matrix (the rows are the reciprocal vectors, without the 2*pi factor).

metric_product(vecA: FracVector, vecB: FracVector) Self[source]

Return the result of the metric product using the present square FracVector as the metric matrix. The same as vecA * self * vecB.T().

cos(prec: fractions.Fraction | None = None, degrees: bool = False, limit: bool = False) Self[source]

Return a FracVector where every element is the cosine of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • degrees – if True, interpret the elements in degrees.

  • limit – if True, require the denominator to be smaller than or equal to the precision.

sin(prec: fractions.Fraction | None = None, degrees: bool = False, limit: bool = False) Self[source]

Return a FracVector where every element is the sine of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • degrees – if True, interpret the elements in degrees.

  • limit – if True, require the denominator to be smaller than or equal to the precision.

acos(prec: fractions.Fraction | None = None, degrees: bool = False, limit: bool = False) Self[source]

Return a FracVector where every element is the arccos of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • degrees – if True, return the result in degrees.

  • limit – if True, require the denominator to be smaller than or equal to the precision.

asin(prec: fractions.Fraction | None = None, degrees: bool = False, limit: bool = False) Self[source]

Return a FracVector where every element is the arcsin of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • degrees – if True, return the result in degrees.

  • limit – if True, require the denominator to be smaller than or equal to the precision.

exp(prec: fractions.Fraction | None = None, limit: bool = False) Self[source]

Return a FracVector where every element is the exponent of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • limit – if True, require the denominator to be smaller than or equal to the precision.

sqrt(prec: fractions.Fraction | None = None, limit: bool = False) Self[source]

Return a FracVector where every element is the sqrt of the element in the source FracVector.

Parameters:
  • prec – the precision (should be set as a fraction).

  • limit – if True, require the denominator to be smaller than or equal to the precision.

max() Self[source]

Return the maximum element across all dimensions in the FracVector. max(fracvector) works for a 1D vector.

nargmax() list[Any][source]

Return a list of indices of all maximum elements across all dimensions in the FracVector.

argmax() Any[source]

Return the index of the maximum element across all dimensions in the FracVector.

min() Self[source]

Return the minimum element across all dimensions in the FracVector. min(fracvector) works for a 1D vector.

nargmin() list[Any][source]

Return a list of indices for all minimum elements across all dimensions in the FracVector.

argmin() Any[source]

Return the index of the minimum element across all dimensions in the FracVector.

class httk.core.vectors.LeafCodec[source]

A leaf codec: a documented conversion of one exact fractions.Fraction leaf into a presentation leaf.

A codec is an orthogonal layer beside the vector backends: given a value already reduced to the canonical Fraction hub, it produces the requested element type. Its from_fraction documents both its exactness contract (when the result is exact) and its default conversion (what it does when an exact result is impossible); on data it never raises.

name: str

Canonical codec name (e.g. "int"); also how an explicit leaf= hint selects it.

from_fraction: collections.abc.Callable[Ellipsis, Any]

Convert (value: fractions.Fraction, **options) -> leaf from the canonical Fraction hub.

check_options: collections.abc.Callable[[dict[str, Any]], None]

Validate an options mapping eagerly, raising ValueError on any invalid option.

httk.core.vectors.known_leaf_codecs() list[str][source]

Return the registered leaf-codec names, in registration order.

httk.core.vectors.register_leaf_codec(codec: LeafCodec) None[source]

Register (or replace) a codec under its name.

class httk.core.vectors.MutableFracVector(noms: Any, denom: int = 1)[source]

Bases: httk.core.vectors.fracvector.FracVector

Same as FracVector, only this version allows assignment of elements, e.g.:

mfracvec[2, 7] = 5

and, e.g.:

mfracvec[:, 7] = [1, 2, 3, 4]

Other than this, the FracVector methods exist and do the same, i.e., they return copies of the fracvector, rather than modifying it.

However, methods have also been added named with set_* prefixes which perform mutating operations, e.g.:

A.set_T()

replaces A with its own transpose, whereas:

A.T()

just returns a new MutableFracVector that is the transpose of A, leaving A unmodified.

nested_map: ClassVar[collections.abc.Callable[Ellipsis, Any]]
nested_inmap: ClassVar[collections.abc.Callable[Ellipsis, Any]]
nested_map_fractions: ClassVar[collections.abc.Callable[Ellipsis, Any]]
noms: Any
classmethod use(old: Any) httk.core.vectors.fracvector.FracVector[source]

Make sure the variable is a MutableFracVector, and if not, convert it.

to_FracVector() httk.core.vectors.fracvector.FracVector[source]

Return a FracVector with the values of this MutableFracVector.

classmethod from_FracVector(other: httk.core.vectors.fracvector.FracVector) MutableFracVector[source]

Create a MutableFracVector from a FracVector.

validate() bool[source]
invalidate() None[source]

Internal method to call when the MutableFracVector is changed in such a way that cached properties are invalidated (e.g., _dim).

set_negative() None[source]

Change the MutableFracVector inline into its own negative: self -> -self.

set_T() None[source]

Change the MutableFracVector inline into its own transpose: self -> self.T.

set_inv() Any[source]

Change the MutableFracVector inline into its own inverse: self -> self^-1.

set_simplify() None[source]

Change the MutableFracVector; reduces any common factor between the denominator and all nominators.

set_set_denominator(resolution: int = 1000000000) None[source]

Change the MutableFracVector; reduces resolution.

Parameters:

resolution – the new denominator; each element becomes the closest numerical approximation using this denominator.

set_normalize() None[source]

Add/remove an integer +/-N to each element to place it in the range [0, 1).

set_normalize_half() None[source]

Add/remove an integer +/-N to each element to place it in the range [-1/2, 1/2).

This is useful to find the shortest vector C between two points A, B in a space with periodic boundary conditions [0, 1):

C = (A - B).normalize_half()
type httk.core.vectors.NumericVector = float | numpy.ndarray[source]
httk.core.vectors.numpy_available() bool[source]

Return whether the optional numpy dependency is available for the numeric helpers.

This reads the vectors package’s _numpy_available flag freshly on each call (the flag set when httk.core.vectors conditionally imports/registers the numpy backend), so tests may monkeypatch httk.core.vectors._numpy_available to exercise the numpy-absent path.

httk.core.vectors.to_numeric(obj: httk.core.vectors.vector_like.VectorLike) NumericVector[source]

Present obj as plain numpy numbers: a numpy.ndarray for a tensor, a float for a scalar.

A tensor becomes a base-class float64 numpy.ndarray (never a view subclass) via VectorNumpyView; a scalar input (shape ()) returns a plain float via to_numeric_scalar() (never a 0-d array).

The numeric presentation is numpy-backed, so this always requires numpy: it raises ImportError (naming the httk-core[numpy] extra) when numpy is not installed, uniformly, so the contract is predictable regardless of the input shape. Use to_numeric_scalar() directly for a single float without a numpy requirement.

httk.core.vectors.to_numeric_scalar(obj: Any) float[source]

Convert a single scalar value to a plain float, deterministically.

A SurdScalar (or scalar SurdVector) and a scalar FracVector render through their own exact to_float(); a Fraction, int, float, or numeric str render via any_to_fraction(). A non-scalar shape raises TypeError.

Unlike to_numeric(), this needs no numpy: a plain float conversion has no numpy dependency, so it works unconditionally and never raises for a missing numpy.

class httk.core.vectors.SurdScalar(components: dict[int, httk.core.vectors.fracvector.FracVector], dim: tuple[int, Ellipsis])[source]

Bases: SurdVector

A scalar SurdVector (shape ()): a single field element \(\sum_r q_r\sqrt r\).

Adds the scalar-only operations — the field inverse, exact sign and ordering, and Decimal rendering — that need a single value rather than a tensor.

inverse() SurdScalar[source]

The multiplicative inverse 1/self (raises ZeroDivisionError on zero).

sign() int[source]

Return the exact sign of the value: -1, 0 or 1.

For an irrational value the sign is decided by refining rational lower/upper bounds on each sqrt(r) (from integer_sqrt() at increasing precision) and summing the weighted intervals until the total interval excludes zero — which always happens in finitely many steps because a nonzero surd is bounded away from zero.

classmethod cos_degrees(q: Any) SurdScalar | None[source]

Return cos(q degrees) as an exact SurdScalar, or None when it is not a surd.

The value lies in the squarefree-radical field precisely when the angle, reduced modulo 360, is a multiple of 15 or of 36 degrees — e.g. \(\cos 30° = \tfrac{\sqrt3}2\), \(\cos 15° = \tfrac{\sqrt6+\sqrt2}4\), \(\cos 36° = \tfrac{1+\sqrt5}4\). q may be an int, Fraction, or numeric string (parsed via any_to_fraction()).

That list is complete: \(\cos(2\pi a/b)\) lies in a field generated by square roots of rationals iff the Galois group \((\mathbb{Z}/b)^\times/\{\pm1\}\) of \(\mathbb{Q}(\cos 2\pi/b)\) has exponent at most 2, which holds exactly for \(b \in \{1,2,3,4,5,6,8,10,12,24\}\) — the rational-degree angles that are multiples of 15° or 36°. (Niven’s theorem is the rational-value special case of this classification.) A None result is therefore a proof that the exact cosine lies outside \(\mathbb{Q}[\sqrt n]\) — use cos() with degrees=True for a deterministic rational approximation in that case.

classmethod sin_degrees(q: Any) SurdScalar | None[source]

Return sin(q degrees) as an exact SurdScalar, or None when it is irrational.

Computed as cos(90 - q) degrees, so exactness follows the same classification as cos_degrees() applied to 90 - q: exact for all multiples of 15 degrees, otherwise None (a proof that the exact sine is outside the field). Note the asymmetry with cos_degrees() for the 36° family: \(\cos 36°\) is an exact surd but \(\sin 36° = \cos 54°\) is not (54 is a multiple of neither 15 nor 36).

acos_degrees() fractions.Fraction | None[source]

Return the exact arccos of this value in degrees over \([0, 180]\), or None.

This is the reverse table lookup: the result is an exact rational number of degrees precisely when the value equals the cosine of a multiple of 15° or 36° (the complete set of rational-degree angles with surd cosines — see cos_degrees()), decided by exact surd equality; otherwise None (the exact angle is then irrational in degrees). Raises ValueError — decided exactly via sign() — when the value lies outside \([-1, 1]\).

to_float(prec: fractions.Fraction = fractions.Fraction(1, 10**30)) float[source]

The value as a float (via a high-precision exact rational approximation).

to_decimal(digits: int | None = None, rounding: str = 'half_even', max_refinements: int | None = None) Any[source]

Render the value as a correctly-rounded decimal.Decimal.

Reuses the exact-math module’s Ziv refinement loop (_to_decimal): a rational value renders exactly (its finite expansion when it fits, else quantized), and an irrational surd — never on a rational rounding boundary — is rendered by refining the rational approximation until the rounding is determined. digits (significant digits; default: the active decimal context precision), rounding ("half_even"/"down") and max_refinements match sqrt() in Decimal mode.

class httk.core.vectors.SurdVector(components: dict[int, httk.core.vectors.fracvector.FracVector], dim: tuple[int, Ellipsis])[source]

An immutable exact tensor over the squarefree-radical field \(\mathbb{Q}[\sqrt n : n\ \text{squarefree}]\).

A SurdVector is a map {squarefree radicand -> FracVector coefficient} (all coefficients sharing one dim); radicand 1 is the rational part. It is stored canonically — coefficients simplified, all-zero coefficients dropped — so the representation is unique and equality/zero-detection are exact. Like FracVector it is immutable and hashable.

See the module docstring for the field facts, the fractional-vs-Cartesian motivation, and the magnitude-vs-linear-structure purpose boundary.

classmethod create(obj: Any) SurdVector[source]

Create a SurdVector from a FracVector, nested rationals, or another SurdVector.

A SurdVector is returned unchanged; anything else is built through create() and embedded exactly at radicand 1 (so every rational value is representable, and a rational input stays rational).

classmethod from_radicand_map(mapping: dict[int, Any]) SurdVector[source]

Compose a SurdVector from a {radicand -> coefficient} mapping.

Radicands are positive integers and need not be squarefree — each is normalized via square_part (sqrt(radicand) = s*sqrt(r)) and the coefficients (FracVector-like, all of one shape) folded together canonically.

classmethod sqrt_of(q: Any) SurdScalar[source]

Return the exact square root of a nonnegative rational q as a SurdScalar.

The result is a plain rational when q is a perfect square (e.g. sqrt_of(4/9) == 2/3) and otherwise a single-radical surd (sqrt_of(8) == 2*sqrt(2)). sqrt(p/q) is normalized as sqrt(p*q)/q so the stored radicand is always a positive squarefree integer (sqrt_of(1/2) == sqrt(2)/2). Raises ValueError on a negative argument — there is no exact square root of a surd (no nested radicals), only of a rational.

classmethod zero(dim: tuple[int, Ellipsis] = ()) SurdVector[source]

The zero SurdVector of shape dim (a SurdScalar for the default ()).

classmethod one() SurdScalar[source]

The scalar 1.

property dim: tuple[int, Ellipsis]

The shape tuple, as for dim.

property is_rational: bool

True iff the value is purely rational (only the radicand-1 term is present).

is_zero() bool[source]

True iff the value is exactly zero (empty canonical form).

property radicands: tuple[int, Ellipsis]

The sorted squarefree radicands present in the canonical form.

coefficient(radicand: int) httk.core.vectors.fracvector.FracVector[source]

The FracVector coefficient of sqrt(radicand) (a zero tensor when absent).

T() SurdVector[source]

Return the transpose, transposing each radicand’s coefficient tensor.

dot(other: Any) SurdScalar[source]

Vector dot product of two 1-D SurdVectors (sum a_i b_i).

lengthsqr() SurdScalar[source]

Return the squared length A * A^T as a SurdScalar.

length() SurdScalar[source]

Return the exact length sqrt(lengthsqr) as a SurdScalar.

Exact precisely when lengthsqr is rational — which canonical arithmetic guarantees for a difference of Cartesian sites under a rational metric (the crystallographic case). When lengthsqr is itself irrational the length would be a nested radical (sqrt(a + b*sqrt(c))), which is outside the field, so this raises ValueError.

det() SurdScalar[source]

Return the determinant of a 3x3 SurdVector as a SurdScalar.

inv() SurdVector[source]

Return the inverse of a 3x3 SurdVector via the adjugate and the scalar field inverse.

to_fractions_approx(prec: fractions.Fraction = fractions.Fraction(1, 10**30)) Any[source]

A deterministic nested list of fractions.Fraction within prec of the true value.

Exact (not merely within prec) whenever the value is rational. This is the compute(prec)-shaped rational approximation reused by the Decimal rendering.

to_floats(prec: fractions.Fraction = fractions.Fraction(1, 10**30)) Any[source]

A nested list of floats (via a high-precision exact rational approximation).

class httk.core.vectors.VectorAPI[source]

Bases: abc.ABC

Abstract base class for the canonical vector interface.

It declares the exactness-preserving fractions accessor (a nested tuple of fractions.Fraction, or a bare Fraction for a scalar) that every vector backend produces from its own native representation and every vector view builds its presentation from, together with the dim shape tuple. This is the single interchange format; there is no pairwise conversion between backends.

On top of the two abstract accessors it provides the guaranteed float renderings to_floats() and to_float(), derived from the fractions hub — so whatever object the family hands you, .to_floats() works. (The exact value types FracVector and SurdVector honor the same contract with their own implementations.)

property fractions: Fractions
Abstractmethod:

property dim: tuple[int, Ellipsis]
Abstractmethod:

to_floats() Any[source]

The value as (possibly nested) plain lists of float — a bare float for a scalar.

Derived from the exact fractions hub; nested lists match the numpy.ndarray.tolist() convention and are directly JSON-serializable.

to_float() float[source]

The scalar value as a plain float; raises TypeError on a non-scalar.

class httk.core.vectors.VectorBackend(backend, **hints)[source]

Bases: httk.core.views.Backend[VectorBackend], httk.core.vectors.vector_api.VectorAPI

Abstract base class for all backends of vector (tensor) data.

Concrete backends carry a native representation (an exact FracVector, plain nested sequences, or a numpy array) and produce the canonical exactness-preserving fractions interchange declared by VectorAPI from it.

backend_classes: ClassVar[list[type[httk.core.views.Backend[Any]]]]
class httk.core.vectors.VectorFrac(obj: httk.core.vectors.fracvector.FracVector, **hints: Any)[source]

Bases: httk.core.vectors.vector_backend.VectorBackend

Backend for a vector backed by an actual FracVector (or FracScalar).

Its fractions accessor produces the exact nested tuple of Fraction, and unwrap returns the wrapped FracVector.

property fractions: httk.core.vectors.vector_api.Fractions
property dim: tuple[int, Ellipsis]
unwrap() Any[source]

Return the most raw representation possible of this backend, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

class httk.core.vectors.VectorFracView(obj: httk.core.vectors.vector_like.VectorLike, denom: Any = _NO_DENOM, **hints: Any)[source]

Bases: httk.core.vectors.vector_view.VectorView, httk.core.vectors.fracvector.FracVector

A view presenting an underlying vector backend as an exact FracVector.

This view is a genuine FracVector, so it can be passed anywhere a FracVector is accepted, and it exposes the full exact-rational algebra (det/inv/*/…). It is built eagerly from the backend’s exact fractions interchange on construction, so the round-trip is exactness-preserving for the frac and native backends. (numpy values are binary rationals, so a numpy source round-trips to the exact float64 rational, not necessarily the original decimal fraction.)

Because inherited FracVector algebra builds its results with the low-level self.__class__(noms, denom) constructor, this class also accepts that two-argument form; results built that way are plain (backend-less) FracVector values presented through this class.

unwrap() Any[source]

Return the most raw representation possible of this view, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

type httk.core.vectors.VectorLike = vector_backend.VectorBackend | vector_view.VectorView | fracvector.FracVector | surdvector.SurdVector | tuple[Any, ...] | list[Any] | 'numpy.ndarray'[source]
class httk.core.vectors.VectorNative(obj: Any, **hints: Any)[source]

Bases: httk.core.vectors.vector_backend.VectorBackend

Backend for a vector backed by plain nested sequences.

The native representation is a (possibly nested) rectangular list or tuple whose leaves are int, float, decimal.Decimal, fractions.Fraction, or str. Conversion into the exact fractions interchange goes through create(), so string-uncertainty parsing (e.g. "0.33342(10)") works here too. unwrap returns the original raw object.

property native: Any

The original nested list/tuple this backend wraps, leaves untouched.

This is the same object returned by unwrap(), exposed as a named accessor so the native view can present a natively-held vector’s leaves verbatim (its preserve-original default) without reaching into private state.

property fractions: httk.core.vectors.vector_api.Fractions
property dim: tuple[int, Ellipsis]
unwrap() Any[source]

Return the most raw representation possible of this backend, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

class httk.core.vectors.VectorNativeView(obj: httk.core.vectors.vector_like.VectorLike, **hints: Any)[source]

Bases: httk.core.vectors.vector_view.VectorView, tuple

A view presenting an underlying vector backend as nested tuples, with a selectable leaf codec.

The leaf codec is the element-domain axis (see httk.core.vectors.leaf_codecs); it is chosen with the leaf= hint plus any codec options (rounding=, digits=, …). There are three modes:

  • preserve-original (leaf=None, and the source is natively-held data): the backend’s original nested leaves are presented verbatim — the same objects, only containers tuple-ized (Decimals in, the same Decimals out). This fixes silent Fraction-ization of natively-held data.

  • exact default (leaf=None, source crossing from a frac/numpy backend): the "exact" codec — int when integral, else fractions.Fraction, never a float (the historical behavior).

  • explicit codec (leaf="int"/"float"/"decimal"/"fraction"/…): every element is converted from the backend’s exact fractions interchange through that codec.

The codec name and its options are validated eagerly at construction (an unknown codec name or invalid option raises ValueError); a codec never raises on the data — a value it cannot represent exactly takes the codec’s documented default conversion, because the backend keeps the exact original. A scalar source is presented as a single-element tuple.

unwrap() Any[source]

Return the most raw representation possible of this view, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

class httk.core.vectors.VectorSurd(obj: httk.core.vectors.surdvector.SurdVector, **hints: Any)[source]

Bases: httk.core.vectors.vector_backend.VectorBackend

Backend for a vector backed by an exact SurdVector (or SurdScalar), kind "surd".

unwrap returns the exact SurdVector. The canonical fractions hub is exact whenever the value is rational (a surd whose canonical form has only the radicand-1 term), matching the established backend-keeps-the-original principle; when the value is genuinely irrational it is reduced to a deterministic rational approximation at the active decimal context precision plus a small guard (lossy but reproducible), and the exact original remains recoverable via unwrap.

property fractions: httk.core.vectors.vector_api.Fractions
property dim: tuple[int, Ellipsis]
unwrap() Any[source]

Return the most raw representation possible of this backend, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

class httk.core.vectors.VectorSurdView(obj: httk.core.vectors.vector_like.VectorLike, **hints: Any)[source]

Bases: httk.core.vectors.vector_view.VectorView, httk.core.vectors.surdvector.SurdVector

A view presenting an underlying vector backend as an exact SurdVector.

This view is a genuine SurdVector, so it exposes the full exact surd algebra (det/inv/*/length/…). It is built eagerly on construction, following the eager immutable-subclass pattern of VectorFracView: from a surd backend it adopts the exact SurdVector directly, and from a frac/native/numpy backend it embeds the backend’s exact rational fractions at radicand 1 — exactly, since every rational is a surd.

(numpy values are binary rationals, so a numpy source embeds the exact float64 rational, not necessarily the original decimal fraction — the same caveat as VectorFracView.)

unwrap() Any[source]

Return the most raw representation possible of this view, i.e., if it uses a backend with an internal representaion - or if it can (possibly lossly) convert itself into a more raw representation that still would be recognized as a <Something>Like type, that representation will be returned. If this is not possible, the instance itself is returned.

class httk.core.vectors.VectorView[source]

Bases: httk.core.views.View[httk.core.vectors.vector_backend.VectorBackend]

Abstract base class for all views of vector (tensor) data.