xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/math_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2018 Google LLC
3*14675a02SAndroid Build Coastguard Worker  *
4*14675a02SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker  *
8*14675a02SAndroid Build Coastguard Worker  *     https://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker  *
10*14675a02SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker  * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker  */
16*14675a02SAndroid Build Coastguard Worker 
17*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/math.h"
18*14675a02SAndroid Build Coastguard Worker 
19*14675a02SAndroid Build Coastguard Worker #include <cstdint>
20*14675a02SAndroid Build Coastguard Worker 
21*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
22*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
23*14675a02SAndroid Build Coastguard Worker 
24*14675a02SAndroid Build Coastguard Worker namespace fcp {
25*14675a02SAndroid Build Coastguard Worker namespace secagg {
26*14675a02SAndroid Build Coastguard Worker namespace {
27*14675a02SAndroid Build Coastguard Worker 
28*14675a02SAndroid Build Coastguard Worker using ::testing::Eq;
29*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,DivideRoundUpIsAccurate)30*14675a02SAndroid Build Coastguard Worker TEST(MathTest, DivideRoundUpIsAccurate) {
31*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(0, 8), Eq(0));
32*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(1, 8), Eq(1));
33*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(8, 8), Eq(1));
34*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(12, 8), Eq(2));
35*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(31, 8), Eq(4));
36*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(32, 8), Eq(4));
37*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(DivideRoundUp(33, 8), Eq(5));
38*14675a02SAndroid Build Coastguard Worker }
39*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,AddModIsAccurate)40*14675a02SAndroid Build Coastguard Worker TEST(MathTest, AddModIsAccurate) {
41*14675a02SAndroid Build Coastguard Worker   // power-of-2 moduli
42*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(2, 5, 8), Eq(7));
43*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(4, 5, 8), Eq(1));
44*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(0, 5, 8), Eq(5));
45*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(5, 0, 8), Eq(5));
46*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(7, 7, 8), Eq(6));
47*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(9223372036854775806ULL, 9223372036854775807ULL,
48*14675a02SAndroid Build Coastguard Worker                      9223372036854775808ULL),
49*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775805ULL));
50*14675a02SAndroid Build Coastguard Worker 
51*14675a02SAndroid Build Coastguard Worker   // non-power-of-2 moduli
52*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(2, 5, 7), Eq(0));
53*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(4, 5, 7), Eq(2));
54*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(0, 5, 7), Eq(5));
55*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(5, 0, 7), Eq(5));
56*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(7, 7, 7), Eq(0));
57*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddMod(9223372036854775805ULL, 9223372036854775806ULL,
58*14675a02SAndroid Build Coastguard Worker                      9223372036854775807ULL),
59*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775804ULL));
60*14675a02SAndroid Build Coastguard Worker }
61*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,AddModOptIsAccurate)62*14675a02SAndroid Build Coastguard Worker TEST(MathTest, AddModOptIsAccurate) {
63*14675a02SAndroid Build Coastguard Worker   // power-of-2 moduli
64*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(2, 5, 8), Eq(7));
65*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(4, 5, 8), Eq(1));
66*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(0, 5, 8), Eq(5));
67*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(5, 0, 8), Eq(5));
68*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(7, 7, 8), Eq(6));
69*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(9223372036854775806ULL, 9223372036854775807ULL,
70*14675a02SAndroid Build Coastguard Worker                         9223372036854775808ULL),
71*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775805ULL));
72*14675a02SAndroid Build Coastguard Worker 
73*14675a02SAndroid Build Coastguard Worker   // non-power-of-2 moduli
74*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(2, 5, 7), Eq(0));
75*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(4, 5, 7), Eq(2));
76*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(0, 5, 7), Eq(5));
77*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(5, 0, 7), Eq(5));
78*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(6, 6, 7), Eq(5));
79*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(AddModOpt(9223372036854775805ULL, 9223372036854775806ULL,
80*14675a02SAndroid Build Coastguard Worker                         9223372036854775807ULL),
81*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775804ULL));
82*14675a02SAndroid Build Coastguard Worker }
83*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,SubtractModWorksAndHandlesUnderflow)84*14675a02SAndroid Build Coastguard Worker TEST(MathTest, SubtractModWorksAndHandlesUnderflow) {
85*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(3, 4, 10), Eq(9));
86*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(2, 9, 10), Eq(3));
87*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(0, 6, 10), Eq(4));
88*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(0, 5, 10), Eq(5));
89*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(7, 3, 10), Eq(4));
90*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(9, 0, 10), Eq(9));
91*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(0, 0, 10), Eq(0));
92*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(7, 7, 10), Eq(0));
93*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(9223372036854775807ULL, 0, 9223372036854775808ULL),
94*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775807ULL));
95*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(0, 9223372036854775807ULL, 9223372036854775808ULL),
96*14675a02SAndroid Build Coastguard Worker               Eq(1));
97*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(9223372036854775805ULL, 9223372036854775807ULL,
98*14675a02SAndroid Build Coastguard Worker                           9223372036854775808ULL),
99*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
100*14675a02SAndroid Build Coastguard Worker 
101*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(9223372036854775806ULL, 0, 9223372036854775807ULL),
102*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
103*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(0, 9223372036854775806ULL, 9223372036854775807ULL),
104*14675a02SAndroid Build Coastguard Worker               Eq(1));
105*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractMod(9223372036854775805ULL, 9223372036854775806ULL,
106*14675a02SAndroid Build Coastguard Worker                           9223372036854775807ULL),
107*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
108*14675a02SAndroid Build Coastguard Worker }
109*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,SubtractModOptWorksAndHandlesUnderflow)110*14675a02SAndroid Build Coastguard Worker TEST(MathTest, SubtractModOptWorksAndHandlesUnderflow) {
111*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(3, 4, 10), Eq(9));
112*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(2, 9, 10), Eq(3));
113*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(0, 6, 10), Eq(4));
114*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(0, 5, 10), Eq(5));
115*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(7, 3, 10), Eq(4));
116*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(9, 0, 10), Eq(9));
117*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(0, 0, 10), Eq(0));
118*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(7, 7, 10), Eq(0));
119*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(9223372036854775807ULL, 0, 9223372036854775808ULL),
120*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775807ULL));
121*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(0, 9223372036854775807ULL, 9223372036854775808ULL),
122*14675a02SAndroid Build Coastguard Worker               Eq(1));
123*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(9223372036854775805ULL, 9223372036854775807ULL,
124*14675a02SAndroid Build Coastguard Worker                              9223372036854775808ULL),
125*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
126*14675a02SAndroid Build Coastguard Worker 
127*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(9223372036854775806ULL, 0, 9223372036854775807ULL),
128*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
129*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(0, 9223372036854775806ULL, 9223372036854775807ULL),
130*14675a02SAndroid Build Coastguard Worker               Eq(1));
131*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(SubtractModOpt(9223372036854775805ULL, 9223372036854775806ULL,
132*14675a02SAndroid Build Coastguard Worker                              9223372036854775807ULL),
133*14675a02SAndroid Build Coastguard Worker               Eq(9223372036854775806ULL));
134*14675a02SAndroid Build Coastguard Worker }
135*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,MultiplyModAvoidsOverflow)136*14675a02SAndroid Build Coastguard Worker TEST(MathTest, MultiplyModAvoidsOverflow) {
137*14675a02SAndroid Build Coastguard Worker   uint64_t p = 2147483659ULL;  // 2 ^ 31 + 11; a prime number
138*14675a02SAndroid Build Coastguard Worker   uint32_t a = 2147483646;     // 2 ^ 31 - 2; -13 mod p
139*14675a02SAndroid Build Coastguard Worker   uint32_t b = 2147483640;     // 2 ^ 31 - 8; -19 mod p
140*14675a02SAndroid Build Coastguard Worker   uint32_t res1 = 169;         // -13 * -13
141*14675a02SAndroid Build Coastguard Worker   uint32_t res2 = 247;         // -13 * -19
142*14675a02SAndroid Build Coastguard Worker   uint32_t res3 = 361;         // -19 * -19
143*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(MultiplyMod(a, a, p), Eq(res1));
144*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(MultiplyMod(a, b, p), Eq(res2));
145*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(MultiplyMod(b, a, p), Eq(res2));
146*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(MultiplyMod(b, b, p), Eq(res3));
147*14675a02SAndroid Build Coastguard Worker }
148*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,MultiplyMod64AvoidsOverflow)149*14675a02SAndroid Build Coastguard Worker TEST(MathTest, MultiplyMod64AvoidsOverflow) {
150*14675a02SAndroid Build Coastguard Worker   {
151*14675a02SAndroid Build Coastguard Worker     uint64_t p = 2147483659ULL;  // 2 ^ 31 + 11; a prime number
152*14675a02SAndroid Build Coastguard Worker     uint32_t a = 2147483646;     // 2 ^ 31 - 2; -13 mod p
153*14675a02SAndroid Build Coastguard Worker     uint32_t b = 2147483640;     // 2 ^ 31 - 8; -19 mod p
154*14675a02SAndroid Build Coastguard Worker     uint32_t res1 = 169;         // -13 * -13
155*14675a02SAndroid Build Coastguard Worker     uint32_t res2 = 247;         // -13 * -19
156*14675a02SAndroid Build Coastguard Worker     uint32_t res3 = 361;         // -19 * -19
157*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(a, a, p), Eq(res1));
158*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(a, b, p), Eq(res2));
159*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(b, a, p), Eq(res2));
160*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(b, b, p), Eq(res3));
161*14675a02SAndroid Build Coastguard Worker   }
162*14675a02SAndroid Build Coastguard Worker 
163*14675a02SAndroid Build Coastguard Worker   {
164*14675a02SAndroid Build Coastguard Worker     uint64_t p = 4503599627371499ULL;     // 2 ^ 52 + 1003; a prime number
165*14675a02SAndroid Build Coastguard Worker     uint64_t a = 1099511627776ULL;        // 2 ^ 40
166*14675a02SAndroid Build Coastguard Worker     uint64_t b = 36028797018963971ULL;    // 2 ^ 55 + 3
167*14675a02SAndroid Build Coastguard Worker     uint64_t res1 = 4503330386609131ULL;  // a * a
168*14675a02SAndroid Build Coastguard Worker     uint64_t res2 = 188016488351702ULL;   // a * b
169*14675a02SAndroid Build Coastguard Worker     uint64_t res3 = 64336441ULL;          // b * b
170*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(a, a, p), Eq(res1));
171*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(a, b, p), Eq(res2));
172*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(b, a, p), Eq(res2));
173*14675a02SAndroid Build Coastguard Worker     EXPECT_THAT(MultiplyMod64(b, b, p), Eq(res3));
174*14675a02SAndroid Build Coastguard Worker   }
175*14675a02SAndroid Build Coastguard Worker }
TEST(MathTest,InverseModPrimeIsAccurate)176*14675a02SAndroid Build Coastguard Worker TEST(MathTest, InverseModPrimeIsAccurate) {
177*14675a02SAndroid Build Coastguard Worker   // All mods assumed to be prime
178*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(InverseModPrime(12, 31), Eq(13));
179*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(InverseModPrime(13, 31), Eq(12));
180*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(InverseModPrime(13, 2147483659ULL), Eq(1651910507));
181*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(InverseModPrime(2147483646, 2147483659ULL), Eq(495573152));
182*14675a02SAndroid Build Coastguard Worker }
183*14675a02SAndroid Build Coastguard Worker 
TEST(MathTest,IntToByteStringProvidesBigEndianString)184*14675a02SAndroid Build Coastguard Worker TEST(MathTest, IntToByteStringProvidesBigEndianString) {
185*14675a02SAndroid Build Coastguard Worker   uint32_t big_low_bits = 0x01234567;
186*14675a02SAndroid Build Coastguard Worker   uint32_t big_high_bits = 0xFEDCBA98;
187*14675a02SAndroid Build Coastguard Worker   uint32_t max_val = 0xFFFFFFFF;
188*14675a02SAndroid Build Coastguard Worker   uint32_t min_val = 0x00000000;
189*14675a02SAndroid Build Coastguard Worker   uint8_t expected0[4] = {0x1, 0x23, 0x45, 0x67};
190*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(IntToByteString(big_low_bits),
191*14675a02SAndroid Build Coastguard Worker               Eq(std::string(reinterpret_cast<char*>(expected0), 4)));
192*14675a02SAndroid Build Coastguard Worker   uint8_t expected1[4] = {0xFE, 0xDC, 0xBA, 0x98};
193*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(IntToByteString(big_high_bits),
194*14675a02SAndroid Build Coastguard Worker               Eq(std::string(reinterpret_cast<char*>(expected1), 4)));
195*14675a02SAndroid Build Coastguard Worker   uint8_t expected2[4] = {0xFF, 0xFF, 0xFF, 0xFF};
196*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(IntToByteString(max_val),
197*14675a02SAndroid Build Coastguard Worker               Eq(std::string(reinterpret_cast<char*>(expected2), 4)));
198*14675a02SAndroid Build Coastguard Worker   uint8_t expected3[4] = {0x0, 0x0, 0x0, 0x0};
199*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(IntToByteString(min_val),
200*14675a02SAndroid Build Coastguard Worker               Eq(std::string(reinterpret_cast<char*>(expected3), 4)));
201*14675a02SAndroid Build Coastguard Worker }
202*14675a02SAndroid Build Coastguard Worker 
203*14675a02SAndroid Build Coastguard Worker }  // namespace
204*14675a02SAndroid Build Coastguard Worker }  // namespace secagg
205*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
206