xref: /llvm-project/polly/lib/External/isl/imath/imtimer.c (revision 658eb9e14264d48888ade0e3daf0b648f76c3f0e)
1*658eb9e1SMichael Kruse /*
2*658eb9e1SMichael Kruse   Name:     imtimer.c
3*658eb9e1SMichael Kruse   Purpose:  Timing tests for the imath library.
4*658eb9e1SMichael Kruse   Author:   M. J. Fromberger
5*658eb9e1SMichael Kruse 
6*658eb9e1SMichael Kruse   Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
7*658eb9e1SMichael Kruse 
8*658eb9e1SMichael Kruse   Permission is hereby granted, free of charge, to any person obtaining a copy
9*658eb9e1SMichael Kruse   of this software and associated documentation files (the "Software"), to deal
10*658eb9e1SMichael Kruse   in the Software without restriction, including without limitation the rights
11*658eb9e1SMichael Kruse   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*658eb9e1SMichael Kruse   copies of the Software, and to permit persons to whom the Software is
13*658eb9e1SMichael Kruse   furnished to do so, subject to the following conditions:
14*658eb9e1SMichael Kruse 
15*658eb9e1SMichael Kruse   The above copyright notice and this permission notice shall be included in
16*658eb9e1SMichael Kruse   all copies or substantial portions of the Software.
17*658eb9e1SMichael Kruse 
18*658eb9e1SMichael Kruse   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*658eb9e1SMichael Kruse   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*658eb9e1SMichael Kruse   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21*658eb9e1SMichael Kruse   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*658eb9e1SMichael Kruse   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*658eb9e1SMichael Kruse   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*658eb9e1SMichael Kruse   SOFTWARE.
25*658eb9e1SMichael Kruse  */
26*658eb9e1SMichael Kruse 
27*658eb9e1SMichael Kruse #include <limits.h>
28*658eb9e1SMichael Kruse #include <stdio.h>
29*658eb9e1SMichael Kruse #include <stdlib.h>
30*658eb9e1SMichael Kruse #include <string.h>
31*658eb9e1SMichael Kruse #include <time.h>
32*658eb9e1SMichael Kruse 
33*658eb9e1SMichael Kruse #include <getopt.h>
34*658eb9e1SMichael Kruse #include <unistd.h>
35*658eb9e1SMichael Kruse 
36*658eb9e1SMichael Kruse #include "imath.h"
37*658eb9e1SMichael Kruse 
38*658eb9e1SMichael Kruse double clocks_to_seconds(clock_t start, clock_t end);
39*658eb9e1SMichael Kruse double get_multiply_time(int nt, int prec);
40*658eb9e1SMichael Kruse double get_exptmod_time(int nt, int prec);
41*658eb9e1SMichael Kruse mp_int alloc_values(int nt, int prec);
42*658eb9e1SMichael Kruse void randomize_values(mp_int values, int nt, int prec);
43*658eb9e1SMichael Kruse void release_values(mp_int values, int nt);
44*658eb9e1SMichael Kruse void mp_int_random(mp_int z, int prec);
45*658eb9e1SMichael Kruse 
46*658eb9e1SMichael Kruse const int g_mul_factor = 1000;
47*658eb9e1SMichael Kruse 
main(int argc,char * argv[])48*658eb9e1SMichael Kruse int main(int argc, char *argv[]) {
49*658eb9e1SMichael Kruse   int do_mul = 0, do_exp = 0, do_header = 1;
50*658eb9e1SMichael Kruse   int num_tests, precision = 0, opt;
51*658eb9e1SMichael Kruse   mp_size threshold = 0;
52*658eb9e1SMichael Kruse   unsigned int seed = (unsigned int)time(NULL);
53*658eb9e1SMichael Kruse 
54*658eb9e1SMichael Kruse   while ((opt = getopt(argc, argv, "ehmnp:s:t:")) != EOF) {
55*658eb9e1SMichael Kruse     switch (opt) {
56*658eb9e1SMichael Kruse       case 'e':
57*658eb9e1SMichael Kruse         do_exp = 1;
58*658eb9e1SMichael Kruse         break;
59*658eb9e1SMichael Kruse       case 'm':
60*658eb9e1SMichael Kruse         do_mul = 1;
61*658eb9e1SMichael Kruse         break;
62*658eb9e1SMichael Kruse       case 'n':
63*658eb9e1SMichael Kruse         do_header = 0;
64*658eb9e1SMichael Kruse         break;
65*658eb9e1SMichael Kruse       case 'p':
66*658eb9e1SMichael Kruse         precision = atoi(optarg);
67*658eb9e1SMichael Kruse         break;
68*658eb9e1SMichael Kruse       case 's':
69*658eb9e1SMichael Kruse         seed = atoi(optarg);
70*658eb9e1SMichael Kruse         break;
71*658eb9e1SMichael Kruse       case 't':
72*658eb9e1SMichael Kruse         threshold = (mp_size)atoi(optarg);
73*658eb9e1SMichael Kruse         break;
74*658eb9e1SMichael Kruse       default:
75*658eb9e1SMichael Kruse         fprintf(stderr,
76*658eb9e1SMichael Kruse                 "Usage:  imtimer [options] <num-tests>\n\n"
77*658eb9e1SMichael Kruse                 "Options understood:\n"
78*658eb9e1SMichael Kruse                 " -e        -- test modular exponentiation speed.\n"
79*658eb9e1SMichael Kruse                 " -h        -- display this help message.\n"
80*658eb9e1SMichael Kruse                 " -m        -- test multiplication speed.\n"
81*658eb9e1SMichael Kruse                 " -n        -- no header line.\n"
82*658eb9e1SMichael Kruse                 " -p <dig>  -- use values with <dig> digits.\n"
83*658eb9e1SMichael Kruse                 " -s <rnd>  -- set random seed to <rnd>.\n"
84*658eb9e1SMichael Kruse                 " -t <dig>  -- set recursion threshold to <dig> digits.\n\n");
85*658eb9e1SMichael Kruse         return (opt != 'h');
86*658eb9e1SMichael Kruse     }
87*658eb9e1SMichael Kruse   }
88*658eb9e1SMichael Kruse 
89*658eb9e1SMichael Kruse   if (optind >= argc) {
90*658eb9e1SMichael Kruse     fprintf(stderr,
91*658eb9e1SMichael Kruse             "Usage:  imtimer [options] <num-tests>\n"
92*658eb9e1SMichael Kruse             "[use \"imtimer -h\" for help with options]\n\n");
93*658eb9e1SMichael Kruse     return 1;
94*658eb9e1SMichael Kruse   } else
95*658eb9e1SMichael Kruse     num_tests = atoi(argv[optind]);
96*658eb9e1SMichael Kruse 
97*658eb9e1SMichael Kruse   srand(seed);
98*658eb9e1SMichael Kruse 
99*658eb9e1SMichael Kruse   if (num_tests <= 0) {
100*658eb9e1SMichael Kruse     fprintf(stderr, "You must request at least one test.\n");
101*658eb9e1SMichael Kruse     return 1;
102*658eb9e1SMichael Kruse   }
103*658eb9e1SMichael Kruse   if (precision < 0) {
104*658eb9e1SMichael Kruse     fprintf(stderr, "Precision must be non-negative (0 means default).\n");
105*658eb9e1SMichael Kruse     return 1;
106*658eb9e1SMichael Kruse   }
107*658eb9e1SMichael Kruse   mp_int_multiply_threshold(threshold);
108*658eb9e1SMichael Kruse 
109*658eb9e1SMichael Kruse   if (do_header) printf("NUM\tPREC\tBITS\tREC\tRESULT\n");
110*658eb9e1SMichael Kruse   printf("%d\t%d\t%d\t%u", num_tests, precision,
111*658eb9e1SMichael Kruse          (int)(precision * MP_DIGIT_BIT), threshold);
112*658eb9e1SMichael Kruse 
113*658eb9e1SMichael Kruse   if (do_mul) {
114*658eb9e1SMichael Kruse     double m_time = get_multiply_time(num_tests, precision);
115*658eb9e1SMichael Kruse 
116*658eb9e1SMichael Kruse     printf("\tMUL %.3f %.3f", m_time, m_time / num_tests);
117*658eb9e1SMichael Kruse   }
118*658eb9e1SMichael Kruse 
119*658eb9e1SMichael Kruse   if (do_exp) {
120*658eb9e1SMichael Kruse     double e_time = get_exptmod_time(num_tests, precision);
121*658eb9e1SMichael Kruse 
122*658eb9e1SMichael Kruse     printf("\tEXP %.3f %.3f", e_time, e_time / num_tests);
123*658eb9e1SMichael Kruse   }
124*658eb9e1SMichael Kruse   fputc('\n', stdout);
125*658eb9e1SMichael Kruse   fflush(stdout);
126*658eb9e1SMichael Kruse 
127*658eb9e1SMichael Kruse   return 0;
128*658eb9e1SMichael Kruse }
129*658eb9e1SMichael Kruse 
clocks_to_seconds(clock_t start,clock_t end)130*658eb9e1SMichael Kruse double clocks_to_seconds(clock_t start, clock_t end) {
131*658eb9e1SMichael Kruse   return (double)(end - start) / CLOCKS_PER_SEC;
132*658eb9e1SMichael Kruse }
133*658eb9e1SMichael Kruse 
alloc_values(int nt,int prec)134*658eb9e1SMichael Kruse mp_int alloc_values(int nt, int prec) {
135*658eb9e1SMichael Kruse   mp_int out = malloc(nt * sizeof(mpz_t));
136*658eb9e1SMichael Kruse   int i;
137*658eb9e1SMichael Kruse 
138*658eb9e1SMichael Kruse   if (out == NULL) return NULL;
139*658eb9e1SMichael Kruse 
140*658eb9e1SMichael Kruse   for (i = 0; i < nt; ++i) {
141*658eb9e1SMichael Kruse     if (mp_int_init_size(out + i, prec) != MP_OK) {
142*658eb9e1SMichael Kruse       while (--i >= 0) mp_int_clear(out + i);
143*658eb9e1SMichael Kruse       return NULL;
144*658eb9e1SMichael Kruse     }
145*658eb9e1SMichael Kruse   }
146*658eb9e1SMichael Kruse 
147*658eb9e1SMichael Kruse   return out;
148*658eb9e1SMichael Kruse }
149*658eb9e1SMichael Kruse 
randomize_values(mp_int values,int nt,int prec)150*658eb9e1SMichael Kruse void randomize_values(mp_int values, int nt, int prec) {
151*658eb9e1SMichael Kruse   int i;
152*658eb9e1SMichael Kruse 
153*658eb9e1SMichael Kruse   for (i = 0; i < nt; ++i) mp_int_random(values + i, prec);
154*658eb9e1SMichael Kruse }
155*658eb9e1SMichael Kruse 
release_values(mp_int values,int nt)156*658eb9e1SMichael Kruse void release_values(mp_int values, int nt) {
157*658eb9e1SMichael Kruse   int i;
158*658eb9e1SMichael Kruse 
159*658eb9e1SMichael Kruse   for (i = 0; i < nt; ++i) mp_int_clear(values + i);
160*658eb9e1SMichael Kruse 
161*658eb9e1SMichael Kruse   free(values);
162*658eb9e1SMichael Kruse }
163*658eb9e1SMichael Kruse 
get_multiply_time(int nt,int prec)164*658eb9e1SMichael Kruse double get_multiply_time(int nt, int prec) {
165*658eb9e1SMichael Kruse   clock_t start, end;
166*658eb9e1SMichael Kruse   mp_int values;
167*658eb9e1SMichael Kruse   int i;
168*658eb9e1SMichael Kruse 
169*658eb9e1SMichael Kruse   if ((values = alloc_values(3, prec)) == NULL) return 0.0;
170*658eb9e1SMichael Kruse   randomize_values(values, 2, prec);
171*658eb9e1SMichael Kruse 
172*658eb9e1SMichael Kruse   start = clock();
173*658eb9e1SMichael Kruse   for (i = 0; i < nt; ++i) mp_int_mul(values, values + 1, values + 2);
174*658eb9e1SMichael Kruse   end = clock();
175*658eb9e1SMichael Kruse 
176*658eb9e1SMichael Kruse   release_values(values, 3);
177*658eb9e1SMichael Kruse 
178*658eb9e1SMichael Kruse   return clocks_to_seconds(start, end);
179*658eb9e1SMichael Kruse }
180*658eb9e1SMichael Kruse 
get_exptmod_time(int nt,int prec)181*658eb9e1SMichael Kruse double get_exptmod_time(int nt, int prec) {
182*658eb9e1SMichael Kruse   clock_t start, end;
183*658eb9e1SMichael Kruse   mp_int values;
184*658eb9e1SMichael Kruse   int i;
185*658eb9e1SMichael Kruse 
186*658eb9e1SMichael Kruse   if ((values = alloc_values(4, prec)) == NULL) return 0.0;
187*658eb9e1SMichael Kruse   randomize_values(values, 3, prec);
188*658eb9e1SMichael Kruse 
189*658eb9e1SMichael Kruse   start = clock();
190*658eb9e1SMichael Kruse   for (i = 0; i < nt; ++i)
191*658eb9e1SMichael Kruse     mp_int_exptmod(values, values + 1, values + 2, values + 3);
192*658eb9e1SMichael Kruse   end = clock();
193*658eb9e1SMichael Kruse 
194*658eb9e1SMichael Kruse   release_values(values, 4);
195*658eb9e1SMichael Kruse 
196*658eb9e1SMichael Kruse   return clocks_to_seconds(start, end);
197*658eb9e1SMichael Kruse }
198*658eb9e1SMichael Kruse 
mp_int_random(mp_int z,int prec)199*658eb9e1SMichael Kruse void mp_int_random(mp_int z, int prec) {
200*658eb9e1SMichael Kruse   int i;
201*658eb9e1SMichael Kruse 
202*658eb9e1SMichael Kruse   if (prec > (int)MP_ALLOC(z)) prec = (int)MP_ALLOC(z);
203*658eb9e1SMichael Kruse 
204*658eb9e1SMichael Kruse   for (i = 0; i < prec; ++i) {
205*658eb9e1SMichael Kruse     mp_digit d = 0;
206*658eb9e1SMichael Kruse     int j;
207*658eb9e1SMichael Kruse 
208*658eb9e1SMichael Kruse     for (j = 0; j < (int)sizeof(d); ++j) {
209*658eb9e1SMichael Kruse       d = (d << CHAR_BIT) | (rand() & UCHAR_MAX);
210*658eb9e1SMichael Kruse     }
211*658eb9e1SMichael Kruse 
212*658eb9e1SMichael Kruse     z->digits[i] = d;
213*658eb9e1SMichael Kruse   }
214*658eb9e1SMichael Kruse   z->used = prec;
215*658eb9e1SMichael Kruse }
216