Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
montgomery_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
35# include <gtest/gtest.h>
36
37# include <random>
38
39# include <modular_arithmetic.H>
40
41using namespace Aleph;
42
43#if defined(__SIZEOF_INT128__)
44
45namespace
46{
49
50 static_assert(kCtx3.mod() == 3);
51 static_assert(kCtx9.mod() == 9);
52
53 void
55 const Array<uint64_t> & values)
56 {
57 const uint64_t mod = ctx.mod();
58 for (size_t i = 0; i < values.size(); ++i)
59 EXPECT_EQ(from_mont(to_mont(values[i], ctx), ctx), values[i] % mod)
60 << "mod=" << mod << " value=" << values[i];
61 }
62
63 void
65 const Array<uint64_t> & values)
66 {
68 }
69
70 void
74 {
75 const uint64_t mod = ctx.mod();
76 for (size_t i = 0; i < lhs_values.size(); ++i)
77 for (size_t j = 0; j < rhs_values.size(); ++j)
78 {
79 const uint64_t lhs = lhs_values[i];
80 const uint64_t rhs = rhs_values[j];
81 const uint64_t got =
82 from_mont(mont_mul(to_mont(lhs, ctx), to_mont(rhs, ctx), ctx),
83 ctx);
84 EXPECT_EQ(got, mod_mul(lhs % mod, rhs % mod, mod))
85 << "mod=" << mod << " lhs=" << lhs << " rhs=" << rhs;
86 }
87 }
88
89 void
90 expect_products(const uint64_t mod,
93 {
95 }
96
97 void
98 expect_powers(const MontgomeryCtx & ctx,
99 const Array<uint64_t> & bases,
100 const Array<uint64_t> & exponents)
101 {
102 const uint64_t mod = ctx.mod();
103 for (size_t j = 0; j < bases.size(); ++j)
104 for (size_t k = 0; k < exponents.size(); ++k)
105 {
106 const uint64_t base = bases[j];
107 const uint64_t exp = exponents[k];
108 const uint64_t got =
109 from_mont(mont_exp(to_mont(base, ctx), exp, ctx), ctx);
110 EXPECT_EQ(got, mod_exp(base % mod, exp, mod))
111 << "mod=" << mod << " base=" << base << " exp=" << exp;
112 }
113 }
114}
115
117{
118 EXPECT_THROW(static_cast<void>(montgomery_ctx(0)), std::invalid_argument);
119 EXPECT_THROW(static_cast<void>(montgomery_ctx(1)), std::invalid_argument);
120 EXPECT_THROW(static_cast<void>(montgomery_ctx(2)), std::invalid_argument);
121 EXPECT_THROW(static_cast<void>(montgomery_ctx(100)), std::invalid_argument);
122}
123
125{
126 const Array<uint64_t> mods =
127 {9ULL, 998244353ULL, 469762049ULL, 1004535809ULL};
128
129 for (size_t i = 0; i < mods.size(); ++i)
130 {
131 const uint64_t mod = mods[i];
132 expect_round_trip(mod, {0ULL, 1ULL, 2ULL, mod - 2, mod - 1,
133 mod, mod + 1, mod * 2 + 7});
134 }
135}
136
138{
139 const Array<uint64_t> mods =
140 {9ULL, 998244353ULL, 469762049ULL, 1004535809ULL};
141
142 for (size_t i = 0; i < mods.size(); ++i)
143 {
144 const uint64_t mod = mods[i];
145 expect_products(mod, {0ULL, 1ULL, 2ULL, mod - 2, mod - 1, mod + 5},
146 {0ULL, 1ULL, 3ULL, mod - 3, mod - 1, mod + 9});
147
148 std::mt19937_64 rng(mod);
149 const MontgomeryCtx ctx = montgomery_ctx(mod);
150 for (size_t sample = 0; sample < 128; ++sample)
151 {
152 const uint64_t lhs = rng();
153 const uint64_t rhs = rng();
154 const uint64_t got =
155 from_mont(mont_mul(to_mont(lhs, ctx), to_mont(rhs, ctx), ctx),
156 ctx);
157 EXPECT_EQ(got, mod_mul(lhs % mod, rhs % mod, mod))
158 << "mod=" << mod << " lhs=" << lhs << " rhs=" << rhs;
159 }
160 }
161}
162
164{
165 const Array<uint64_t> mods =
166 {9ULL, 998244353ULL, 469762049ULL, 1004535809ULL};
167 const Array<uint64_t> exponents =
168 {0ULL, 1ULL, 2ULL, 7ULL, 31ULL, 123456ULL};
169
170 for (size_t i = 0; i < mods.size(); ++i)
171 {
172 const uint64_t mod = mods[i];
173 const MontgomeryCtx ctx = montgomery_ctx(mod);
174 const Array<uint64_t> bases =
175 {0ULL, 1ULL, 2ULL, 5ULL, mod - 2, mod - 1, mod + 11};
176 expect_powers(ctx, bases, exponents);
177 }
178}
179
181{
182 const Array<uint64_t> bases = {0ULL, 1ULL, 2ULL, 5ULL, 7ULL, 8ULL, 9ULL, 17ULL};
183 const Array<uint64_t> exponents = {0ULL, 1ULL, 2ULL, 7ULL, 31ULL};
184
186 expect_products(kCtx9, bases, {0ULL, 1ULL, 3ULL, 4ULL, 8ULL, 9ULL, 14ULL});
187 expect_powers(kCtx9, bases, exponents);
188}
189
191{
192 constexpr uint64_t mod = 18446744073709551557ULL;
193 const MontgomeryCtx ctx = montgomery_ctx(mod);
194
195 expect_round_trip(ctx, {0ULL, 1ULL, 2ULL, mod - 2, mod - 1});
196 expect_products(ctx, {mod - 1, mod - 2, mod - 3},
197 {mod - 4, mod - 5, mod - 6});
198
199 EXPECT_EQ(from_mont(mont_exp(to_mont(mod - 1, ctx), 5, ctx), ctx),
200 mod_exp(mod - 1, 5, mod));
201}
202
203#endif
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
#define TEST(name)
static mt19937 rng
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_exp_function > > exp(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4066
Safe modular arithmetic, extended Euclidean algorithm, and Chinese Remainder Theorem.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
uint64_t mod_exp(uint64_t base, uint64_t exp, const uint64_t m)
Modular exponentiation.
uint64_t mod_mul(uint64_t a, uint64_t b, uint64_t m)
Safe 64-bit modular multiplication.
double mod(double a, double b)
static int * k