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