fhelium.experimental.bootstrap.reduction.cosine
Cosine-seed periodic reduction with double-angle reconstruction.
CosineDoubleAngleReduction
class View source
CosineDoubleAngleReduction(input_bound: int, double_angle_iterations: int, approximator: Any, evaluator: Any, fuse_input_normalization: bool = False, retain_ntt: bool = False, maximum_plaintext_error: float = 0.001, seed_shift: float = 0.0)Reduce one real branch with a cosine seed and double-angle chain.
input_bound is the positive integer seed_shift places its seed polynomial at a shifted coordinate. With double_angle_iterations, the unshifted seed is
and iteration
Thus seed_shift=c evaluates the seed at z=x+c and subtracts the same shift in its fitted phase. The periodic map is unchanged. For c=-1/(2B), the fitted seed is even; its odd Chebyshev coefficients are zero. Approximation and homomorphic evaluation are separate components.
reference(values) always takes normalized evaluate(...) takes raw fuse_input_normalization=False, dividing by
The homomorphic input is a two-component Q ciphertext in either coefficient/standard or NTT/Montgomery representation, with payload axes [component, *batch, limb, coefficient], active prime_ids, and actual scale matching the arithmetic owner's target at the input depth. Evaluation is functional. With retain_ntt=True, a coefficient input is transformed once and the polynomial and double-angle chain retain NTT/Montgomery form until one final inverse transform. Otherwise each multiplication returns to the input representation. Rescale removes one Q group and divides actual scale by its product. The output uses the input representation, batch and component axes, Q basis, and context; its depth advances by required_depths, its limb axis contains the corresponding suffix of prime_ids, and its actual scale follows the arithmetic owner's depth schedule.
More iterations reduce the seed frequency but each iteration costs one ciphertext multiplication, relinearization, and rescale depth. Neither the class nor evaluate measures the encrypted branch range; the caller must establish
Attributes
| Name | Type | Default/value |
|---|---|---|
requires_relinearization | True | |
input_bound | int | |
double_angle_iterations | int | |
approximator | Any | |
evaluator | Any | |
fuse_input_normalization | bool | False |
retain_ntt | bool | False |
maximum_plaintext_error | float | 0.001 |
seed_shift | float | 0.0 |
polynomial
property
polynomial: PolynomialApproximationFit the low-frequency seed in normalized coordinate
For double_angle_iterations, the returned Chebyshev or power series in z=x+seed_shift approximates
Its coefficient basis is selected by approximator; coefficients use that basis's ascending-degree convention.
approximation_error
property
approximation_error: floatSample
The grid spans normalized
fused_input_divisor
property
fused_input_divisor: floatReturn
required_depths
property
required_depths: intCount normalization, polynomial-evaluation, and recurrence depths.
relinearization_depths
method
def relinearization_depths(*, input_depth: int=0) -> tuple[int, ...] | None: ...Compose normalization, polynomial products and double-angle products.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, *, relinearization_key: RelinearizationKey | EvaluationKeySet | Mapping[int, RelinearizationKey] | None, conjugation_key: ConjugationKey | None=None) -> Ciphertext: ...Evaluate
With non-fused normalization the input represents raw ciphertext.depth + required_depths. Input storage is not mutated or aliased by the result.
reference
method
def reference(values: np.ndarray) -> np.ndarray: ...Evaluate the plaintext oracle on normalized coordinates
values may have any NumPy-broadcastable shape and that shape is preserved. Unlike non-fused evaluate, this method never divides by values / input_bound. The target is