← HomOps Reference
HomSumSlots
Sum across the slots inside a ciphertext.
SsSlots
RunsServer
Changes shapeYes, by default
Changes scaleNo
Levels spent0
RotatesYes - stage plan via
stage_sizesKeysRotation key
What it does
HomSumSlots sums values along the slot axis. It uses rotations and additions, and it spends no levels. Use it when the sum is the slot axis. HomAxisSum sums a normal tensor axis and cannot do this.nb_cols is how many sums you want. The default is 1: one sum of the whole period. The period is split into that many columns. Each sum adds the slots in one column. stage_sizes must multiply to n_slots / nb_cols, the number of slots in a column.Zero padding is allowed. Padded slots are zero, so they do not change the sums.
reduce_output is true by default. The slot axis shrinks to the nb_cols sums. Set it to false to keep the input length. Each sum is then repeated every nb_cols slots. A slot axis that spans more than one ring needs false, because those rings do not hold the same sums.HomMatMul runs one internally when it multiplies over the n axis. Stage plans are on Slots, rotations & stages.
Signature
HomSumSlots( nb_cols=None, stage_sizes=None, reduce_output=True, )
No
set_data.Parameters
ParameterTypeDefaultDescription
nb_colsint | NoneNoneNumber of sums. None means 1, one sum of the period. Must be a power of two that divides n_slots.stage_sizessequenceNoneThe stage plan. Unset means (2,) × log₂(n_slots / nb_cols).reduce_outputboolTrueWhen true, the slot axis holds only the nb_cols sums. When false, the axis keeps the input length and the sums repeat every nb_cols slots.Rules that depend on the value
SettingRuleIf you break it
stage_sizesThe entries must multiply to the column length: prod(stage_sizes) == n_slots / nb_cols. When nb_cols is omitted, that product must equal n_slots.Compilation fails.stage_sizes unsetThe default plan only exists when n_slots / nb_cols is a power of two.Write the plan yourself.reduce_output=TrueThe slot axis must fit in one ring.Compilation fails. Use reduce_output=False when the slot axis spans more than one ring.Requirements
- Rotation key entries. Every rotation offset in the stage plan must be present in the evaluation key. The compiler derives the exact set; you don't list them yourself.
These surface as compilation errors; see Compilation errors.
Shape effect: yes, by default
With
reduce_output=True, the slot axis becomes nb_cols long. With reduce_output=False, the tensor shape stays the same and n_slots becomes nb_cols.Scale effect - no
Rotations and additions only; the scale carries through unchanged.
Stages & rotations
The general rules live on Slots, rotations & stages; here is how they apply to
HomSumSlots:QuestionAnswer for HomSumSlots
Span the plan must cover
n_slots / nb_cols. The default nb_cols is 1, so the span is the whole period.Default plan
(2,) × log₂(n_slots / nb_cols), when that length is a power of two.Plan constraint
prod(stage_sizes) == n_slots / nb_colsDistinct rotation offsets
Σ (entry − 1) over the plan. Sets the rotation key size.Rounds
len(stage_sizes). Fewer rounds means a faster query.Levels spent0, always. No mod-switch runs inside, so there is no
stages_per_level here.Since levels are never at stake, the plan is a pure speed-versus-key-size trade:
plans.pyPYTHON
# Default: nb_cols = 1, one sum of the period HomSumSlots() # 4 sums. The plan covers n_slots / nb_cols slots. HomSumSlots(nb_cols=4, stage_sizes=[2, 4]) # 2 * 4 = n_slots / 4
Level budget
Zero. The tree is rotations and additions; no prime is ever dropped, whatever the plan.
Keys
Rotation key. Every offset in the stage plan needs an entry in the rotation key, derived at compile time from the plan and generated for you during key generation. Wider stages mean more offsets and a bigger key. No square key.
Example
Standalone slot sum
32 slots as 4 columns. The default
reduce_output returns 4 sums:pipeline.pyPYTHON
from lattica_build.operators import HomSumSlots from lattica_build.base_classes.hom_pipeline import HomomorphicPipeline from lattica_build.operators.composite.sequential import SequentialHomOp pipeline = HomomorphicPipeline( hom=SequentialHomOp( HomSumSlots(nb_cols=4, stage_sizes=[2, 4]), # n_slots = 32; 2 * 4 = 8 ), input_shape=(32,), )
Inside HomMatMul
You don't write this one; when HomMatMul multiplies over the n axis, it runs a
HomSumSlots with defaults to do its summation. The rotation key entries it needs are derived along with everything else at compile time.See also
- HomAxisSum - sum a tensor axis; cannot reduce the n axis
- HomRotateSum - rotate-and-add primitive behind slot-sum stages
- HomRunningSum - keep the prefixes instead of one total
- HomMatMul - the main consumer of this operator
- Slots, rotations & stages - stage plans, offsets, and the key-size trade
- Bootstrap - refresh when the level budget runs out