blob: ad5125b49c74e742161476bd05e1f982f6117d9b [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/*
2Copyright 1996, 1998-2001, 2004, 2007, 2009, 2011 Free Software Foundation,
3Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20#include <stdlib.h>
21#include <string.h>
22#include <stdio.h>
23#include "gmp-impl.h"
24#include "tests.h"
25
26#ifdef OPERATION_lshift
27#define func __gmpn_lshift
28#define reffunc refmpn_lshift
29#define funcname "mpn_lshift"
30#endif
31
32#ifdef OPERATION_rshift
33#define func __gmpn_rshift
34#define reffunc refmpn_rshift
35#define funcname "mpn_rshift"
36#endif
37
38#if defined (USG) || defined (__SVR4) || defined (_UNICOS) || defined (__hpux)
39#include <time.h>
40
41int
42cputime ()
43{
44 if (CLOCKS_PER_SEC < 100000)
45 return clock () * 1000 / CLOCKS_PER_SEC;
46 return clock () / (CLOCKS_PER_SEC / 1000);
47}
48#else
49#include <sys/types.h>
50#include <sys/time.h>
51#include <sys/resource.h>
52
53int
54cputime ()
55{
56 struct rusage rus;
57
58 getrusage (0, &rus);
59 return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
60}
61#endif
62
63static void print_posneg (mp_limb_t);
64static void mpn_print (mp_ptr, mp_size_t);
65
66#define LXW ((int) (2 * sizeof (mp_limb_t)))
67#define M * 1000000
68
69#ifndef CLOCK
70#error "Don't know CLOCK of your machine"
71#endif
72
73#ifndef OPS
74#define OPS (CLOCK/5)
75#endif
76#ifndef SIZE
77#define SIZE 496
78#endif
79#ifndef TIMES
80#define TIMES OPS/(SIZE+1)
81#endif
82
83#ifndef CNT
84int CNT = 4;
85#endif
86
87int
88main (int argc, char **argv)
89{
90 mp_ptr s1, dx, dy;
91 mp_limb_t cyx, cyy;
92 int i;
93 long t0, t;
94 unsigned int test;
95 int cnt = CNT;
96 mp_size_t size;
97 unsigned int ntests;
98
99 s1 = malloc (SIZE * sizeof (mp_limb_t));
100 dx = malloc ((SIZE + 2) * sizeof (mp_limb_t));
101 dy = malloc ((SIZE + 2) * sizeof (mp_limb_t));
102
103 ntests = ~(unsigned) 0;
104 if (argc == 2)
105 ntests = strtol (argv[1], 0, 0);
106
107 for (test = 1; test <= ntests; test++)
108 {
109#if TIMES == 1 && ! defined (PRINT)
110 if (test % (SIZE > 100000 ? 1 : 100000 / SIZE) == 0)
111 {
112 printf ("\r%u", test);
113 fflush (stdout);
114 }
115#endif
116
117#if TIMES == 1
118 cnt = random () % (GMP_NUMB_BITS - 1) + 1;
119#endif
120
121#ifdef RANDOM
122 size = random () % SIZE + 1;
123#else
124 size = SIZE;
125#endif
126
127 dx[0] = 0x87654321;
128 dy[0] = 0x87654321;
129 dx[size+1] = 0x12345678;
130 dy[size+1] = 0x12345678;
131
132#if TIMES != 1
133 mpn_random (s1, size);
134
135 t0 = cputime();
136 for (i = 0; i < TIMES; i++)
137 func (dx+1, s1, size, cnt);
138 t = cputime() - t0;
139 printf (funcname ": %5ldms (%.3f cycles/limb)\n",
140 t, ((double) t * CLOCK) / (TIMES * size * 1000.0));
141#endif
142
143#ifndef NOCHECK
144 mpn_random (s1, size);
145
146#ifdef PRINT
147 printf ("cnt=%-*d ", (int) (2 * sizeof(mp_limb_t)) - 4, cnt);
148 mpn_print (s1, size);
149#endif
150
151 /* Put garbage in the destination. */
152 for (i = 0; i < size; i++)
153 {
154 dx[i+1] = 0xdead;
155 dy[i+1] = 0xbeef;
156 }
157
158 cyx = reffunc (dx+1, s1, size, cnt);
159 cyy = func (dy+1, s1, size, cnt);
160
161#ifdef PRINT
162 mpn_print (&cyx, 1);
163 mpn_print (dx+1, size);
164 mpn_print (&cyy, 1);
165 mpn_print (dy+1, size);
166#endif
167
168 if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
169 || dx[0] != 0x87654321 || dx[size+1] != 0x12345678)
170 {
171 mp_size_t s, e;
172 for (s = 0;; s++)
173 if ((unsigned long long) (dx+1)[s] != (unsigned long long) (dy+1)[s])
174 break;
175 for (e = size - 1;; e--)
176 if ((unsigned long long) (dx+1)[e] != (unsigned long long) (dy+1)[e])
177 break;
178#ifndef PRINT
179 printf ("cnt=%-*d\n", (int) (2 * sizeof(mp_limb_t)) - 4, cnt);
180 for (i = s; i <= e; i++)
181 {
182 printf ("%6d: ", i);
183 printf ("%0*llX ", LXW, (unsigned long long) (dx+1)[i]);
184 printf ("%0*llX ", LXW, (unsigned long long) (dy+1)[i]);
185 print_posneg ((dy+1)[i] - (dx+1)[i]);
186 printf ("\n");
187 }
188 printf ("%6s: ", "retval");
189 printf ("%0*llX ", LXW, (unsigned long long) cyx);
190 printf ("%0*llX ", LXW, (unsigned long long) cyy);
191 print_posneg (cyx - cyy);
192#endif
193 printf ("\n");
194 if (dy[0] != 0x87654321)
195 printf ("clobbered at low end\n");
196 if (dy[size+1] != 0x12345678)
197 printf ("clobbered at high end\n");
198 printf ("TEST NUMBER %u\n", test);
199 abort();
200 }
201#endif
202 }
203 exit (0);
204}
205
206static void
207print_posneg (mp_limb_t d)
208{
209 char buf[LXW + 2];
210 if (d == 0)
211 printf (" %*X", LXW, 0);
212 else if (-d < d)
213 {
214 sprintf (buf, "%llX", (unsigned long long) -d);
215 printf ("%*s-%s", LXW - (int) strlen (buf), "", buf);
216 }
217 else
218 {
219 sprintf (buf, "%llX", (unsigned long long) d);
220 printf ("%*s+%s", LXW - (int) strlen (buf), "", buf);
221 }
222}
223
224static void
225mpn_print (mp_ptr p, mp_size_t size)
226{
227 mp_size_t i;
228
229 for (i = size - 1; i >= 0; i--)
230 {
231#ifdef _LONG_LONG_LIMB
232 printf ("%0*lX%0*lX", (int) (sizeof(mp_limb_t)),
233 (unsigned long) (p[i] >> (GMP_LIMB_BITS/2)),
234 (int) (sizeof(mp_limb_t)), (unsigned long) (p[i]));
235#else
236 printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
237#endif
238#ifdef SPACE
239 if (i != 0)
240 printf (" ");
241#endif
242 }
243 puts ("");
244}