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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
98
99
100
101
102
104#define CECCO_ERASURE_SUPPORT
108
109
110
111
112
114#define CECCO_USE_LUTS_FOR_FP
118
119
120
121
122
123
124
125#ifndef CECCO_COMPRESS_LUTS_FROM_Q
126#define CECCO_COMPRESS_LUTS_FROM_Q 256
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
163template <ComponentType T>
165template <CoefficientType T>
167template <ComponentType T>
169template <FiniteFieldType MAIN, FiniteFieldType... OTHERS>
174
175
176
177
178
179
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
225 constexpr bool operator!=(
const T& rhs)
const {
return !(
static_cast<
const T&>(*
this) == rhs); }
232 constexpr T
operator+()
const& {
return static_cast<
const T&>(*
this); }
234 constexpr T&&
operator+() &&
noexcept {
return static_cast<T&&>(*
this); }
277#ifdef CECCO_ERASURE_SUPPORT
292
293
294
295
296
297
298
299
300
301
302
303
305template <FieldType T>
312template <FieldType T>
314 T res(
std::move(lhs));
319template <FieldType T>
321 T res(
std::move(rhs));
326template <FieldType T>
328 T res(
std::move(lhs));
333template <FieldType T>
340template <FieldType T>
342 T res(
std::move(lhs));
347template <FieldType T>
349 T res(-
std::move(rhs));
354template <FieldType T>
356 T res(
std::move(lhs));
361template <FieldType T>
368template <FieldType T>
370 T res(
std::move(lhs));
375template <FieldType T>
377 T res(
std::move(rhs));
382template <FieldType T>
384 T res(
std::move(lhs));
389template <FieldType T>
396template <FieldType T>
403template <FieldType T>
405 T res(
std::move(lhs));
410template <FieldType T>
412 T res(
std::move(rhs));
417template <FieldType T>
424template <FieldType T>
426 T res(
std::move(lhs));
431template <FieldType T>
433 return sqm<T>(base, exponent);
436template <FieldType T>
438 return sqm<T>(
std::move(base), exponent);
443#ifdef CECCO_ERASURE_SUPPORT
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469template <SignedIntType T = InfInt>
473
474
475
476
477
478
492#ifdef CECCO_ERASURE_SUPPORT
493 if (is_erased() != rhs.is_erased())
return false;
495 return numerator * rhs.get_denominator() == rhs.get_numerator() * denominator;
518
519
520
521
522
530 static const std::string info =
"rational number";
541 constexpr bool is_zero()
const noexcept {
return numerator == 0; }
543#ifdef CECCO_ERASURE_SUPPORT
545
546
547
548
549
567 constexpr void simplify();
572template <SignedIntType T>
574 if (d == 0)
throw std::invalid_argument(
"denominator must not be zero");
578template <SignedIntType T>
585template <SignedIntType T>
587 if (
this == &rhs)
return *
this;
588 numerator = std::move(rhs.numerator);
589 denominator = std::move(rhs.denominator);
593template <SignedIntType T>
595#ifdef CECCO_ERASURE_SUPPORT
596 if (
this->is_erased())
return Rationals().erase();
599 res.numerator = -res.numerator;
603template <SignedIntType T>
605#ifdef CECCO_ERASURE_SUPPORT
606 if (
this->is_erased())
return this->erase();
608 numerator = -numerator;
612template <SignedIntType T>
614#ifdef CECCO_ERASURE_SUPPORT
615 if (
this->is_erased() || rhs.is_erased())
return this->erase();
617 auto tn = numerator * rhs.get_denominator() + denominator * rhs.get_numerator();
618 auto td = denominator * rhs.get_denominator();
625template <SignedIntType T>
627#ifdef CECCO_ERASURE_SUPPORT
628 if (
this->is_erased() || rhs.is_erased())
return this->erase();
630 auto tn = numerator * rhs.get_denominator() - denominator * rhs.get_numerator();
631 auto td = denominator * rhs.get_denominator();
638template <SignedIntType T>
640#ifdef CECCO_ERASURE_SUPPORT
641 if (
this->is_erased() || rhs.is_erased())
return this->erase();
643 auto tn = numerator * rhs.get_numerator();
644 auto td = denominator * rhs.get_denominator();
651template <SignedIntType T>
653#ifdef CECCO_ERASURE_SUPPORT
654 if (
this->is_erased() || rhs.is_erased())
return this->erase();
656 if (rhs.numerator == 0)
throw std::invalid_argument(
"division by zero");
657 auto tn = numerator * rhs.get_denominator();
658 auto td = denominator * rhs.get_numerator();
665template <SignedIntType T>
667#ifdef CECCO_ERASURE_SUPPORT
670 thread_local std::uniform_int_distribution<
int> dist(-100, 100);
671 numerator = dist(gen());
673 denominator = dist(gen());
674 }
while (denominator == 0);
679template <SignedIntType T>
681#ifdef CECCO_ERASURE_SUPPORT
684 thread_local std::uniform_int_distribution<
int> dist(-100, 100);
692 }
while (T(n) * denominator == numerator * T(d));
699template <SignedIntType T>
702 throw std::invalid_argument(
703 "trying to calculate multiplicative order "
704 "of additive neutral element");
705 if (numerator == denominator)
707 else if (numerator == -denominator)
712template <SignedIntType T>
714 if (numerator == 0) {
720#ifdef CECCO_ERASURE_SUPPORT
737template <SignedIntType T>
739 if (numerator == 0) {
744 auto d = GCD<T>(numerator, denominator);
747 if (denominator < 0) {
754
755
756
757
758template <SignedIntType T>
760#ifdef CECCO_ERASURE_SUPPORT
762 os << ERASURE_MARKER;
765 std::string temp = std::to_string(e.get_numerator());
766 if (e.get_denominator() != 1) temp +=
"/" + std::to_string(e.get_denominator());
768#ifdef CECCO_ERASURE_SUPPORT
774template <FiniteFieldType B,
MOD modulus,
LutMode mode>
789 const bool negative = l < 0;
790 const size_t magnitude = negative ?
static_cast<size_t>(-(l + 1)) + 1 :
static_cast<size_t>(l);
791 if (magnitude >= field_size)
792 throw std::invalid_argument(
"absolute value of l must be no larger than the field size minus one");
793 return {magnitude, negative};
797
798
799
800
801
802
803template <uint16_t q, uint8_t m, size_t SIZE>
805 static_assert(SIZE >=
static_cast<size_t>(m),
"array size must be at least the extension degree m");
806 size_t res = coeffs[0];
808 for (uint8_t i = 1; i < m; ++i) {
809 res += coeffs[i] * t;
816
817
818
819
820
821template <
typename LabelType, size_t FieldSize>
828
829
830
831
832
833
834
835
836
837template <
typename LabelType, size_t FieldSize>
840 constexpr LabelType&
operator()(size_t i, size_t j) {
841 if (i > j)
return operator()(j, i);
845 if (i > FieldSize / 2) {
846 return values[FieldSize - i][j - i];
854 constexpr LabelType
operator()(size_t i, size_t j)
const noexcept {
855 if (i > j)
return operator()(j, i);
859 if (i > FieldSize / 2) {
860 return values[FieldSize - i][j - i];
868 std::array<
std::array<LabelType, FieldSize>,
874
875
876
877
878
879
880template <
typename LabelType, size_t ExtensionDegree, size_t FieldSize>
882 std::array<
std::array<LabelType, ExtensionDegree>, FieldSize>
values{};
889template <
typename LabelType, LabelType FieldSize>
891 Lut1D<LabelType, FieldSize> lut_mul_ord;
893 lut_mul_ord.values[0] = 0;
894 lut_mul_ord.values[1] = 1;
895 for (LabelType i = 2; i < FieldSize; ++i) {
897 for (LabelType j = 1; j < FieldSize; ++j) {
899 lut_mul_ord.values[i] = j;
902 temp = mul_lut(temp, i);
913template <
typename LabelType, LabelType FieldSize>
1008template <
typename F>
1011 if constexpr (
p == 2)
return typename F::
label_t{1};
1069 "trying to calculate multiplicative order "
1070 "of additive neutral element");
1168 const auto S =
lhs[
m - 1 -
s];
1169 if (
S == 0)
continue;
1171 const auto T =
rhs[
m - 1 -
t];
1172 if (
T == 0)
continue;
1181 if (
flag == 0)
continue;
1204
1205
1206
1207
1208
1209
1210
1211
1216template <
typename LutType, LutType (*F)()>
1221 static constexpr LutType
lut = F();
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248template <
typename LutType,
typename ProviderLutType,
const ProviderLutType& (*P)(),
1249 LutType (*F)(
const ProviderLutType& (*)()),
LutMode mode>
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1329#ifdef CECCO_ERASURE_SUPPORT
1330 if (sub.is_erased())
return SUPERFIELD().erase();
1332 return SUPERFIELD(embedding_map[sub.get_label()]);
1336
1337
1338
1339
1340
1341
1342
1346 std::span<
const size_t> embedding_map;
1349 static std::vector<size_t> compute_embedding();
1353
1354
1366#ifdef CECCO_ERASURE_SUPPORT
1427 if (
lhs !=
rhs)
return false;
1467 throw std::
logic_error(
"Cannot construct additive subfield embedding");
1473
1474
1475
1476
1477
1478
1479
1480
1506 if (
h_A(
a) ==
A(0)) {
1516 if (
h_B(
b) ==
B(0)) {
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1593#ifdef CECCO_ERASURE_SUPPORT
1607
1608
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662template <uint16_t p>
1664 static_assert(is_prime(p),
"p is not a prime");
1680 constexpr Fp(
const Fp& other)
noexcept =
default;
1681 constexpr Fp(
Fp&& other)
noexcept =
default;
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694 template <FiniteFieldType S,
MOD ext_modulus,
LutMode mode>
1695 Fp(
const Ext<S, ext_modulus, mode>& other);
1698
1699
1700
1701
1702
1703
1704
1705 template <FiniteFieldType MAIN, FiniteFieldType... OTHERS>
1709 ~
Fp()
noexcept =
default;
1719 template <FiniteFieldType S,
MOD ext_modulus,
LutMode mode>
1723 template <FiniteFieldType MAIN, FiniteFieldType... OTHERS>
1724 requires(MAIN::get_characteristic() == p)
1727 constexpr bool operator==(
const Fp& rhs)
const noexcept {
return label == rhs.get_label(); }
1751
1752
1753
1754
1762 static const std::string info =
"prime field with " + std::to_string(p) +
" elements";
1780
1781
1782
1783
1784
1793 constexpr bool is_zero()
const noexcept {
return label == 0; }
1795#ifdef CECCO_ERASURE_SUPPORT
1797
1798
1799
1800
1801
1810
1811
1812
1813
1814
1816#ifdef CECCO_USE_LUTS_FOR_FP
1826#ifndef CECCO_USE_LUTS_FOR_FP
1828 static constexpr label_t lut_add(label_t a, label_t b)
noexcept {
1829 Fp temp_a(a), temp_b(b);
1831 return temp_a.get_label();
1835 static constexpr label_t lut_mul(label_t a, label_t b)
noexcept {
1836 Fp temp_a(a), temp_b(b);
1838 return temp_a.get_label();
1842 static constexpr label_t lut_neg(label_t a)
noexcept {
1844 temp = -
std::move(temp);
1845 return temp.get_label();
1858#ifdef CECCO_USE_LUTS_FOR_FP
1866
1867
1868
1869
1887 static_assert(
lut_add(0, 0) == 0);
1888 static_assert(
lut_neg(0) == 0);
1889 static_assert(
lut_mul(0, 1) == 0);
1900template <uint16_t p>
1902 const auto parsed = details::parse_signed_label(l, p);
1903 label =
static_cast<label_t>(parsed.magnitude);
1904 if (parsed.negative) label = lut_neg(label);
1908template <FiniteFieldType S,
MOD ext_modulus,
LutMode mode>
1909Fp<p>::
Fp(
const Ext<S, ext_modulus, mode>& other) {
1911 static_assert(Fp<p>::get_characteristic() ==
Ext<S, ext_modulus, mode>::get_characteristic(),
1912 "trying to convert between fields with different characteristic");
1914#ifdef CECCO_ERASURE_SUPPORT
1915 if (other.is_erased()) {
1923 auto embedding = Embedding<Fp<p>, Ext<S, ext_modulus, mode>>();
1924 Fp<p> result = embedding.extract(other);
1925 label = result.get_label();
1929template <FiniteFieldType MAIN, FiniteFieldType... OTHERS>
1933#ifdef CECCO_ERASURE_SUPPORT
1962template <uint16_t p>
1964 const auto parsed = details::parse_signed_label(l, p);
1965 label =
static_cast<label_t>(parsed.magnitude);
1966 if (parsed.negative) label = lut_neg(label);
1971template <FiniteFieldType S,
MOD ext_modulus,
LutMode mode>
1974 std::swap(*
this, temp);
1989#ifdef CECCO_ERASURE_SUPPORT
1994#ifndef CECCO_USE_LUTS_FOR_FP
2006#ifdef CECCO_ERASURE_SUPPORT
2010#ifndef CECCO_USE_LUTS_FOR_FP
2021#ifdef CECCO_ERASURE_SUPPORT
2024#ifndef CECCO_USE_LUTS_FOR_FP
2038#ifdef CECCO_ERASURE_SUPPORT
2041#ifndef CECCO_USE_LUTS_FOR_FP
2055#ifdef CECCO_ERASURE_SUPPORT
2058#ifndef CECCO_USE_LUTS_FOR_FP
2074#ifdef CECCO_ERASURE_SUPPORT
2085#ifdef CECCO_ERASURE_SUPPORT
2089#ifndef CECCO_USE_LUTS_FOR_FP
2099#ifdef CECCO_ERASURE_SUPPORT
2103#ifndef CECCO_USE_LUTS_FOR_FP
2117#ifdef CECCO_ERASURE_SUPPORT
2121#ifndef CECCO_USE_LUTS_FOR_FP
2135#ifdef CECCO_ERASURE_SUPPORT
2138 if (
label == 0)
throw std::
invalid_argument(
"trying to calculate multiplicative order of additive neutral element");
2139#ifndef CECCO_USE_LUTS_FOR_FP
2148#ifdef CECCO_ERASURE_SUPPORT
2151 if (
label == 0)
return 1;
2157 std::
cout <<
"addition table (row and column headers omitted)" <<
std::
endl;
2163#ifdef CECCO_USE_LUTS_FOR_FP
2164 std::
cout <<
"additive inverse table (row headers omitted)" <<
std::
endl;
2168 std::
cout <<
"multiplication table (row and column headers omitted)" <<
std::
endl;
2174#ifdef CECCO_USE_LUTS_FOR_FP
2175 std::
cout <<
"multiplicative inverse table (row headers omitted)" <<
std::
endl;
2180#ifdef CECCO_ERASURE_SUPPORT
2197#ifdef CECCO_ERASURE_SUPPORT
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2245 static_assert(
modulus.
back() == 1,
"provided polynomial is not monic");
2246 static_assert(
modulus.
size() > 2,
"provided polynomial has degree less than 2");
2253 "modulus coefficients must be reduced base field labels in {0, ..., q - 1}");
2254 static_assert(
B::
ready(),
"base field must be fully instantiated");
2256 "CompileTime extension fields require all base fields to have constexpr-ready interfaces");
2271
2272
2273
2274
2275
2276
2277
2278
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2304
2305
2306
2307
2308
2309
2310
2311
2316
2317
2318
2319
2320
2321
2322
2327
2328
2329
2330
2331
2382
2383
2384
2385
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2418
2419
2420
2421
2422
2429
2430
2431
2432
2452#ifdef CECCO_ERASURE_SUPPORT
2454
2455
2456
2457
2458
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2484
2485
2486
2487
2488
2489
2490
2491
2492
2512
2513
2514
2515
2594 static_assert(
B::
ready());
2599 static_assert(
lut_add()(0, 0) == 0);
2600 static_assert(
lut_neg()(0) == 0);
2601 static_assert(
lut_mul()(0, 1) == 0);
2603 static_assert(
g().
value != 1);
2623#ifdef CECCO_ERASURE_SUPPORT
2641#ifdef CECCO_ERASURE_SUPPORT
2661 "trying to convert between fields with different characteristic");
2663#ifdef CECCO_ERASURE_SUPPORT
2707 "trying to construct extension field element using base field vector of wrong length");
2709#ifdef CECCO_ERASURE_SUPPORT
2725 "extension field elements can only be constructed from vectors over subfields");
2732 "trying to construct extension field element using subfield vector of wrong length");
2734#ifdef CECCO_ERASURE_SUPPORT
2763 "trying to convert between fields with different characteristic");
2765#ifdef CECCO_ERASURE_SUPPORT
2840 "Prime field characteristic must match extension field characteristic");
2842#ifdef CECCO_ERASURE_SUPPORT
2892#ifdef CECCO_ERASURE_SUPPORT
2902#ifdef CECCO_ERASURE_SUPPORT
2911#ifdef CECCO_ERASURE_SUPPORT
2920#ifdef CECCO_ERASURE_SUPPORT
2929#ifdef CECCO_ERASURE_SUPPORT
2938#ifdef CECCO_ERASURE_SUPPORT
2949#ifdef CECCO_ERASURE_SUPPORT
2959#ifdef CECCO_ERASURE_SUPPORT
2969#ifdef CECCO_ERASURE_SUPPORT
2979#ifdef CECCO_ERASURE_SUPPORT
2982 if (
label == 0)
throw std::
invalid_argument(
"trying to calculate multiplicative order of additive neutral element");
2988#ifdef CECCO_ERASURE_SUPPORT
2991 if (
label == 0)
return 1;
3000#ifdef CECCO_ERASURE_SUPPORT
3008 if (
i > 0 &&
beta == *
this)
break;
3021 " extension of (" +
B::
get_info() +
"), irreducible polynomial ";
3051#ifdef CECCO_ERASURE_SUPPORT
3064 "extension field elements can only be converted into vectors over subfields");
3082 std::
cout <<
"addition table (row and column headers omitted)" <<
std::
endl;
3088 std::
cout <<
"additive inverse table (row headers omitted)" <<
std::
endl;
3091 std::
cout <<
"multiplication table (row and column headers omitted)" <<
std::
endl;
3097 std::
cout <<
"multiplicative inverse table (row headers omitted)" <<
std::
endl;
3100 std::
cout <<
"multiplicative order table (row headers omitted)" <<
std::
endl;
3103 std::
cout <<
"element coefficients table (column headers omitted)" <<
std::
endl;
3117#ifdef CECCO_ERASURE_SUPPORT
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3163 static_assert(
sizeof...(
OTHERS) > 0,
"Iso requires at least two field representations");
3166 "All field representations in Iso must be pairwise distinct");
3199
3200
3201
3202
3203
3204
3205
3206
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3225
3226
3227
3228
3229
3230
3237
3238
3239
3240
3241
3242
3243
3244
3245
3255 template <
typename OTHER>
3262 template <
typename OTHER>
3269 template <
typename OTHER>
3279 template <
typename OTHER>
3284
3285
3286
3287
3288 template <
typename TO>
3289 constexpr TO as()
const
3315#ifdef CECCO_ERASURE_SUPPORT
3317
3318
3319
3320
3321
3338 template <
typename OTHER>
3416
3417
3418
3419
3441template <
typename OTHER>
3451template <uint16_t p>
3483 "trying to convert between fields with different characteristic");
3485#ifdef CECCO_ERASURE_SUPPORT
3556 static_assert(
MAIN::
get_characteristic() ==
p,
"Prime field characteristic must match Iso field characteristic");
3558#ifdef CECCO_ERASURE_SUPPORT
3590 "trying to convert between fields with different characteristic");
3592#ifdef CECCO_ERASURE_SUPPORT
3764template <
typename OTHER>
3779template <
typename OTHER>
3794template <
typename OTHER>
3815template <
typename OTHER>
3824template <
typename TO>
3828#ifdef CECCO_ERASURE_SUPPORT
3872#ifdef CECCO_ERASURE_SUPPORT
Functor representing the field embedding Ο: SUBFIELD β SUPERFIELD, with reverse lookup.
constexpr SUPERFIELD operator()(const SUBFIELD &sub) const
Apply Ο: SUBFIELD β SUPERFIELD.
Embedding()
Constructs the embedding (cached on first instantiation per template arguments).
constexpr SUBFIELD extract(const SUPERFIELD &super) const
Reverse Ο: find the unique s β SUBFIELD with Ο(s) == super.
Extension field π½_{q^m} β
B[x]/(f(x)), constructed from a base field and an irreducible monic modulus...
Prime field π½_p β
β€/pβ€
constexpr Fp() noexcept
Default constructor: 0.
Fp & randomize_force_change()
Like randomize but guaranteed to differ from the current value.
constexpr Fp(const Fp &other) noexcept=default
static std::string get_info()
Human-readable description: "prime field with p elements".
static constexpr size_t get_characteristic() noexcept
size_t get_additive_order() const
Additive order: 1 for zero, p otherwise.
constexpr Fp(int l)
Construct from a signed element label l β {β(p β 1), β¦, p β 1}.
Fp & operator=(const Ext< S, ext_modulus, mode > &other)
Project an extension-field element to π½_p (copy-and-swap; same semantics as the constructor).
constexpr Fp operator-() const &noexcept
Additive inverse (lvalue): returns a new element with -label mod p.
constexpr Fp & operator-() &&noexcept
Additive inverse (rvalue): in place.
static constexpr size_t get_q() noexcept
constexpr Fp & operator=(Fp &&rhs) noexcept=default
static void show_tables()
Print all lookup tables to std::cout (debugging aid).
Fp & randomize()
Uniform random element in {0, β¦, p β 1}.
static constexpr size_t get_size() noexcept
constexpr Fp & operator+=(const Fp &rhs) noexcept
*this = (label + rhs.label) mod p
constexpr bool operator==(const Fp &rhs) const noexcept
constexpr bool is_zero() const noexcept
True iff this is the additive identity.
static constexpr Fp get_generator() noexcept
Generator (primitive root) of π½_p*; precomputed label is Gen.
constexpr Fp & operator=(const Fp &rhs) noexcept=default
static constexpr size_t get_m() noexcept
constexpr Fp & operator=(int l)
Assign a signed element label (same semantics and range as Fp(int)).
size_t get_multiplicative_order() const
Multiplicative order in π½_p*.
static constexpr label_t Gen
Primitive element (generator) of F_p*.
Fp(const Iso< MAIN, OTHERS... > &other)
Extract a prime-field element from an Iso containing this prime subfield.
Fp & operator/=(const Fp &rhs)
*this = (label Β· rhs.labelβ»ΒΉ) mod p; throws std::invalid_argument if rhs is zero
static constexpr bool is_constexpr_ready() noexcept
Always true for prime fields.
constexpr Fp & operator*=(const Fp &rhs) noexcept
*this = (label Β· rhs.label) mod p
Fp(const Ext< S, ext_modulus, mode > &other)
Extract a prime-field element from an extension field (downcast).
constexpr bool has_positive_sign() const noexcept
Always true (finite fields are unordered).
constexpr Fp & operator*=(int s) noexcept
*this = (label Β· s) mod p (repeated addition)
constexpr Fp & operator-=(const Fp &rhs) noexcept
*this = (label β rhs.label) mod p
static constexpr size_t get_p() noexcept
constexpr Fp(Fp &&other) noexcept=default
static constexpr bool ready()
Compile-time signal that all LUTs are constructed.
constexpr size_t get_label() const noexcept
Underlying integer label in {0, β¦, p β 1}.
Single logical field unifying several pairwise-isomorphic representations.
Dense m Γ n matrix over a CECCO::ComponentType.
Univariate polynomial p(x) = aβ + aβx + β¦ + aβxβΏ over a CECCO::CoefficientType.
Field of rational numbers β = { p/q : p, q β β€, q β 0 } with selectable precision.
static constexpr size_t get_characteristic() noexcept
Characteristic of β: 0.
constexpr bool operator==(const Rationals< T > &rhs) const
Cross-multiplication equality.
constexpr bool has_positive_sign() const noexcept
Sign predicate: true iff the numerator is non-negative (always false for erased elements).
constexpr Rationals & operator=(int l)
Assign the integer l as l / 1.
Rationals(int n=0, int d=1)
Construct n / d, simplified to lowest terms with positive denominator.
constexpr Rationals & operator*=(const Rationals &rhs)
*this *= rhs, result kept in lowest terms
Rationals & randomize_force_change()
Like randomize but guaranteed to differ from the current value.
size_t get_multiplicative_order() const
Multiplicative order.
constexpr Rationals operator-() const &
Additive inverse (lvalue overload returns a copy with negated numerator).
constexpr Rationals & operator-=(const Rationals &rhs)
*this -= rhs, result kept in lowest terms
Rationals & randomize()
Random rational (bounded numerator and denominator), simplified.
Rationals(Rationals &&other)=default
constexpr const T & get_denominator() const noexcept
Denominator (always positive after simplification).
static std::string get_info()
Human-readable description: "rational number".
Rationals & operator/=(const Rationals &rhs)
*this /= rhs; throws std::invalid_argument if rhs is zero
constexpr const T & get_numerator() const noexcept
Numerator (sign carrier).
Rationals(const Rationals &other)=default
Rationals & operator=(Rationals &&rhs)
constexpr Rationals & operator-() &&
Additive inverse (rvalue overload negates in place).
constexpr Rationals & operator=(const Rationals &rhs)=default
constexpr Rationals & operator+=(const Rationals &rhs)
*this += rhs, result kept in lowest terms
constexpr bool is_zero() const noexcept
True iff numerator is zero.
size_t get_additive_order() const noexcept
Additive order: 1 for zero, 0 (infinite) otherwise (characteristic 0).
Vector v = (vβ, vβ, β¦, vβββ) over a CECCO::ComponentType.
Tag base for the CRTP-protection idiom.
CRTP base documenting the interface every field type must provide.
T & operator=(T &&rhs) noexcept=delete
Move assignment (derived must implement).
T & operator+=(const T &rhs) noexcept=delete
*this += rhs (derived must implement)
T & operator-=(const T &rhs) noexcept=delete
*this -= rhs (derived must implement)
T & operator*=(const T &rhs) noexcept=delete
*this *= rhs (derived must implement)
bool is_zero() const noexcept=delete
True if *this is the additive identity.
T & operator/=(const T &rhs)=delete
*this /= rhs (derived must implement), throws std::invalid_argument if rhs is zero
size_t get_multiplicative_order() const =delete
Smallest k > 0 with this^k == 1; throws std::invalid_argument if *this is zero.
Field & randomize_force_change()=delete
Like randomize but guaranteed to differ from the current value (derived must implement).
~Field() noexcept=default
T & operator=(int l)=delete
Assign from int (derived must implement).
constexpr T operator+() const &
Unary + on an lvalue: returns a copy.
constexpr T && operator+() &&noexcept
Unary + on an rvalue: returns the rvalue itself.
Field & randomize()=delete
Uniform random element of the field (derived must implement), may return the same value.
size_t get_additive_order() const =delete
Smallest k > 0 with k * *this == 0; for finite fields of characteristic p this is p (or 1 for zero); ...
T & operator-() &&noexcept=delete
In-place additive inverse on an rvalue (derived must implement).
T & operator=(const T &rhs) noexcept=delete
Copy assignment (derived must implement).
constexpr bool operator!=(const T &rhs) const
Inequality, defined as !(*this == rhs).
T operator-() const &noexcept=delete
Additive inverse on an lvalue (derived must implement).
bool has_positive_sign() const noexcept=delete
True if the element is "positive" (always true for finite fields; sign of numerator for β).
#define MOD
Alias for std::array, used to spell modulus polynomials in CECCO::Ext.
#define CECCO_COMPRESS_LUTS_FROM_Q
Compression threshold for 2D lookup tables in extension fields.
Contains implementation details not to be exposed to the user. Functions and classes here may change ...
constexpr auto compute_multiplicative_orders(const Lut2D< LabelType, FieldSize > &mul_lut)
Build the table of multiplicative orders for all elements of π½_Q.
constexpr SignedLabel parse_signed_label(int l, size_t field_size)
constexpr auto compute_multiplicative_inverses_direct()
Build multiplicative-inverse table for π½_p via extended Euclidean algorithm.
static size_t constexpr integer_from_coeffs(const std::array< size_t, SIZE > &coeffs) noexcept
Encode polynomial coefficients (low-to-high) as a base-q integer label.
Provides a framework for error correcting codes.
constexpr T operator*(int lhs, const T &rhs)
constexpr T operator-(T &&lhs, const T &rhs)
constexpr T operator+(T &&lhs, const T &rhs)
constexpr T operator*(const T &lhs, T &&rhs)
constexpr T operator*(T &&lhs, T &&rhs)
T operator/(const T &lhs, const T &rhs)
constexpr T operator+(const T &lhs, T &&rhs)
constexpr T operator+(const T &lhs, const T &rhs)
constexpr T operator*(const T &lhs, const T &rhs)
constexpr T operator-(const T &lhs, const T &rhs)
constexpr T operator+(T &&lhs, T &&rhs)
constexpr T operator*(const T &lhs, int rhs)
constexpr T operator*(int lhs, T &&rhs)
constexpr T operator^(const T &base, int exponent)
constexpr T operator^(T &&base, int exponent)
constexpr T operator-(const T &lhs, T &&rhs)
T operator/(T &&lhs, const T &rhs)
constexpr T operator-(T &&lhs, T &&rhs)
LutMode
LUT generation mode for field operations.
constexpr T operator*(T &&lhs, const T &rhs)
constexpr T operator*(T &&lhs, int rhs)
1D lookup table for unary field operations (negation, inversion, order)
std::array< LabelType, FieldSize > values
constexpr LabelType operator()(size_t i) const noexcept
2D lookup table for commutative binary operations, optionally compressed
constexpr LabelType operator()(size_t i, size_t j) const noexcept
Const access (used during field operations).
constexpr LabelType & operator()(size_t i, size_t j)
Mutable access (used during table construction).
std::array< std::array< LabelType, FieldSize >,(FieldSize< CECCO_COMPRESS_LUTS_FROM_Q ? FieldSize :FieldSize/2+1)> values
Backing storage; full square below the compression threshold, upper triangle above.
Lookup table mapping each extension-field label to its base-field coefficient vector.
std::array< std::array< LabelType, ExtensionDegree >, FieldSize > values
CompileTime specialisation: table is a constexpr static member.
static constexpr const LutType & get_lut()
static constexpr LutType lut
Holds a LUT generated by F(P); P provides a dependency table.