fhelium.experimental.bootstrap.linear.evaluators
Direct and baby-step/giant-step execution of diagonal linear maps.
DirectDiagonalEvaluator
class View source
DirectDiagonalEvaluator()Evaluate each cyclic diagonal independently, then rescale once.
For every nonzero offset this strategy rotates the input, multiplies it by the corresponding encoded diagonal, and adds the product to an accumulator. All products have pending scale
The input is a two-component coefficient-domain standard-RNS Q ciphertext with data axes [component, *batch, limb, coefficient], ring extent prime_ids tuple. If the removed Q group has product
and Q prime_ids with the complete group removed. The output remains in coefficient domain with standard residues; temporary diagonal plaintexts are NTT-domain Montgomery RNS. The result does not alias an input.
required_depths
method
def required_depths(transform: Any) -> int: ...Return the single rescale consumed by one diagonal stage.
required_rotation_offsets
method
def required_rotation_offsets(transform: Any) -> tuple[int, ...]: ...Return direct non-zero diagonal offsets.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, transform: Any, *, rotation_keys: RotationKeySet, rotate: Callable[[Ciphertext, int], Ciphertext], encode_diagonal: Callable[..., Plaintext]) -> Ciphertext: ...Apply
The input must match the engine's slot count. For offset zero the input is reused directly; every other term requests one rotation through the supplied rotation-key strategy. Each diagonal is encoded at the input depth, multiplied into its rotated ciphertext, and accumulated at pending scale. A single final rescale advances the output by one depth.
Raises
TypeError: Iftransformuses another stage representation.ValueError: If slot count or diagonal content is invalid.
DiagonalBSGSEvaluator
class View source
DiagonalBSGSEvaluator(baby_step: int, hoist_baby_rotations: bool = True, aggregate_groups: bool = False, baby_steps_by_transform: Mapping[str, int] | None = None)Evaluate the same diagonal map with a BSGS rotation schedule.
An offset baby_step. Baby rotations of the input are shared across giant groups. Each group's diagonals are shifted to compensate for the final giant rotation, its plaintext products are accumulated and rescaled, and then the group result is giant-rotated into place.
Algebraically, each term is unchanged because
Thus direct and BSGS evaluators implement the same map and depth/scale/state transition; different grouping and CKKS rounding need not produce bit-identical residues. hoist_baby_rotations uses engine.rotate_many_with_keys only when direct baby-step keys are available. Compact power-of-two inventories compose rotations through the private key-aware evaluation helper. baby_steps_by_transform may override the fallback step for named compiled transforms, keeping a stage-specific BSGS schedule inspectable without changing the transform representation. aggregate_groups applies all giant-group plaintext rows to the shared baby ciphertexts in one represented RNS operation; it changes execution grouping but not the BSGS partition or arithmetic.
Attributes
| Name | Type | Default/value |
|---|---|---|
baby_step | int | |
hoist_baby_rotations | bool | True |
aggregate_groups | bool | False |
baby_steps_by_transform | Mapping[str, int] | None | None |
required_depths
method
def required_depths(transform: Any) -> int: ...Return the single rescale consumed by one BSGS stage.
baby_step_for
method
def baby_step_for(transform: DiagonalLinearTransform) -> int: ...Return the caller-selected BSGS step for one compiled transform.
required_rotation_offsets
method
def required_rotation_offsets(transform: Any) -> tuple[int, ...]: ...Return the union of nonzero baby and giant rotations.
evaluate
method
def evaluate(arithmetic: BootstrapArithmetic, ciphertext: Ciphertext, transform: Any, *, rotation_keys: RotationKeySet, rotate: Callable[[Ciphertext, int], Ciphertext], encode_diagonal: Callable[..., Plaintext]) -> Ciphertext: ...Execute shared baby rotations, group sums, and giant rotations.
Each giant-group accumulator is rescaled before its giant rotation, so all group results have common depth and actual scale
Here Delta_p is the selected diagonal plaintext scale and M_d is the dropped Q-group product.
The input and output tensor/state requirements are identical to DirectDiagonalEvaluator; evaluation is functional.