fhelium.engine.rns.runtime
RnsRuntime
class View source
RnsRuntime(ckks_config: CkksConfig, device: str | torch.device | None=None, ntt_backend: str | None=None)Own one engine's dense RNS parameters and representation transitions.
Unless a method states otherwise, an RNS operand is an integral tensor with shape [*batch, limb, coefficient_or_ntt_index] and final extent j represents the modulus whose canonical parameter id is prime_ids[j]. Public full-basis calls derive those ids from level and internal calls supply parameter_row_start for an exact contiguous row interval. include_p is only this internal row selector; it is not public modulus_basis metadata.
Functional methods allocate non-aliasing output. A trailing underscore mutates the operand and preserves its storage. Standard and Montgomery conversions do not change polynomial domain. Forward NTT maps coefficient index to NTT index and inverse NTT maps it back, independently for every batch item and prime row.
rns_basis_level_count
property
rns_basis_level_count: intNumber of RNS row-suffix levels, including private structural levels.
rns_parameters_for
method
def rns_parameters_for(tensor: torch.Tensor, *, include_p: bool=False, rns_dimension: int=-2, parameter_row_start: int | None=None) -> torch.Tensor: ...Return [parameter, limb] parameters aligned with an RNS operand.
The result is a zero-copy CUDA view with the engine integral dtype. Column j describes tensor[..., j, :] exactly; this method does not mutate or alias the operand itself.
rns_parameters_for_prime_ids
method
def rns_parameters_for_prime_ids(prime_ids: tuple[int, ...]) -> torch.Tensor: ...Return a zero-copy parameter view for canonical local RNS rows.
row_parameters
method
def row_parameters(key) -> RnsRowParameters: ...Return immutable host/device parameters for exact prime_ids.
basis_parameters
method
def basis_parameters(level: int, *, include_p: bool=False) -> RnsRowParameters: ...Return parameters for the exact Q or QP rows active at level.
twice_modulus_for_basis
method
def twice_modulus_for_basis(level: int, *, include_p: bool=False) -> torch.Tensor: ...Return integral row vector
moduli_for_basis
method
def moduli_for_basis(level: int, *, include_p: bool=False) -> list[int]: ...Return host integers in the active basis's exact prime_ids order.
to_montgomery_
method
def to_montgomery_(a: torch.Tensor, *, include_p: bool=False) -> None: ...Replace each standard residue
a is coefficient- or NTT-domain [*batch, limb, N] in the lazy interval
montgomery_mul_row_scalars_
method
def montgomery_mul_row_scalars_(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False) -> None: ...Mutate a[..., i, :] to
b has shape [limb] and is aligned with the same exact prime rows. Both inputs use one integral dtype and Montgomery form; polynomial domain is preserved and the result is lazy in
montgomery_mul_row_scalars_canonical
method
def montgomery_mul_row_scalars_canonical(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False) -> torch.Tensor: ...Return canonical
a is integral [*batch, limb, index] and b is the aligned Montgomery [limb] scalar vector for the same exact prime rows. Polynomial domain is preserved. Output has canonical Montgomery residues in
montgomery_mul
method
def montgomery_mul(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Return
Operands have equal [*batch, limb, N] layouts, integral dtype, exact prime-row mapping, polynomial domain, and Montgomery form. The output has the same state, is lazy in
montgomery_mul_cyclic_compressed
method
def montgomery_mul_cyclic_compressed(a: torch.Tensor, compressed_b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Multiply by a cyclically repeated compact Montgomery operand.
a is integral [*batch, limb, N] and compressed_b is [*compressed_batch, limb, unique_index] on the same device, domain, exact prime rows, and Montgomery form. The compact final axis repeats cyclically to extent
montgomery_mul_contiguous_compressed
method
def montgomery_mul_contiguous_compressed(a: torch.Tensor, compressed_b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Multiply by a block-repeated compact Montgomery operand.
Tensor state and broadcasting match montgomery_mul_cyclic_compressed, but each compact value is repeated in one contiguous block along the expanded extent-
from_montgomery_
method
def from_montgomery_(a: torch.Tensor, *, include_p: bool=False) -> None: ...Replace
Shape, integral dtype, exact prime rows, polynomial domain, and storage are preserved. The output is lazy in
canonicalize_residues_
method
def canonicalize_residues_(a: torch.Tensor, *, include_p: bool=False) -> None: ...Reduce lazy
Axes, integral dtype, prime rows, polynomial domain, residue representation, and storage are unchanged.
center_residues_
method
def center_residues_(a: torch.Tensor, *, include_p: bool=False) -> None: ...Map canonical residues to centered representatives in place.
Per prime row,
shift_residues_positive_
method
def shift_residues_positive_(a: torch.Tensor, *, include_p: bool=False) -> None: ...Add
This storage-preserving operation consumes the centered interval
add_lazy
method
def add_lazy(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Return
Equal-shape integral operands use the same domain, representation, and exact prime rows and lie in
sub_lazy
method
def sub_lazy(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False) -> torch.Tensor: ...Return
lift_centered_coefficients
method
def lift_centered_coefficients(a: torch.Tensor, level: int=0, *, include_p: bool=False) -> torch.Tensor: ...Lift [*batch, coefficient] integers into coefficient RNS.
The input is an integral tensor of final extent [*batch, limb, coefficient] in standard representation with limb order rns_layout.prime_ids(level, include_p=include_p) and lazy range a.
lift_integer_coefficients_exact
method
def lift_integer_coefficients_exact(coefficients: torch.Tensor, level: int=0, *, include_p: bool=False, max_abs: int | None=None) -> torch.Tensor: ...Lift signed compact coefficients without a one-prime assumption.
For row
add_canonical
method
def add_canonical(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Return
Equal-shape integral operands have layout [*batch, limb, coefficient_or_ntt_index], identical domain and residue representation, and the same exact prime rows. Output preserves that state and aliases neither input.
add_canonical_
method
def add_canonical_(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> None: ...Replace a by
The tensor layout and state requirements match add_canonical; a storage is mutated in place, while b is read-only.
sub_canonical
method
def sub_canonical(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> torch.Tensor: ...Return
Equal-shape integral operands have layout [*batch, limb, coefficient_or_ntt_index], identical domain and residue representation, and the same exact prime rows. Output preserves that state and aliases neither input.
sub_canonical_
method
def sub_canonical_(a: torch.Tensor, b: torch.Tensor, *, include_p: bool=False, prime_ids: tuple[int, ...] | None=None) -> None: ...Replace a by
The tensor layout and state requirements match sub_canonical; a storage is mutated in place, while b is read-only.
forward_montgomery_
method
def forward_montgomery_(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Apply the negacyclic forward NTT to Montgomery residues in place.
a maps from [*batch, limb, coefficient] to the same storage viewed as [*batch, limb, ntt_index]. For row
forward_to_montgomery_
method
def forward_to_montgomery_(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Apply forward NTT and standard-to-Montgomery conversion in place.
The state transition is coefficient + standard to ntt + montgomery on unchanged [*batch, limb, N] integral storage and exact prime rows; output is lazy in
forward_to_montgomery
method
def forward_to_montgomery(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> torch.Tensor: ...Return the non-aliasing forward NTT/Montgomery transition.
inverse_montgomery_
method
def inverse_montgomery_(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Apply normalized inverse NTT while retaining Montgomery form.
Per prime row normalization multiplies by
inverse_to_standard_lazy_
method
def inverse_to_standard_lazy_(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Inverse NTT to coefficient/standard lazy
inverse_to_standard_
method
def inverse_to_standard_(a: torch.Tensor, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Inverse NTT to canonical coefficient/standard
inverse_to_centered_
method
def inverse_to_centered_(a, *, include_p: bool=False, parameter_row_start: int | None=None) -> None: ...Inverse NTT to centered coefficient/standard residues in place.