Skip to main content

HomOps Reference

HomPolyEvalBase

Evaluate Chebyshev coefficients on an encrypted value.

PbPolynomials
RunsServer
Changes shapeYes - when coefficients carry batch dims
Changes scaleYes - grows through the evaluation
Levels spentSeveral - grows with the degree
RotatesNo
KeysSquare key

What it does

HomPolyEvalBase evaluates a Chebyshev polynomial on every element of a ciphertext. Low degrees run a direct recurrence; higher degrees use a Paterson–Stockmeyer schedule so a degree-d polynomial costs far fewer multiplications than d, but it is still one of the deepest operators in the set.
This is the registered Chebyshev leaf behind the PolyEval family. Reach for it when you already have coefficients, or when you are wiring a building block used by higher-level helpers:
ClassRole
HomPolyEvalFit Chebyshev coefficients to a Python func of a given degree
HomPolyIndicatorPacked bin indicators
HomPolyThresholdStep / Heaviside approximations
HomSignSign approximation built from nested poly stages
Prefer those helpers when they match the curve you need. Use HomPolyEvalBase directly when the coefficients are already computed, or when you need an explicit domain remap from [left, right] onto [-1, 1] before evaluation.

Signature

HomPolyEvalBase(
    coefs,              # required: Chebyshev coeffs; last axis = degree + 1
    left=-1,
    right=1,
    tol=1e-8,
    rows_budget=None,
)
No set_data; the coefficients are fixed at construction. The last axis of coefs is degree + 1.

Parameters

ParameterTypeDefaultDescription
coefstensorrequiredChebyshev coefficients with shape [..., deg+1]. Leading dims are batch dims prepended to the output shape.
left, rightint-1, 1The input domain. Inputs are remapped from [left, right] to the Chebyshev domain [-1, 1] before evaluation.
tolfloat1e-8Internal rescales whose factor is within tol of 1 are skipped, saving a multiply.
rows_budgetsequenceNoneRestricts which levels the internal mod-switches may spend, by absolute row index. See rows_budget.
Rules that depend on the value
SettingRuleIf you break it
left, rightThe actual input values must lie inside [left, right]. The polynomial is only a valid approximation on its domain; values outside it produce garbage, silently.Wrong results, not an error. Check the range your previous ops can produce.
left, rightA domain other than [-1, 1] adds an affine remap before evaluation, which can cost one extra mod-switch plus scalar mul/add.-
degreeDegree ≤ 4 uses direct Chebyshev evaluation (levels ≈ deg - 1). Degree > 4 uses Paterson–Stockmeyer; levels grow with the optimal baby-step / giant-step split.-
rows_budgetAt least one listed row must be droppable at each internal mod-switch.Compilation fails if none are eligible.

Requirements

  • Input in domain. Whatever arrives must fit in [left, right]. This is a numerical requirement the compiler cannot check for you.
  • Square key. The internal Chebyshev multiplies are ciphertext multiplies; any pipeline with a HomPolyEvalBase needs the square key (generated for you during key generation).
  • Level headroom. Plan several levels for high degree and verify with the compile-time simulation; see Level budget.

Shape effect - yes when coefs are batched

Rule: output_shape = coef_batch_shape + input.tensor_shape.
Scalar coefficients leave the shape unchanged. Packed indicator-style coefficients prepend their batch dims, for example num_bins channels from HomPolyIndicator.

Scale effect - yes

Scale grows through the Chebyshev multiplies and is paid down by internal mod-switches as evaluation proceeds. The backend often restores toward the input scale (or an internal target) via packed mul/add. You don't manage this step by step. Check the compiled result: the pipeline's compile-time simulation reports the output scale, and that is the number to plan the next operator around.
How scale moves through a pipeline is on Ciphertext state - Scale.

Level budget

HomPolyEvalBase spends levels at several points inside:
PhaseLevels
Domain remap to [-1, 1]0 or 1, only when [left, right] is not [-1, 1] and the remap factor is not near 1
Direct evaluation (degree ≤ 4)About degree - 1
Paterson–Stockmeyer (degree > 4)Several; grows with the optimal baby-step / giant-step split for the degree
The exact count for a given degree is settled at compile time; verify it with the compile-time simulation rather than estimating by hand. Optionally pin drops with rows_budget.
How primes are organized in the chain is explained on Level budget - The chain.

Keys

Square key (relinearization key). The Chebyshev evaluation multiplies ciphertexts by ciphertexts, so every multiply is followed by a relinearization. Generated for you during key generation. No rotation key (unless a nested composite around this leaf adds rotations).

Example

Bring your own Chebyshev coefficients:
pipeline.pyPYTHON
import torch
from lattica_build.operators import HomPolyEvalBase
from lattica_build.base_classes.hom_pipeline import HomomorphicPipeline
from lattica_build.operators.composite.sequential import SequentialHomOp

coefs = torch.tensor([0.0, 1.0, 0.0, -0.1])  # degree 3

pipeline = HomomorphicPipeline(
    hom=SequentialHomOp(
        HomPolyEvalBase(coefs=coefs, left=-1, right=1, rows_budget=[3]),
    ),
    input_shape=(128,),
)
When you want to fit a callable instead of supplying coefficients, prefer HomPolyEval.

See also