fhelium.experimental.bootstrap.polynomial
Polynomial approximations and encrypted evaluation schedules.
BalancedPowerEvaluator
class View source
BalancedPowerEvaluator(skip_near_zero: float = 0.0)Evaluate a power series through a shared balanced product tree.
To construct
evaluate consumes a two-component coefficient-domain, standard-RNS Q ciphertext representing the basis coordinate [component, *batch, limb, coefficient]; all batch members share depth, scale, and prime_ids. The method is functional. Each ciphertext product converts operands to NTT/Montgomery form, multiplies to three components, relinearizes back to two coefficient-domain standard components, and rescales by the complete Q group product while retaining actual scale. The final result is coefficient-domain standard RNS over Q at ciphertext.depth + required_depths(polynomial), with the corresponding prime_ids, unchanged batch shape, two components, and the coefficient-product target scale.
Attributes
| Name | Type | Default/value |
|---|---|---|
skip_near_zero | float | 0.0 |
operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...Return multiplying operations executed by evaluate.
Coefficient multiplication counts only active nonconstant terms. Alignment multiplication counts every multiply-by-one depth advance, including advances used inside the shared power tree and before term addition. Additions and plaintext encoding are not multiplications.
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Count the deepest balanced-product path and coefficient product.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | None=None) -> Ciphertext: ...Evaluate
Coefficients with magnitude at or below skip_near_zero are omitted. A constant-only polynomial still consumes one depth by multiplying the input by zero; this keeps the execution behavior equal to the declared one-depth cost. Inputs are not mutated and output storage does not alias an input.
BinaryDecompositionChebyshevEvaluator
class View source
BinaryDecompositionChebyshevEvaluator(skip_near_zero: float = 0.0)Evaluate a Chebyshev series through shared doubling identities.
The evaluator builds only basis elements required by nonzero terms. It recursively uses
caching every required
The coordinate, tensor axes, arithmetic-state preconditions, functional behavior, per-product transitions, output depth, active prime_ids, and depth-dependent scale schedule match BalancedPowerEvaluator; only the polynomial basis and multiplication DAG differ.
Attributes
| Name | Type | Default/value |
|---|---|---|
skip_near_zero | float | 0.0 |
operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...Return multiplying operations executed by evaluate.
Alignment includes operand advancement within odd recurrences, the shared depth chain for rescale_operations counts one coefficient rescale per occupied basis depth rather than one per coefficient product.
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Count the deepest required recurrence plus coefficient product.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | None=None) -> Ciphertext: ...Build required
Terms at or below skip_near_zero are omitted. As in the power evaluator, the constant-only case deliberately consumes one depth so its execution agrees with required_depths. The method is functional and returns a two-component coefficient-domain standard-RNS Q value at the arithmetic owner's target scale.
ChebyshevInterpolator
class View source
ChebyshevInterpolator(degree: int, error_samples: int = 8193)Fit a degree-limited Chebyshev series at first-kind nodes.
degree controls both the number of interpolation nodes and the highest returned term error_samples controls only the dense grid used to report max_error; that sampled value is not a proof of the uniform error between grid points.
Attributes
| Name | Type | Default/value |
|---|---|---|
degree | int | |
error_samples | int | 8193 |
approximate
method
def approximate(function: Callable[[np.ndarray], np.ndarray], *, domain: tuple[float, float]=(-1.0, 1.0), name: str='polynomial') -> PolynomialApproximation: ...Interpolate after mapping physical
If domain=(a, b), first-kind nodes
Coefficients in the returned object are functions of normalized
max_error is measured on error_samples equally spaced normalized coordinates after fitting. Approximation runs on CPU binary64/complex128 arrays and returns no encrypted tensor.
HornerPowerEvaluator
class View source
HornerPowerEvaluator()Evaluate a power polynomial by a corrected depth-aware Horner chain.
For degree
and then applies
A constant polynomial deliberately consumes one depth by multiplying the input by zero. A linear polynomial consumes one coefficient-multiplication depth and requires no relinearization key. Degree
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Return one depth for constants or the declared power degree.
operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...Return the corrected-Horner multiplication inventory.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | None=None) -> Ciphertext: ...Evaluate a power polynomial with a corrected Horner recurrence.
The input must be a complete two-component coefficient-domain, standard-RNS Q ciphertext at its recorded actual scale. The method validates all context, key, scale, and available-depth requirements before allocating encrypted temporaries. The functional output is in the same arithmetic state at ciphertext.depth + required_depths(polynomial) and the arithmetic owner's target scale.
PatersonStockmeyerPowerEvaluator
class View source
PatersonStockmeyerPowerEvaluator(baby_step: int)Evaluate a power polynomial with one fixed baby-step size.
baby_step=k is part of the evaluator identity and is never selected at runtime. The evaluator writes
Balanced shared powers
Basis powers follow the input's actual scale recurrence. Coefficient accumulators use a common multiple of those scales chosen so the final product reaches the requested output scale. This keeps additions coherent without changing the polynomial's coefficients or its input coordinate.
The declared coefficient tuple, including zero entries, fixes the schedule. baby_step therefore controls a reproducible DAG rather than an unreliable degree-only estimate.
Attributes
| Name | Type | Default/value |
|---|---|---|
baby_step | int |
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Return the critical-path depth cost for this fixed k.
operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...Return ciphertext, coefficient, and alignment counts.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | None=None) -> Ciphertext: ...Evaluate with the fixed baby/giant schedule and depth caches.
PolynomialApproximation
class View source
PolynomialApproximation(basis: PolynomialBasis, coefficients: tuple[complex, ...], domain: tuple[float, float] = (-1.0, 1.0), name: str = 'polynomial', max_error: float | None = None)An immutable polynomial produced independently of its evaluation DAG.
The coefficient convention is ascending degree. For basis="power",
while basis="chebyshev" means
domain=(a, b) records the physical interval used to design the approximation. The evaluator input is nevertheless normalized (a, b) == (-1, 1); the caller owns the affine map.
Attributes
basis: Basis in whichcoefficientsare expressed.coefficients: Ascending coefficients: entryimultiplies either or .domain: Plaintext interval on which the approximation was designed.name: Human-readable diagnostic name.max_error: Optional sampled or certified approximation error.
Attributes
| Name | Type | Default/value |
|---|---|---|
basis | PolynomialBasis | |
coefficients | tuple[complex, ...] | |
domain | tuple[float, float] | (-1.0, 1.0) |
name | str | 'polynomial' |
max_error | float | None | None |
degree
property
degree: intReturn the algebraic degree including trailing zero entries.
evaluate_plaintext
method
def evaluate_plaintext(values: np.ndarray) -> np.ndarray: ...Evaluate
values may have any NumPy-broadcastable shape, which is preserved in the output. They are coordinates in the polynomial's basis domain. For a Chebyshev approximation created on a physical interval other than