fhelium.experimental.bootstrap.polynomial
Polynomial approximations and encrypted evaluation schedules.
EvenChebyshevEvaluator
class View source
EvenChebyshevEvaluator(evaluator: Any)Evaluate sum a_(2j) T_(2j)(x) as sum a_(2j) T_j(T2(x)).
evaluator selects the inner polynomial schedule. Forming T2(x)=2x²−1 consumes one ciphertext multiplication, relinearization and complete Q group rescale. The inner evaluator consumes the resulting actual scale. Odd coefficients must be zero; constants use the inner evaluator directly. Output preserves input representation and batch axes.
Attributes
| Name | Type | Default/value |
|---|---|---|
evaluator | Any |
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...] | None: ...Compose the actual T2 product and the folded evaluator's consumers.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, RelinearizationKey] | None=None) -> Ciphertext: ...BlockedChebyshevEvaluator
class View source
BlockedChebyshevEvaluator(baby_step: int | None = None, skip_near_zero: float = 0.0)Evaluate
Descending elimination uses baby_step=None,
At final depth
Input and output are CT2 over Q with the same batch axes. The input domain is preserved when retaining NTT; otherwise output is coefficient form. NTT intermediates follow BootstrapArithmetic.retain_ntt. The approximation's domain remains caller-owned; complex inputs are evaluated as
Attributes
| Name | Type | Default/value |
|---|---|---|
baby_step | int | None | None |
skip_near_zero | float | 0.0 |
plan
method
def plan(polynomial: PolynomialApproximation) -> ChebyshevBlockPlan: ...Return the shared coefficient, basis, depth and operation plan.
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Return the depth consumed by this polynomial's selected plan.
operation_inventory
method
def operation_inventory(polynomial: PolynomialApproximation) -> dict[str, int]: ...Count products, relinearizations and group rescales in the plan.
relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...]: ...Return basis-product depths and the single delayed giant-sum depth.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, RelinearizationKey] | None=None) -> Ciphertext: ...Execute the plan, retaining actual scales and the input domain.
ChebyshevBlockPlan
class View source
ChebyshevBlockPlan(polynomial: PolynomialApproximation, baby_step: int, coefficients: tuple[tuple[complex, ...], ...], basis_depths: tuple[tuple[int, int], ...], required_depths: int, inventory: tuple[tuple[str, int], ...])Coefficient blocks, shared binary nodes and their depth schedule.
coefficients[j][i] multiplies T_i(x) T_(j*m)(x). A baby step of zero denotes the direct low-degree schedule. basis_depths records each node's depth relative to the input, in dependency order.
Attributes
| Name | Type | Default/value |
|---|---|---|
polynomial | PolynomialApproximation | |
baby_step | int | |
coefficients | tuple[tuple[complex, ...], ...] | |
basis_depths | tuple[tuple[int, int], ...] | |
required_depths | int | |
inventory | tuple[tuple[str, int], ...] |
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 in the shared power schedule.
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Count the deepest shared power node plus its coefficient rescale.
relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...]: ...Return product-input depths of the required shared power nodes.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, 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
Shared basis nodes are retained until their last polynomial or recurrence consumer. Depth-specific
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 in the shared basis schedule.
required_depths
method
def required_depths(polynomial: PolynomialApproximation) -> int: ...Count the deepest shared basis node plus its coefficient rescale.
relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...]: ...Return product-input depths of the required shared basis nodes.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, RelinearizationKey] | None=None) -> Ciphertext: ...Build required
Terms at or below skip_near_zero are omitted. A constant-only polynomial consumes one depth, as reported by 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 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.
relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...]: ...Return Horner product depths after the leading coefficient rescale.
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 | EvaluationKeySet | Mapping[int, 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 determines the product DAG and its required depths.
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.
relinearization_depths
method
def relinearization_depths(polynomial: PolynomialApproximation, *, input_depth: int=0) -> tuple[int, ...]: ...Return basis and aligned giant-product depths from the fixed schedule.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, polynomial: PolynomialApproximation, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, 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