Tutorials
First evaluator
This program encrypts two vectors, evaluates addition and multiplication, and decrypts the results.
import torch
import fhelium as fh
engine = fh.CkksEngine(fh.Preset.slots8192_scale40_levels7_int64, device="cpu")
x = torch.linspace(-0.05, 0.05, 32, dtype=torch.float64)
y = torch.linspace(0.02, -0.02, 32, dtype=torch.float64)
ct_x = engine.encrypt_message(x)
ct_y = engine.encrypt_message(y)
# Addition preserves level and scale.
ct_sum = engine.add(ct_x, ct_y)
# Multiplication exposes representation conversion, relinearization, and a
# post-product rescale.
x_ntt = engine.coefficient_domain_to_ntt_domain(ct_x)
y_ntt = engine.coefficient_domain_to_ntt_domain(ct_y)
triplet = engine.multiply(x_ntt, y_ntt)
ct_product = engine.rescale_to_next_level(engine.relinearize(triplet))
sum_clear = engine.decrypt_message(ct_sum, is_real=True)[: x.numel()]
product_clear = engine.decrypt_message(ct_product, is_real=True)[: x.numel()]
torch.testing.assert_close(sum_clear, x + y, atol=2e-5, rtol=0)
torch.testing.assert_close(product_clear, x * y, atol=2e-5, rtol=0)2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
The separate operations are intentional:
- in this example, fresh ciphertexts use
engine.config.default_scaleas their initial actual scale ; coefficient_domain_to_ntt_domainenters NTT/Montgomery representation;multiplyaccepts two two-component NTT ciphertexts and returns a three-component NTT ciphertext;relinearizereturns the ordinary two-component form, andrescale_to_next_levelthen consumes one Q prime and records the product scale divided by that prime.
See Scale and level lifecycle for the exact level/scale laws, Evaluator operation transitions for the broader state machine, and CkksEngine for the generated method reference. The same program runs with device="cuda:0" when the native build includes CUDA; see Choose and switch a local execution device. Before optimizing or deploying this evaluator, continue with Screen NTT backends to compare the implementations compatible with the target device and preset.
Choose a tutorial
Each tutorial follows one maintained numbered file under examples/. Choose a track by goal; the numbers preserve the source mapping and do not impose one mandatory reading order.
CKKS
| Example | Tutorial | Main question |
|---|---|---|
| 01 | Basic CKKS workflow | How do encryption, three-component multiplication state, rotation, and decryption fit together? |
| 02 | Key material lifecycle | What state does each key store, and which cryptographic relations remain application-owned? |
| 04 | Modulus-chain depth | How do the level-transition budget, configured chain depth, security budget, and ciphertext size relate? |
| 05 | Explicit scale management | How does a program track the actual dropped prime and keep level alignment separate from scale policy? |
| 06 | Late relinearization and NTT reuse | When can products remain three-component and operands remain in NTT form? |
Performance
| Example | Tutorial | Main question |
|---|---|---|
| 07 | Rotation hoisting | When does a grouped rotation request avoid repeated decomposition work? |
Distributed execution
| Example | Tutorial | Main question |
|---|---|---|
| 08 | Independent ciphertexts | When should SPMD code scatter and gather independent encrypted values? |
| 09 | Rotation-parallel matrix-vector | How are additive diagonal terms and exact rotation keys partitioned across processes? |
| 10 | Limb-parallel pipeline | Which operations are RNS-row local, and where must every expected active row be reconstructed? |
Execution and lifecycle
| Example | Tutorial | Main question |
|---|---|---|
| 03 | Values, memory, and persistence | How do device movement, exact value files, and artifact policy differ? |
| 11 | CUDA Graph matrix-vector | How are static keys and weights separated from changing request ciphertexts? |
| 12 | Reusable value buffers | How can pinned-host tiles stream through two fixed CUDA allocations? |
| 13 | Explicit residency plans and CUDA leases | How do opaque handles, lazy local locations, optional budgets, scoped reservations, and event-backed CUDA leases compose? |
| 14 | Automatic residency admission | How does an exact working-set request become a deterministic, inspectable, state-bound admission decision under managed pressure? |
| 15 | Homogeneous batching | How does a leading message batch compare with an explicit loop? |
| 16 | Compressed plaintexts | When can an operation-ready plaintext use the versioned compressed encoded-axis layout? |
Features
Read the bootstrapping composition and range requirements or the multiparty supported security scope before the corresponding workflow.
| Example | Tutorial | Main question |
|---|---|---|
| 17 | Refresh with composable CKKS bootstrapping | How are approximation, polynomial evaluation, transforms, periodic reduction, keys, and range evidence composed? |
| 18 | Multiparty CKKS | How do stateless collective-key and unsafe output arithmetic phases fit together under application-owned protocol state? |
| 19 | JIT programs | How do PyTorch tracing, a mixed-dialect Program, selected passes, a retained workspace, readiness, and encrypted execution compose? |
| 20 | Import and execute JIT textual IR | How can versioned textual IR preserve an application operation and execute it through a bound handler? |
| 21 | Compose a custom JIT pipeline | How does a custom pass publish retained workspace analysis inside an inspectable pipeline? |
Static documentation build
The site build does not run native workloads. CPU and CUDA validation exercise applicable examples separately from VitePress generation.
Use Concepts for the underlying invariants, How-to guides for focused tasks, and the API reference for exact signatures.