poulpyFully homomorphic encryption
GitHub Get started
Menu

Two routes to bit-granular CKKS.

Compare the representation and its costs before comparing implementations.

For readers familiar with CKKS and polynomial arithmetic · Source guide · 2394fa5

The shared problem

CKKS represents approximate numerical values at a scale. Conventional RNS rescaling removes a modulus prime, coupling scale management to the chosen prime chain. Both Grafting and the bivariate representation address this coupling.

The primary references are Grafting, ePrint 2024/1014 (revision dated 12 June 2026) and Revisiting Key Decomposition Techniques for FHE, ePrint 2023/771 (revision dated 20 September 2024). This page compares their mechanisms; it is not a measured Poulpy-versus-Grafting benchmark.

Two strategies

Grafting retains an RNS coefficient representation. Rational rescaling and reusable modulus factors called sprouts allow more flexible scale and modulus choices while retaining word-size NTT arithmetic. The paper describes how to reuse key-switching material across the supported moduli.

Poulpy represents large coefficients as base-2ᴷ limbs. The limb decomposition supplies the digits used by key switching and separates large-integer representation from polynomial multiplication. Modulus widths and scale adjustments are expressed in bits.

An NTT backend can still use fixed primes for polynomial arithmetic. The application does not select those primes as its ciphertext modulus chain. Backends explains Poulpy’s FFT64, NTT4x30, and NTT3x42 arithmetic families.

Side-by-side

QuestionGraftingPoulpy’s bivariate representation
How are large coefficients represented?RNS residues with additional modulus factorsSigned base-2ᴷ limbs
How is scale decoupled from the modulus chain?Rational rescaling and sproutsBit-granular operations on the limb representation
Where are polynomial transforms chosen?Within the RNS constructionIndependently in an FFT or NTT backend
What happens to key decomposition?Managed within the RNS constructionDigit decomposition is already represented by the limbs
What changes for an implementation?Extends an RNS arithmetic stackRequires a bivariate arithmetic stack and its layout/normalization contracts

Plaintext storage depends on the encoding, precision, and operation. It is not universally one limb in Poulpy, nor should a single expansion factor be assumed for every RNS plaintext implementation.

Cost and limits of the comparison

The bivariate key-switching construction has a linear transform count in the number of limbs. That is a statement about the construction’s transforms, not a linear bound on all arithmetic or a universal runtime advantage over every RNS implementation.

Runtime also includes products, normalization, key preparation, memory traffic, and scheduling. Grafting’s reported improvements use the baselines and parameters in its paper; they are not comparisons against the CKKS workload reported on this website.

A fair implementation comparison needs the same workload, security target, output accuracy, packing, and clearly defined preparation costs. Follow Measure a workload. Source availability belongs to a particular implementation and revision, not to the mathematical technique itself.

Where Poulpy’s choice matters

Reuse the arithmetic setup across circuits. With base-2ᴷ, setup does not fix a circuit’s sequence of rescaling primes. Different circuits can choose their own modulus widths and scale adjustments in bits during evaluation, consuming the budget needed at each stage. This separates setup from circuit evaluation and avoids redesigning a conventional RNS prime chain when the scaling schedule changes.

Parameterize the calculation in bits. Choose the scale needed to represent intermediate values and the modulus width needed to carry the remaining computation. Rescaling amounts can follow those requirements directly. The setup provides the arithmetic capacity; the circuit decides how to use it.

For example, two polynomial evaluations can use different degrees and rescaling schedules with the same arithmetic setup. A shorter evaluation can consume less budget, while a deeper one can use more of the available capacity. Changing the polynomial does not require finding a new sequence of modulus primes to match its scaling schedule.

Reuse is within the setup’s supported parameter bounds and requires the evaluation keys needed by each circuit. It does not imply unlimited depth or that every circuit uses the same rotation or bootstrapping keys. Grafting also loosens conventional RNS constraints, as described above; the contrast is with a fixed rescaling prime chain.

The concrete application interface is bit-granular modulus management; the backend interface separates scheme composition from arithmetic specialization. See Parameters for the choices still required from an application, and Architecture for the reference contract behind backend overrides.