|
| 1 | +# dyadic — Six-Axiom 2-Adic Operator Calculus |
| 2 | + |
| 3 | +Single-header C++20 library for arithmetic in ℤ₂[[t]]: carry chains, formal derivatives, forward differences, Witt vectors, basis conversions, power series composition and reversion. |
| 4 | + |
| 5 | +```cpp |
| 6 | +#include "dyadic.h" |
| 7 | +#include <cstdio> |
| 8 | +using namespace dyadic; |
| 9 | + |
| 10 | +int main() { |
| 11 | + Polynomial<4, uint64_t> p{{1, 2, 3, 4}}; |
| 12 | + |
| 13 | + // Formal derivative: D(P)(t) = dP/dt |
| 14 | + auto dp = formal_derivative(p); // {2, 6, 12, 0} |
| 15 | + for (auto c : dp) std::printf("%lu ", c); |
| 16 | + |
| 17 | + // Forward difference: Δ(P)(t) = P(t+1) − P(t) |
| 18 | + auto fp = forward_difference(p); // {9, 18, 12, 0} |
| 19 | + |
| 20 | + // Basis conversions (exact roundtrip) |
| 21 | + auto ff = change_basis<FallingFactorialBasis>(p); |
| 22 | + auto back = change_basis<MonomialBasis>(ff); // == p |
| 23 | + |
| 24 | + // Evaluate P(5) = 1 + 2·5 + 3·25 + 4·125 = 586 |
| 25 | + auto y = p.eval(5); |
| 26 | + |
| 27 | + // Witt vector ring operations |
| 28 | + WittVector<3, uint64_t> a{{1, 2, 3}}, b{{4, 5, 6}}; |
| 29 | + auto sum = a + b; // Witt addition (via ghost map) |
| 30 | + auto prod = a * b; // Witt multiplication |
| 31 | + |
| 32 | + // Power series reversion (Lagrange inversion) |
| 33 | + Polynomial<6, uint64_t> P{{0, 1, 1}}; // t + t² |
| 34 | + auto Q = reversion(P); |
| 35 | + // Q = t − t² + 2t³ − 5t⁴ + 14t⁵ − 42t⁶ + … |
| 36 | + // (stored as unsigned ℤ₂ values: −1 ≡ 2⁶⁴−1, etc.) |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +## Requirements |
| 41 | + |
| 42 | +- **C++20** compiler (GCC 12+, Clang 17+, MSVC 2022+) |
| 43 | +- No external dependencies |
| 44 | +- `detail::uint128_t` (software 128-bit pair) provides `uint64_t` word support without `unsigned __int128` |
| 45 | +- Clang needs `-fconstexpr-steps=50000000` for compile-time proofs; GCC needs `-fconstexpr-ops-limit=200000000` |
| 46 | + |
| 47 | +## Features |
| 48 | + |
| 49 | +| Area | What | |
| 50 | +|------|------| |
| 51 | +| **2-Adic Primitives** | `v2` (valuation), `modinv_odd`, `div_2k_adic`, `artin_schreier` (℘(x)=x²−x) | |
| 52 | +| **Polynomials** | `Polynomial<N,W,Basis>` with `eval`, `+`, `−`, `*`, basis conversion between Monomial / FallingFactorial / Taylor | |
| 53 | +| **Calculus** | `formal_derivative` (D), `forward_difference` (Δ), `taylor_shift`, `indefinite_sum` (Σ = Δ⁻¹) | |
| 54 | +| **Witt Vectors** | `WittVector<N,W>` with ghost map, Frobenius, Verschiebung, `+`, `*`, `adams_operation`, `teichmuller_lift` | |
| 55 | +| **Carry Chain** | Full-width carry propagation `C = (I−N)⁻¹` — converges in one pass | |
| 56 | +| **Compose / Reversion** | Power series composition P(Q(t)) and Lagrange inversion | |
| 57 | +| **Compile-Time Proofs** | 20+ `static_assert` proofs verifying ring axioms, basis roundtrips, D∘Δ=Δ∘D, ghost homomorphism, carry idempotence (see `dyadic_verify.h`) | |
| 58 | + |
| 59 | +## More Examples |
| 60 | + |
| 61 | +### Witt vector ring |
| 62 | + |
| 63 | +```cpp |
| 64 | +WittVector<3, uint64_t> a{{1, 2, 3}}, b{{4, 5, 6}}; |
| 65 | + |
| 66 | +auto sum = a + b; |
| 67 | +auto prod = a * b; |
| 68 | + |
| 69 | +// Frobenius and Verschiebung |
| 70 | +auto fa = a.frobenius(); |
| 71 | +auto vb = b.verschiebung(); |
| 72 | +// F(V(a)) == V(F(a)) — verified at compile time |
| 73 | + |
| 74 | +// Adams operation ψⁿ |
| 75 | +auto psi = adams_operation(a, 3); |
| 76 | + |
| 77 | +// Teichmüller lift: τ(x) = (x, 0, 0, …) (N is required) |
| 78 | +auto tau = teichmueller_lift<4>(uint64_t{7}); |
| 79 | +// ghost_j(τ(ab)) = ghost_j(τ(a)) · ghost_j(τ(b)) — verified at compile time |
| 80 | +``` |
| 81 | +
|
| 82 | +### Polynomial composition and reversion |
| 83 | +
|
| 84 | +```cpp |
| 85 | +Polynomial<6, uint64_t> P{{0, 1, 1}}; // P(t) = t + t² |
| 86 | +Polynomial<6, uint64_t> Q{{0, 1, 2}}; // Q(t) = t + 2t² |
| 87 | +
|
| 88 | +auto PQ = compose(P, Q); // P(Q(t)) — degree (N-1)*(M-1)+1 = 26 |
| 89 | +auto R = reversion(P); // Lagrange inverse: P(R(t)) = t |
| 90 | +// R(t) = t − t² + 2t³ − 5t⁴ + 14t⁵ − 42t⁶ + … |
| 91 | +// (stored in ℤ₂: negative coefficients wrap modulo 2^W) |
| 92 | +``` |
| 93 | + |
| 94 | +### Compile-time verification |
| 95 | + |
| 96 | +```cpp |
| 97 | +#include "dyadic_verify.h" // triggers all static_asserts at compile time |
| 98 | +// If it compiles, all 20+ proofs passed. |
| 99 | +``` |
| 100 | + |
| 101 | +Day-to-day compiles include a sampled subset. For the full exhaustive suite (256² cases, 8K+ multiplication cases), define `DYADIC_HEAVY_PROOFS`. |
| 102 | + |
| 103 | +### Precision window checkers |
| 104 | + |
| 105 | +```cpp |
| 106 | +Polynomial<6, uint8_t> p{{0, 0, 0, 0, 0, 255}}; |
| 107 | +if (!check_taylor_roundtrip_precision(p)) |
| 108 | + // T₅ = 5! · 255 = 30600 > 256 — high bits lost |
| 109 | + |
| 110 | +WittVector<4, uint32_t> w{{1, 2, 3, 4}}; |
| 111 | +if (!check_witt_recovery_precision(w)) |
| 112 | + // Some rⱼ ≥ 2³²⁻ʲ — ghost recovery inexact |
| 113 | +``` |
| 114 | +
|
| 115 | +## Build & Integrate |
| 116 | +
|
| 117 | +**As a single header** — copy `dyadic.h` into your project and `#include "dyadic.h"`. |
| 118 | +
|
| 119 | +**With CMake**: |
| 120 | +```bash |
| 121 | +cmake -B build -DDYADIC_BUILD_TESTS=ON |
| 122 | +cmake --build build |
| 123 | +ctest --test-dir build |
| 124 | +``` |
| 125 | + |
| 126 | +Optional: `-DDYADIC_HEAVY_PROOFS=ON` for exhaustive compile-time proofs. |
| 127 | + |
| 128 | +**Via CI script**: |
| 129 | +```bash |
| 130 | +./ci_compile_check.sh |
| 131 | +``` |
| 132 | + |
| 133 | +## Tests |
| 134 | + |
| 135 | +| File | What | |
| 136 | +|------|------| |
| 137 | +| `test_verify.cpp` | 20+ compile-time proofs + runtime verification across 9 (N,W) combos | |
| 138 | +| `test_property.cpp` | Randomized property-based tests: 7 invariants × 10 (N,W) combos | |
| 139 | +| `test_full.cpp` | 16 functional test groups covering the entire API surface | |
| 140 | +| `benchmark.cpp` | Runtime benchmarks for key operations (build manually: `g++ -O2 -std=c++20 -I.. benchmark.cpp`) | |
| 141 | + |
| 142 | +All tests pass under GCC 14 and Clang 21 with ASan+UBSan. CI covers GCC (light + heavy proofs), Clang, and MSVC on Windows. |
| 143 | + |
| 144 | +## Known Limitations |
| 145 | + |
| 146 | +- **Taylor basis roundtrip**: `T_k = k! · FF_k` wraps when `FF_k ≥ 2^W / k!`. Use small coefficients for exact roundtrips. FallingFactorial basis has no such limitation. |
| 147 | +- **Witt precision window**: Recovery `r_j = (G_j − S_j) / 2^j` requires `r_j < 2^{W−j}`. |
| 148 | +- **`detail::uint128_t`** is a software 128-bit pair — no `unsigned __int128` required. `__int128` is used only as an optimization in `binom()`, guarded by feature-test macros. |
| 149 | + |
| 150 | +## License |
| 151 | + |
| 152 | +This project is made available under the terms of the MIT License. |
0 commit comments