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