1 /*
2  * @author TPOC: contact@palisade-crypto.org
3  *
4  * @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT)
5  * All rights reserved.
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution. THIS SOFTWARE IS
13  * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 /*
26   Description:
27   This code benchmarks functions of the math directory  of the PALISADE lattice
28   encryption library.
29 */
30 #define _USE_MATH_DEFINES
31 #include "benchmark/benchmark.h"
32 
33 #include "palisade.h"
34 
35 #include <iostream>
36 #include <vector>
37 
38 using namespace std;
39 using namespace lbcrypto;
40 
41 #define DO_BENCHMARK_TEMPLATE(X, Y) \
42   BENCHMARK_TEMPLATE(X, Y)->Unit(benchmark::kMicrosecond);
43 
44 // four simple benchmarks to test constructing BigInts
45 // typically the code to benchmark is in a 'function' that is then
46 // called within the actual benchmark.
47 
48 // test BigInt constants
49 template <typename I>
make_BigInt_constants(void)50 static void make_BigInt_constants(void) {  // function
51   I one(1);
52 }
53 
54 template <typename I>
BM_BigInt_constants(benchmark::State & state)55 void BM_BigInt_constants(benchmark::State& state) {  // benchmark
56   while (state.KeepRunning()) {
57     make_BigInt_constants<I>();
58   }
59 }
60 
DO_BENCHMARK_TEMPLATE(BM_BigInt_constants,M2Integer)61 DO_BENCHMARK_TEMPLATE(BM_BigInt_constants, M2Integer)
62 DO_BENCHMARK_TEMPLATE(BM_BigInt_constants, M4Integer)
63 #ifdef WITH_NTL
64 DO_BENCHMARK_TEMPLATE(BM_BigInt_constants, M6Integer)
65 #endif
66 DO_BENCHMARK_TEMPLATE(BM_BigInt_constants, NativeInteger)
67 
68 template <typename I>
69 static void make_BigInt_small_variables(void) {  // function
70   I a("10403"), b("103");
71 }
72 
73 template <typename I>
BM_BigInt_small_variables(benchmark::State & state)74 void BM_BigInt_small_variables(benchmark::State& state) {  // benchmark
75   while (state.KeepRunning()) {
76     make_BigInt_small_variables<I>();
77   }
78 }
79 
DO_BENCHMARK_TEMPLATE(BM_BigInt_small_variables,M2Integer)80 DO_BENCHMARK_TEMPLATE(BM_BigInt_small_variables, M2Integer)
81 DO_BENCHMARK_TEMPLATE(BM_BigInt_small_variables, M4Integer)
82 #ifdef WITH_NTL
83 DO_BENCHMARK_TEMPLATE(BM_BigInt_small_variables, M6Integer)
84 #endif
85 DO_BENCHMARK_TEMPLATE(BM_BigInt_small_variables, NativeInteger)
86 
87 template <typename I>
88 static void make_BigInt_large_variables(void) {  // function
89   I a("18446744073709551616"), b("18446744073709551617");
90 }
91 
92 template <typename I>
BM_BigInt_large_variables(benchmark::State & state)93 void BM_BigInt_large_variables(benchmark::State& state) {  // benchmark
94   while (state.KeepRunning()) {
95     make_BigInt_large_variables<I>();
96   }
97 }
98 
99 DO_BENCHMARK_TEMPLATE(BM_BigInt_large_variables, M2Integer)
100 DO_BENCHMARK_TEMPLATE(BM_BigInt_large_variables, M4Integer)
101 #ifdef WITH_NTL
102 DO_BENCHMARK_TEMPLATE(BM_BigInt_large_variables, M6Integer)
103 #endif
104 
105 static string smalla("10403"), smallb("103");
106 static string largea("18446744073709551616"), largeb("18446744073709551617");
107 
108 // add
109 template <typename I>
add_BigInt(const I & a,const I & b)110 static void add_BigInt(const I& a, const I& b) {  // function
111   __attribute__((unused)) I c = a + b;
112 }
113 
114 template <typename I>
BM_BigInt_Add(benchmark::State & state)115 static void BM_BigInt_Add(benchmark::State& state) {  // benchmark
116   I a(state.range(0) == 0 ? smalla : largea);
117   I b(state.range(0) == 0 ? smallb : largeb);
118 
119   while (state.KeepRunning()) {
120     add_BigInt(a, b);
121   }
122 }
123 
124 BENCHMARK_TEMPLATE(BM_BigInt_Add, M2Integer)
125     ->Unit(benchmark::kMicrosecond)
126     ->ArgName("Small")
127     ->Arg(0);
128 BENCHMARK_TEMPLATE(BM_BigInt_Add, M2Integer)
129     ->Unit(benchmark::kMicrosecond)
130     ->ArgName("Large")
131     ->Arg(1);
132 BENCHMARK_TEMPLATE(BM_BigInt_Add, M4Integer)
133     ->Unit(benchmark::kMicrosecond)
134     ->ArgName("Small")
135     ->Arg(0);
136 BENCHMARK_TEMPLATE(BM_BigInt_Add, M4Integer)
137     ->Unit(benchmark::kMicrosecond)
138     ->ArgName("Large")
139     ->Arg(1);
140 #ifdef WITH_NTL
141 BENCHMARK_TEMPLATE(BM_BigInt_Add, M6Integer)
142     ->Unit(benchmark::kMicrosecond)
143     ->ArgName("Small")
144     ->Arg(0);
145 BENCHMARK_TEMPLATE(BM_BigInt_Add, M6Integer)
146     ->Unit(benchmark::kMicrosecond)
147     ->ArgName("Large")
148     ->Arg(1);
149 #endif
150 BENCHMARK_TEMPLATE(BM_BigInt_Add, NativeInteger)
151     ->Unit(benchmark::kMicrosecond)
152     ->ArgName("Small")
153     ->Arg(0);
154 
155 // +=
156 template <typename I>
addeq_BigInt(I & a,const I & b)157 static void addeq_BigInt(I& a, const I& b) {  // function
158   a += b;
159 }
160 
161 template <typename I>
BM_BigInt_Addeq(benchmark::State & state)162 static void BM_BigInt_Addeq(benchmark::State& state) {  // benchmark
163   I b(state.range(0) == 0 ? smallb : largeb);
164 
165   while (state.KeepRunning()) {
166     I a(state.range(0) == 0 ? smalla : largea);
167     addeq_BigInt(a, b);
168   }
169 }
170 
171 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M2Integer)
172     ->Unit(benchmark::kMicrosecond)
173     ->ArgName("Small")
174     ->Arg(0);
175 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M2Integer)
176     ->Unit(benchmark::kMicrosecond)
177     ->ArgName("Large")
178     ->Arg(1);
179 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M4Integer)
180     ->Unit(benchmark::kMicrosecond)
181     ->ArgName("Small")
182     ->Arg(0);
183 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M4Integer)
184     ->Unit(benchmark::kMicrosecond)
185     ->ArgName("Large")
186     ->Arg(1);
187 #ifdef WITH_NTL
188 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M6Integer)
189     ->Unit(benchmark::kMicrosecond)
190     ->ArgName("Small")
191     ->Arg(0);
192 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, M6Integer)
193     ->Unit(benchmark::kMicrosecond)
194     ->ArgName("Large")
195     ->Arg(1);
196 #endif
197 BENCHMARK_TEMPLATE(BM_BigInt_Addeq, NativeInteger)
198     ->Unit(benchmark::kMicrosecond)
199     ->ArgName("Small")
200     ->Arg(0);
201 
202 // mult
203 template <typename I>
mult_BigInt(const I & a,const I & b)204 static void mult_BigInt(const I& a, const I& b) {  // function
205   __attribute__((unused)) I c1 = a * b;
206 }
207 
208 template <typename I>
BM_BigInt_Mult(benchmark::State & state)209 static void BM_BigInt_Mult(benchmark::State& state) {  // benchmark
210   I a(state.range(0) == 0 ? smalla : largea);
211   I b(state.range(0) == 0 ? smallb : largeb);
212 
213   while (state.KeepRunning()) {
214     mult_BigInt(a, b);
215   }
216 }
217 
218 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M2Integer)
219     ->Unit(benchmark::kMicrosecond)
220     ->ArgName("Small")
221     ->Arg(0);
222 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M2Integer)
223     ->Unit(benchmark::kMicrosecond)
224     ->ArgName("Large")
225     ->Arg(1);
226 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M4Integer)
227     ->Unit(benchmark::kMicrosecond)
228     ->ArgName("Small")
229     ->Arg(0);
230 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M4Integer)
231     ->Unit(benchmark::kMicrosecond)
232     ->ArgName("Large")
233     ->Arg(1);
234 #ifdef WITH_NTL
235 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M6Integer)
236     ->Unit(benchmark::kMicrosecond)
237     ->ArgName("Small")
238     ->Arg(0);
239 BENCHMARK_TEMPLATE(BM_BigInt_Mult, M6Integer)
240     ->Unit(benchmark::kMicrosecond)
241     ->ArgName("Large")
242     ->Arg(1);
243 #endif
244 BENCHMARK_TEMPLATE(BM_BigInt_Mult, NativeInteger)
245     ->Unit(benchmark::kMicrosecond)
246     ->ArgName("Small")
247     ->Arg(0);
248 
249 // *=
250 template <typename I>
multeq_BigInt(I & a,const I & b)251 static void multeq_BigInt(I& a, const I& b) {  // function
252   a *= b;
253 }
254 
255 template <typename I>
BM_BigInt_Multeq(benchmark::State & state)256 static void BM_BigInt_Multeq(benchmark::State& state) {  // benchmark
257   I b(state.range(0) == 0 ? smallb : largeb);
258 
259   while (state.KeepRunning()) {
260     I a(state.range(0) == 0 ? smalla : largea);
261     multeq_BigInt(a, b);
262   }
263 }
264 
265 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M2Integer)
266     ->Unit(benchmark::kMicrosecond)
267     ->ArgName("Small")
268     ->Arg(0);
269 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M2Integer)
270     ->Unit(benchmark::kMicrosecond)
271     ->ArgName("Large")
272     ->Arg(1);
273 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M4Integer)
274     ->Unit(benchmark::kMicrosecond)
275     ->ArgName("Small")
276     ->Arg(0);
277 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M4Integer)
278     ->Unit(benchmark::kMicrosecond)
279     ->ArgName("Large")
280     ->Arg(1);
281 #ifdef WITH_NTL
282 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M6Integer)
283     ->Unit(benchmark::kMicrosecond)
284     ->ArgName("Small")
285     ->Arg(0);
286 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, M6Integer)
287     ->Unit(benchmark::kMicrosecond)
288     ->ArgName("Large")
289     ->Arg(1);
290 #endif
291 BENCHMARK_TEMPLATE(BM_BigInt_Multeq, NativeInteger)
292     ->Unit(benchmark::kMicrosecond)
293     ->ArgName("Small")
294     ->Arg(0);
295 
296 template <typename I>
BM_BigInt_ModInverse(benchmark::State & state)297 static void BM_BigInt_ModInverse(benchmark::State& state) {  // benchmark
298   while (state.KeepRunning()) {
299     I c = I(3017).ModInverse(I(108));
300     PALISADE_UNUSED(c);
301   }
302 }
303 
304 BENCHMARK_TEMPLATE(BM_BigInt_ModInverse, M2Integer)
305     ->Unit(benchmark::kMicrosecond);
306 BENCHMARK_TEMPLATE(BM_BigInt_ModInverse, M4Integer)
307     ->Unit(benchmark::kMicrosecond);
308 #ifdef WITH_NTL
309 BENCHMARK_TEMPLATE(BM_BigInt_ModInverse, M6Integer)
310     ->Unit(benchmark::kMicrosecond);
311 #endif
312 BENCHMARK_TEMPLATE(BM_BigInt_ModInverse, NativeInteger)
313     ->Unit(benchmark::kMicrosecond);
314 
315 template <typename I>
BM_BigInt_ModInverseEq(benchmark::State & state)316 static void BM_BigInt_ModInverseEq(benchmark::State& state) {  // benchmark
317   while (state.KeepRunning()) {
318     I(3017).ModInverseEq(I(108));
319   }
320 }
321 
322 BENCHMARK_TEMPLATE(BM_BigInt_ModInverseEq, M2Integer)
323     ->Unit(benchmark::kMicrosecond);
324 BENCHMARK_TEMPLATE(BM_BigInt_ModInverseEq, M4Integer)
325     ->Unit(benchmark::kMicrosecond);
326 #ifdef WITH_NTL
327 BENCHMARK_TEMPLATE(BM_BigInt_ModInverseEq, M6Integer)
328     ->Unit(benchmark::kMicrosecond);
329 #endif
330 BENCHMARK_TEMPLATE(BM_BigInt_ModInverseEq, NativeInteger)
331     ->Unit(benchmark::kMicrosecond);
332 
333 // execute the benchmarks
334 BENCHMARK_MAIN();
335