1 /* Test mpn_add_1 and mpn_sub_1.
2 
3 Copyright 2001, 2002 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "gmp-impl.h"
24 #include "tests.h"
25 
26 
27 #define M      GMP_NUMB_MAX
28 #define ASIZE  10
29 #define MAGIC  0x1234
30 
31 #define SETUP()                         \
32   do {                                  \
33     refmpn_random (got, data[i].size);  \
34     got[data[i].size] = MAGIC;          \
35   } while (0)
36 
37 #define SETUP_INPLACE()                                 \
38   do {                                                  \
39     refmpn_copyi (got, data[i].src, data[i].size);      \
40     got[data[i].size] = MAGIC;                          \
41   } while (0)
42 
43 #define VERIFY(name)                            \
44   do {                                          \
45     verify (name, i, data[i].src, data[i].n,    \
46             got_c, data[i].want_c,              \
47             got, data[i].want, data[i].size);   \
48   } while (0)
49 
50 typedef mp_limb_t (*mpn_aors_1_t) (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
51 mpn_aors_1_t fudge (mpn_aors_1_t);
52 
53 
54 void
verify(const char * name,int i,mp_srcptr src,mp_limb_t n,mp_limb_t got_c,mp_limb_t want_c,mp_srcptr got,mp_srcptr want,mp_size_t size)55 verify (const char *name, int i,
56         mp_srcptr src, mp_limb_t n,
57         mp_limb_t got_c, mp_limb_t want_c,
58         mp_srcptr got, mp_srcptr want, mp_size_t size)
59 {
60   if (got[size] != MAGIC)
61     {
62       printf ("Overwrite at %s i=%d\n", name, i);
63       abort ();
64     }
65 
66   if (got_c != want_c || ! refmpn_equal_anynail (got, want, size))
67     {
68       printf ("Wrong at %s i=%d size=%ld\n", name, i, size);
69       mpn_trace ("   src", src,  size);
70       mpn_trace ("     n", &n,   (mp_size_t) 1);
71       mpn_trace ("   got", got,  size);
72       mpn_trace ("  want", want, size);
73       mpn_trace (" got c", &got_c,  (mp_size_t) 1);
74       mpn_trace ("want c", &want_c, (mp_size_t) 1);
75       abort ();
76     }
77 }
78 
79 
80 void
check_add_1(void)81 check_add_1 (void)
82 {
83   static const struct {
84     mp_size_t        size;
85     mp_limb_t        n;
86     const mp_limb_t  src[ASIZE];
87     mp_limb_t        want_c;
88     const mp_limb_t  want[ASIZE];
89   } data[] = {
90     { 1, 0, { 0 },  0, { 0 } },
91     { 1, 0, { 1 },  0, { 1 } },
92     { 1, 1, { 0 },  0, { 1 } },
93     { 1, 0, { M },  0, { M } },
94     { 1, M, { 0 },  0, { M } },
95     { 1, 1, { 123 }, 0, { 124 } },
96 
97     { 1, 1, { M },  1, { 0 } },
98     { 1, M, { 1 },  1, { 0 } },
99     { 1, M, { M },  1, { M-1 } },
100 
101     { 2, 0, { 0, 0 },  0, { 0, 0 } },
102     { 2, 0, { 1, 0 },  0, { 1, 0 } },
103     { 2, 1, { 0, 0 },  0, { 1, 0 } },
104     { 2, 0, { M, 0 },  0, { M, 0 } },
105     { 2, M, { 0, 0 },  0, { M, 0 } },
106     { 2, 1, { M, 0 },  0, { 0, 1 } },
107     { 2, M, { 1, 0 },  0, { 0, 1 } },
108     { 2, M, { M, 0 },  0, { M-1, 1 } },
109     { 2, M, { M, 0 },  0, { M-1, 1 } },
110 
111     { 2, 1, { M, M },  1, { 0, 0 } },
112     { 2, M, { 1, M },  1, { 0, 0 } },
113     { 2, M, { M, M },  1, { M-1, 0 } },
114     { 2, M, { M, M },  1, { M-1, 0 } },
115 
116     { 3, 1, { M, M, M },  1, { 0, 0, 0 } },
117     { 3, M, { 1, M, M },  1, { 0, 0, 0 } },
118     { 3, M, { M, M, M },  1, { M-1, 0, 0 } },
119     { 3, M, { M, M, M },  1, { M-1, 0, 0 } },
120 
121     { 4, 1, { M, M, M, M },  1, { 0, 0, 0, 0 } },
122     { 4, M, { 1, M, M, M },  1, { 0, 0, 0, 0 } },
123     { 4, M, { M, M, M, M },  1, { M-1, 0, 0, 0 } },
124     { 4, M, { M, M, M, M },  1, { M-1, 0, 0, 0 } },
125 
126     { 4, M, { M, 0,   M, M },  0, { M-1, 1, M, M } },
127     { 4, M, { M, M-1, M, M },  0, { M-1, M, M, M } },
128 
129     { 4, M, { M, M, 0,   M },  0, { M-1, 0, 1, M } },
130     { 4, M, { M, M, M-1, M },  0, { M-1, 0, M, M } },
131   };
132 
133   mp_limb_t  got[ASIZE];
134   mp_limb_t  got_c;
135   /* mpn_sec_add_a_itch(n) <= n */
136   mp_limb_t  scratch[ASIZE];
137   int        i;
138 
139   for (i = 0; i < numberof (data); i++)
140     {
141       SETUP ();
142       got_c = mpn_add_1 (got, data[i].src, data[i].size, data[i].n);
143       VERIFY ("check_add_1 (separate)");
144 
145       SETUP_INPLACE ();
146       got_c = mpn_add_1 (got, got, data[i].size, data[i].n);
147       VERIFY ("check_add_1 (in-place)");
148 
149       SETUP ();
150       scratch [mpn_sec_add_1_itch(data[i].size)] = MAGIC;
151       got_c = mpn_sec_add_1 (got, data[i].src, data[i].size, data[i].n, scratch);
152       got_c ^= scratch [mpn_sec_add_1_itch(data[i].size)] ^ MAGIC;
153       VERIFY ("check_sec_add_1 (separate)");
154 
155       SETUP_INPLACE ();
156       got_c = mpn_sec_add_1 (got, got, data[i].size, data[i].n, scratch);
157       VERIFY ("check_sec_add_1 (in-place)");
158 
159       if (data[i].n == 1)
160         {
161           SETUP ();
162           got_c = mpn_add_1 (got, data[i].src, data[i].size, CNST_LIMB(1));
163           VERIFY ("check_add_1 (separate, const 1)");
164 
165           SETUP_INPLACE ();
166           got_c = mpn_add_1 (got, got, data[i].size, CNST_LIMB(1));
167           VERIFY ("check_add_1 (in-place, const 1)");
168 
169           SETUP ();
170           got_c = mpn_sec_add_1 (got, data[i].src, data[i].size,
171 				 CNST_LIMB(1), scratch);
172           VERIFY ("check_sec_add_1 (separate, const 1)");
173 
174           SETUP_INPLACE ();
175           got_c = mpn_sec_add_1 (got, got, data[i].size,
176 				 CNST_LIMB(1), scratch);
177           VERIFY ("check_sec_add_1 (in-place, const 1)");
178         }
179 
180       /* Same again on functions, not inlines. */
181       SETUP ();
182       got_c = (*fudge(mpn_add_1)) (got, data[i].src, data[i].size, data[i].n);
183       VERIFY ("check_add_1 (function, separate)");
184 
185       SETUP_INPLACE ();
186       got_c = (*fudge(mpn_add_1)) (got, got, data[i].size, data[i].n);
187       VERIFY ("check_add_1 (function, in-place)");
188     }
189 }
190 
191 void
check_sub_1(void)192 check_sub_1 (void)
193 {
194   static const struct {
195     mp_size_t        size;
196     mp_limb_t        n;
197     const mp_limb_t  src[ASIZE];
198     mp_limb_t        want_c;
199     const mp_limb_t  want[ASIZE];
200   } data[] = {
201     { 1, 0, { 0 },  0, { 0 } },
202     { 1, 0, { 1 },  0, { 1 } },
203     { 1, 1, { 1 },  0, { 0 } },
204     { 1, 0, { M },  0, { M } },
205     { 1, 1, { M },  0, { M-1 } },
206     { 1, 1, { 123 }, 0, { 122 } },
207 
208     { 1, 1, { 0 },  1, { M } },
209     { 1, M, { 0 },  1, { 1 } },
210 
211     { 2, 0, { 0, 0 },  0, { 0, 0 } },
212     { 2, 0, { 1, 0 },  0, { 1, 0 } },
213     { 2, 1, { 1, 0 },  0, { 0, 0 } },
214     { 2, 0, { M, 0 },  0, { M, 0 } },
215     { 2, 1, { M, 0 },  0, { M-1, 0 } },
216     { 2, 1, { 123, 0 }, 0, { 122, 0 } },
217 
218     { 2, 1, { 0, 0 },  1, { M, M } },
219     { 2, M, { 0, 0 },  1, { 1, M } },
220 
221     { 3, 0, { 0,   0, 0 },  0, { 0,   0, 0 } },
222     { 3, 0, { 123, 0, 0 },  0, { 123, 0, 0 } },
223 
224     { 3, 1, { 0, 0, 0 },  1, { M, M, M } },
225     { 3, M, { 0, 0, 0 },  1, { 1, M, M } },
226 
227     { 4, 1, { 0, 0, 0, 0 },  1, { M, M, M, M } },
228     { 4, M, { 0, 0, 0, 0 },  1, { 1, M, M, M } },
229 
230     { 4, 1, { 0, 0, 1,   42 },  0, { M, M, 0,   42 } },
231     { 4, M, { 0, 0, 123, 24 },  0, { 1, M, 122, 24 } },
232   };
233 
234   mp_limb_t  got[ASIZE];
235   mp_limb_t  got_c;
236   /* mpn_sec_sub_1_itch(n) <= n */
237   mp_limb_t  scratch[ASIZE];
238   int        i;
239 
240   for (i = 0; i < numberof (data); i++)
241     {
242       SETUP ();
243       got_c = mpn_sub_1 (got, data[i].src, data[i].size, data[i].n);
244       VERIFY ("check_sub_1 (separate)");
245 
246       SETUP_INPLACE ();
247       got_c = mpn_sub_1 (got, got, data[i].size, data[i].n);
248       VERIFY ("check_sub_1 (in-place)");
249 
250       SETUP ();
251       scratch [mpn_sec_sub_1_itch(data[i].size)] = MAGIC;
252       got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size, data[i].n, scratch);
253       got_c ^= scratch [mpn_sec_sub_1_itch(data[i].size)] ^ MAGIC;
254       VERIFY ("check_sec_sub_1 (separate)");
255 
256       SETUP_INPLACE ();
257       got_c = mpn_sec_sub_1 (got, got, data[i].size, data[i].n, scratch);
258       VERIFY ("check_sec_sub_1 (in-place)");
259 
260       if (data[i].n == 1)
261         {
262           SETUP ();
263           got_c = mpn_sub_1 (got, data[i].src, data[i].size, CNST_LIMB(1));
264           VERIFY ("check_sub_1 (separate, const 1)");
265 
266           SETUP_INPLACE ();
267           got_c = mpn_sub_1 (got, got, data[i].size, CNST_LIMB(1));
268           VERIFY ("check_sub_1 (in-place, const 1)");
269 
270           SETUP ();
271           got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size,
272 				 CNST_LIMB(1), scratch);
273           VERIFY ("check_sec_sub_1 (separate, const 1)");
274 
275           SETUP_INPLACE ();
276           got_c = mpn_sec_sub_1 (got, got, data[i].size,
277 				 CNST_LIMB(1), scratch);
278           VERIFY ("check_sec_sub_1 (in-place, const 1)");
279         }
280 
281       /* Same again on functions, not inlines. */
282       SETUP ();
283       got_c = (*fudge(mpn_sub_1)) (got, data[i].src, data[i].size, data[i].n);
284       VERIFY ("check_sub_1 (function, separate)");
285 
286       SETUP_INPLACE ();
287       got_c = (*fudge(mpn_sub_1)) (got, got, data[i].size, data[i].n);
288       VERIFY ("check_sub_1 (function, in-place)");
289     }
290 }
291 
292 /* Try to prevent the optimizer inlining. */
293 mpn_aors_1_t
fudge(mpn_aors_1_t f)294 fudge (mpn_aors_1_t f)
295 {
296   return f;
297 }
298 
299 int
main(void)300 main (void)
301 {
302   tests_start ();
303   mp_trace_base = -16;
304 
305   check_add_1 ();
306   check_sub_1 ();
307 
308   tests_end ();
309   exit (0);
310 }
311