Adds composintscaling* support for SPARSE_ENCAPSULATED (all CKKS bootstrapping flavors), StC-First BT, and CKKS FBT - #1286
Merged
Merged
Conversation
…trapping mode The SlotsToCoeffs-first slot-encoding mode (BTSlotsEncoding = true) now works with COMPOSITESCALINGAUTO/MANUAL. Three issues were fixed in EvalBootstrapStCFirst / EvalBootstrap: - The expected input level counted levels in degree-1 units, while the SlotsToCoeffs matrix is encoded for compositeDegree * (levelBudget + 2) remaining towers, which caused a modulus mismatch for composite scaling. - The level adjustment applied when the input has extra levels mixed up the current and target levels (relative to AdjustLevelsAndDepthInPlace). This is invisible for FLEXIBLEAUTO but capped the composite scaling precision at ~15 bits. - When deg = log2(q0 / 2^p) exceeds the correction factor (allowed for composite scaling), the correction is now clamped to 0 instead of wrapping around (affected both bootstrapping modes, e.g., for composite degree 3 or a small correction factor). Precision of composite scaling is comparable to FLEXIBLEAUTO in this mode (within ~1-3 bits, and typically better at ring dimension 2^14), matching the behavior of the ModRaise-first mode. The composite scaling bootstrapping unit tests now also run the StC-first variant (FULL/EDGE/SPARSE, ITERATIVE, NUM_TOWERS, SERIALIZE), and four CS-vs-FA precision regression tests were added for this mode. Removed stale TODO notes that predate PR #1245. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Composite scaling is handled like the FLEXIBLE* modes (the raised ciphertext is declared to carry the level-specific scaling factor and the ratios to the nominal 2^p are folded into the encoding/decoding matrices), with all tower counts scaled by the composite degree: the modulus of the bottom level and of the output, the levels of the homomorphic encoding/decoding matrices, the modulus raise (via ExtendCiphertext), the rescaling steps, and the level reduction in EvalHomDecoding. SchemeletRLWEMP interprets levels in multiplicative levels for composite scaling. Two precision issues that were invisible for single-prime moduli were fixed along the way: - The ratio between the bottom modulus and the closest power of two (pre) was folded into the matrices although the correction applied after the modulus raise already removes it exactly; for composite moduli (~2^-10 off a power of two) this scaled the mod-raise overflows and cost ~14 bits. It is now applied only in FIXED* modes. - For UNIFORM_TERNARY the division by K_UNIFORM was applied as a tiny scalar (~1/(K*N)) after the modulus raise, whose encoding at the scaling factor loses precision unless the scaling factor is close to a power of two. The division by K is now folded into the CoeffsToSlots matrix for all distributions, which also avoids amplifying the CoeffsToSlots key-switching noise by K. The output noise of composite scaling matches FLEXIBLEAUTO for the same parameters (within ~0.5 bits at ring dimensions 2^12-2^14). Composite scaling also enables scaling factors above 64 bits (e.g., 90 bits). Unit tests: COMPOSITESCALINGAUTO rows 1001-1014 and 1031-1037 (90-bit scaling factor), COMPOSITESCALINGMANUAL rows 1041-1047, and the new FBT_NOISE_VS_FLEXIBLE test type (rows 1021-1024, 1047) comparing the noise with FLEXIBLEAUTO. Documentation updated accordingly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ootstrapping flavors
Sparse secret encapsulation now works with COMPOSITESCALING* in
ModRaise-first bootstrapping, SlotsToCoeffs-first bootstrapping, and
functional bootstrapping.
- The sparse key switching is defined over the bottom basis
Ql = {q_0, ..., q_{d-1}} (d = composite degree): the ciphertext and the
keys are extended from Ql to the auxiliary basis P' and scaled back down
with exact (HPS-style) CRT basis switches over all d limbs (the
single-limb centered lift is kept for d = 1). The Ql-only tables are
shared with the composite scaling modulus raise; only the P'-dependent
tables are new.
- Auxiliary modulus P': ~66 bits for bottom moduli of at most 60 bits
(two 33-bit primes, or three ~22-bit primes when the register word size
is at most 33 bits), and ~127 bits (split into primes fitting the
register word size) for larger bottom moduli of up to 121 bits, where
the Hamming weight of the sparse secret is also increased from 32 to 64.
The primes of the composite cases are searched upwards so that enough
primes exist up to ring dimension 2^17.
- With composite scaling, the sparse-encapsulated case uses the K = 25
approximation of the modular reduction: the existing coefficient tables
in functional bootstrapping and a new degree-44 table
(g_coefficientsSparseAlt) in regular bootstrapping, generated from the
closed form of the Chebyshev coefficients (Bessel functions).
- The modulus raise of the three bootstrapping flavors is factored into
ModRaiseInPlace. GetFBTDepth/AdjustDepthFBT take an optional composite
degree to select the same approximation tables.
Unit tests: composite scaling bootstrapping with SPARSE_ENCAPSULATED for
composite degrees 2 and 3 (66- and 127-bit auxiliary moduli), a key
switching test over the composite bottom basis, functional bootstrapping
rows with SPARSE_ENCAPSULATED (including 90-bit scaling factors and
COMPOSITESCALINGMANUAL), and the largest scaling factors: 119 bits with a
120-bit first modulus (register word size 64) and 120 bits with a 121-bit
first modulus (register word size 32). The noise comparison with
FLEXIBLEAUTO in the functional bootstrapping tests uses the maximum over
three runs to be robust to the key-dependent approximation error.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was
linked to
issues
Aug 28, 2026
…E_SIZE=128) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 119/120-bit scaling factor rows (and the deeper 90-bit functional bootstrapping rows) need modulus chains beyond the fixed 3500-bit width of the MATHBACKEND 2 multiprecision integers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pascoec
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR completes the composite scaling (
COMPOSITESCALINGAUTO/COMPOSITESCALINGMANUAL) support for CKKS bootstrapping. It adds composite scaling to the two bootstrapping flavors that did not support it yet — the SlotsToCoeffs-first slot-encoding mode and functional bootstrapping (EvalFBT) — and enables theSPARSE_ENCAPSULATEDsecret key distribution with composite scaling for all three flavors (ModRaise-first, SlotsToCoeffs-first, and functional bootstrapping). In all cases the precision/noise of composite scaling is on par withFLEXIBLEAUTOfor the same parameters, and composite scaling now also enables functional bootstrapping with scaling factors above 64 bits (up to the 120-bit maximum of composite scaling).Fixes #1267.
Changes
1.
COMPOSITESCALING*for the SlotsToCoeffs-first bootstrapping mode (BTSlotsEncoding = true)The setup side and the post-ModRaise code were already composite-aware; the mode was disabled because of three issues in
EvalBootstrapStCFirst:compositeDegree * (levelBudget + 2)remaining towers (modulus mismatch for composite scaling).AdjustLevelsAndDepthInPlace). This is invisible forFLEXIBLEAUTO(its per-level scaling factors agree to ~2^-30) but capped composite scaling at ~15 bits.deg = log2(q0 / 2^p)exceeds the correction factor (allowed for composite scaling), the correction wrapped around (unsigned subtraction); it is now clamped to 0 in both bootstrapping variants (e.g., composite degree 3, or a small correction factor).The StC-first variant is now enabled for all composite scaling bootstrapping unit tests (FULL/EDGE/SPARSE, ITERATIVE, NUM_TOWERS, SERIALIZE), and four
StCFirst*precision regression tests (CS vs FA) were added toUnitTestCKKSrnsCompositeScalingVsFlexible.cpp.2.
COMPOSITESCALING*for CKKS functional bootstrappingComposite scaling is handled like the
FLEXIBLE*modes (the raised ciphertext is declared to carry the level-specific scaling factor and the ratios to the nominal 2^p are folded into the encoding/decoding matrices), with all tower counts scaled by the composite degree: the moduli of the bottom level and of the output, the levels of the homomorphic encoding/decoding matrices, the modulus raise (viaExtendCiphertext), the rescaling steps, and the level reduction inEvalHomDecoding.SchemeletRLWEMPinterprets levels in multiplicative levels for composite scaling.Two precision issues that were invisible for single-prime moduli were fixed along the way:
pre) was folded into the matrices although the correction applied after the modulus raise already removes it exactly. For composite moduli (~2^-10 off a power of two) this scaled the mod-raise overflows and cost ~14 bits. It is now applied only in theFIXED*modes.UNIFORM_TERNARY, the division byK_UNIFORMwas applied as a tiny scalar (~1/(K·N)) after the modulus raise, whose encoding at the scaling factor loses precision unless the scaling factor is close to a power of two. The division by K is now folded into the CoeffsToSlots matrix for all distributions, which also avoids amplifying the CoeffsToSlots key-switching noise by K.Note that the parameter generation for composite scaling requires
firstModSize > scalingModSize, so in these modes the first modulus has to be at least one bit larger than the scaling factor (whose bit length matches the RLWE ciphertext modulus).3.
SPARSE_ENCAPSULATEDwith composite scaling (all bootstrapping flavors)Ql = {q_0, ..., q_{d-1}}(d= composite degree): the ciphertext and the keys are extended fromQlto the auxiliary basisP'and scaled back down with exact (HPS-style) CRT basis switches over alldlimbs (the single-limb centered lift is kept ford = 1). TheQl-only tables are shared with the composite scaling modulus raise; only theP'-dependent tables are new.P': ~66 bits for bottom moduli of at most 60 bits (two 33-bit primes, or three ~22-bit primes when the register word size is at most 33 bits), and ~127 bits (split into primes fitting the register word size) for larger bottom moduli of up to 121 bits, where the Hamming weight of the sparse secret is also increased from 32 to 64. The primes of the composite cases are searched upwards so that enough primes exist up to ring dimension 2^17 (verified).g_coefficientsSparseAlt) in regular bootstrapping, generated from the closed form of the Chebyshev coefficients (Bessel functions).GetFBTDepth/AdjustDepthFBTtake an optional composite degree to select the same tables.ModRaiseInPlace.Precision
Composite scaling vs
FLEXIBLEAUTOfor the same parameters (UNIFORM_TERNARY, 59/60-bit moduli, noise/precision in bits):FLEXIBLEAUTOin most configurations at rings 2^13/2^14 (e.g., 2^14: 8 slots +2.4, 1024 slots +1.5, full packing +1.2).Tests
UnitTestCKKSrnsCompositeScalingBootstrap.cpp: StC-first variants for all test types;SPARSE_ENCAPSULATEDrows for composite degrees 2 and 3 (66- and 127-bit auxiliary moduli); aKeySwitchSparseround-trip test over the composite bottom basis; the largest scaling factors (119 bits with a 120-bit first modulus at register word size 64, and 120 bits with a 121-bit first modulus at register word size 32).UnitTestCKKSrnsCompositeScalingVsFlexible.cpp: four StC-first CS-vs-FA regression tests.UnitTestFBT.cpp:COMPOSITESCALINGAUTOrows (LUTs, sign digit, consecutive levels, MVB, multi-limb initial scaling, 90-bit scaling factors),COMPOSITESCALINGMANUALrows,SPARSE_ENCAPSULATED+ composite rows, the largest scaling factors, and a newFBT_NOISE_VS_FLEXIBLEtest type asserting that the composite scaling noise is within 3 bits ofFLEXIBLEAUTO(maximum over three runs, for robustness against the key-dependent approximation error).The full PKE unit test suite passes (2029 tests).
Documentation
COMPOSITE_SCALING.mdandCKKS_FUNCTIONAL_BOOTSTRAPING.mddescribe the supported modes, the first-modulus requirement, the auxiliary modulus rules of sparse encapsulation, and the support of scaling factors above 64 bits; the functional bootstrapping example comments were updated accordingly.🤖 Generated with Claude Code