t-aors_1.c revision 1.1.1.3 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.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26
27
28 #define M GMP_NUMB_MAX
29 #define ASIZE 10
30 #define MAGIC 0x1234
31
32 #define SETUP() \
33 do { \
34 refmpn_random (got, data[i].size); \
35 got[data[i].size] = MAGIC; \
36 } while (0)
37
38 #define SETUP_INPLACE() \
39 do { \
40 refmpn_copyi (got, data[i].src, data[i].size); \
41 got[data[i].size] = MAGIC; \
42 } while (0)
43
44 #define VERIFY(name) \
45 do { \
46 verify (name, i, data[i].src, data[i].n, \
47 got_c, data[i].want_c, \
48 got, data[i].want, data[i].size); \
49 } while (0)
50
51 typedef mp_limb_t (*mpn_aors_1_t) (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
52 mpn_aors_1_t fudge (mpn_aors_1_t);
53
54
55 void
56 verify (const char *name, int i,
57 mp_srcptr src, mp_limb_t n,
58 mp_limb_t got_c, mp_limb_t want_c,
59 mp_srcptr got, mp_srcptr want, mp_size_t size)
60 {
61 if (got[size] != MAGIC)
62 {
63 printf ("Overwrite at %s i=%d\n", name, i);
64 abort ();
65 }
66
67 if (got_c != want_c || ! refmpn_equal_anynail (got, want, size))
68 {
69 printf ("Wrong at %s i=%d size=%ld\n", name, i, size);
70 mpn_trace (" src", src, size);
71 mpn_trace (" n", &n, (mp_size_t) 1);
72 mpn_trace (" got", got, size);
73 mpn_trace (" want", want, size);
74 mpn_trace (" got c", &got_c, (mp_size_t) 1);
75 mpn_trace ("want c", &want_c, (mp_size_t) 1);
76 abort ();
77 }
78 }
79
80
81 void
82 check_add_1 (void)
83 {
84 static const struct {
85 mp_size_t size;
86 mp_limb_t n;
87 const mp_limb_t src[ASIZE];
88 mp_limb_t want_c;
89 const mp_limb_t want[ASIZE];
90 } data[] = {
91 { 1, 0, { 0 }, 0, { 0 } },
92 { 1, 0, { 1 }, 0, { 1 } },
93 { 1, 1, { 0 }, 0, { 1 } },
94 { 1, 0, { M }, 0, { M } },
95 { 1, M, { 0 }, 0, { M } },
96 { 1, 1, { 123 }, 0, { 124 } },
97
98 { 1, 1, { M }, 1, { 0 } },
99 { 1, M, { 1 }, 1, { 0 } },
100 { 1, M, { M }, 1, { M-1 } },
101
102 { 2, 0, { 0, 0 }, 0, { 0, 0 } },
103 { 2, 0, { 1, 0 }, 0, { 1, 0 } },
104 { 2, 1, { 0, 0 }, 0, { 1, 0 } },
105 { 2, 0, { M, 0 }, 0, { M, 0 } },
106 { 2, M, { 0, 0 }, 0, { M, 0 } },
107 { 2, 1, { M, 0 }, 0, { 0, 1 } },
108 { 2, M, { 1, 0 }, 0, { 0, 1 } },
109 { 2, M, { M, 0 }, 0, { M-1, 1 } },
110 { 2, M, { M, 0 }, 0, { M-1, 1 } },
111
112 { 2, 1, { M, M }, 1, { 0, 0 } },
113 { 2, M, { 1, M }, 1, { 0, 0 } },
114 { 2, M, { M, M }, 1, { M-1, 0 } },
115 { 2, M, { M, M }, 1, { M-1, 0 } },
116
117 { 3, 1, { M, M, M }, 1, { 0, 0, 0 } },
118 { 3, M, { 1, M, M }, 1, { 0, 0, 0 } },
119 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } },
120 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } },
121
122 { 4, 1, { M, M, M, M }, 1, { 0, 0, 0, 0 } },
123 { 4, M, { 1, M, M, M }, 1, { 0, 0, 0, 0 } },
124 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } },
125 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } },
126
127 { 4, M, { M, 0, M, M }, 0, { M-1, 1, M, M } },
128 { 4, M, { M, M-1, M, M }, 0, { M-1, M, M, M } },
129
130 { 4, M, { M, M, 0, M }, 0, { M-1, 0, 1, M } },
131 { 4, M, { M, M, M-1, M }, 0, { M-1, 0, M, M } },
132 };
133
134 mp_limb_t got[ASIZE];
135 mp_limb_t got_c;
136 /* mpn_sec_add_a_itch(n) <= n */
137 mp_limb_t scratch[ASIZE];
138 int i;
139
140 for (i = 0; i < numberof (data); i++)
141 {
142 SETUP ();
143 got_c = mpn_add_1 (got, data[i].src, data[i].size, data[i].n);
144 VERIFY ("check_add_1 (separate)");
145
146 SETUP_INPLACE ();
147 got_c = mpn_add_1 (got, got, data[i].size, data[i].n);
148 VERIFY ("check_add_1 (in-place)");
149
150 SETUP ();
151 scratch [mpn_sec_add_1_itch(data[i].size)] = MAGIC;
152 got_c = mpn_sec_add_1 (got, data[i].src, data[i].size, data[i].n, scratch);
153 got_c ^= scratch [mpn_sec_add_1_itch(data[i].size)] ^ MAGIC;
154 VERIFY ("check_sec_add_1 (separate)");
155
156 SETUP_INPLACE ();
157 got_c = mpn_sec_add_1 (got, got, data[i].size, data[i].n, scratch);
158 VERIFY ("check_sec_add_1 (in-place)");
159
160 if (data[i].n == 1)
161 {
162 SETUP ();
163 got_c = mpn_add_1 (got, data[i].src, data[i].size, CNST_LIMB(1));
164 VERIFY ("check_add_1 (separate, const 1)");
165
166 SETUP_INPLACE ();
167 got_c = mpn_add_1 (got, got, data[i].size, CNST_LIMB(1));
168 VERIFY ("check_add_1 (in-place, const 1)");
169
170 SETUP ();
171 got_c = mpn_sec_add_1 (got, data[i].src, data[i].size,
172 CNST_LIMB(1), scratch);
173 VERIFY ("check_sec_add_1 (separate, const 1)");
174
175 SETUP_INPLACE ();
176 got_c = mpn_sec_add_1 (got, got, data[i].size,
177 CNST_LIMB(1), scratch);
178 VERIFY ("check_sec_add_1 (in-place, const 1)");
179 }
180
181 /* Same again on functions, not inlines. */
182 SETUP ();
183 got_c = (*fudge(mpn_add_1)) (got, data[i].src, data[i].size, data[i].n);
184 VERIFY ("check_add_1 (function, separate)");
185
186 SETUP_INPLACE ();
187 got_c = (*fudge(mpn_add_1)) (got, got, data[i].size, data[i].n);
188 VERIFY ("check_add_1 (function, in-place)");
189 }
190 }
191
192 void
193 check_sub_1 (void)
194 {
195 static const struct {
196 mp_size_t size;
197 mp_limb_t n;
198 const mp_limb_t src[ASIZE];
199 mp_limb_t want_c;
200 const mp_limb_t want[ASIZE];
201 } data[] = {
202 { 1, 0, { 0 }, 0, { 0 } },
203 { 1, 0, { 1 }, 0, { 1 } },
204 { 1, 1, { 1 }, 0, { 0 } },
205 { 1, 0, { M }, 0, { M } },
206 { 1, 1, { M }, 0, { M-1 } },
207 { 1, 1, { 123 }, 0, { 122 } },
208
209 { 1, 1, { 0 }, 1, { M } },
210 { 1, M, { 0 }, 1, { 1 } },
211
212 { 2, 0, { 0, 0 }, 0, { 0, 0 } },
213 { 2, 0, { 1, 0 }, 0, { 1, 0 } },
214 { 2, 1, { 1, 0 }, 0, { 0, 0 } },
215 { 2, 0, { M, 0 }, 0, { M, 0 } },
216 { 2, 1, { M, 0 }, 0, { M-1, 0 } },
217 { 2, 1, { 123, 0 }, 0, { 122, 0 } },
218
219 { 2, 1, { 0, 0 }, 1, { M, M } },
220 { 2, M, { 0, 0 }, 1, { 1, M } },
221
222 { 3, 0, { 0, 0, 0 }, 0, { 0, 0, 0 } },
223 { 3, 0, { 123, 0, 0 }, 0, { 123, 0, 0 } },
224
225 { 3, 1, { 0, 0, 0 }, 1, { M, M, M } },
226 { 3, M, { 0, 0, 0 }, 1, { 1, M, M } },
227
228 { 4, 1, { 0, 0, 0, 0 }, 1, { M, M, M, M } },
229 { 4, M, { 0, 0, 0, 0 }, 1, { 1, M, M, M } },
230
231 { 4, 1, { 0, 0, 1, 42 }, 0, { M, M, 0, 42 } },
232 { 4, M, { 0, 0, 123, 24 }, 0, { 1, M, 122, 24 } },
233 };
234
235 mp_limb_t got[ASIZE];
236 mp_limb_t got_c;
237 /* mpn_sec_sub_1_itch(n) <= n */
238 mp_limb_t scratch[ASIZE];
239 int i;
240
241 for (i = 0; i < numberof (data); i++)
242 {
243 SETUP ();
244 got_c = mpn_sub_1 (got, data[i].src, data[i].size, data[i].n);
245 VERIFY ("check_sub_1 (separate)");
246
247 SETUP_INPLACE ();
248 got_c = mpn_sub_1 (got, got, data[i].size, data[i].n);
249 VERIFY ("check_sub_1 (in-place)");
250
251 SETUP ();
252 scratch [mpn_sec_sub_1_itch(data[i].size)] = MAGIC;
253 got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size, data[i].n, scratch);
254 got_c ^= scratch [mpn_sec_sub_1_itch(data[i].size)] ^ MAGIC;
255 VERIFY ("check_sec_sub_1 (separate)");
256
257 SETUP_INPLACE ();
258 got_c = mpn_sec_sub_1 (got, got, data[i].size, data[i].n, scratch);
259 VERIFY ("check_sec_sub_1 (in-place)");
260
261 if (data[i].n == 1)
262 {
263 SETUP ();
264 got_c = mpn_sub_1 (got, data[i].src, data[i].size, CNST_LIMB(1));
265 VERIFY ("check_sub_1 (separate, const 1)");
266
267 SETUP_INPLACE ();
268 got_c = mpn_sub_1 (got, got, data[i].size, CNST_LIMB(1));
269 VERIFY ("check_sub_1 (in-place, const 1)");
270
271 SETUP ();
272 got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size,
273 CNST_LIMB(1), scratch);
274 VERIFY ("check_sec_sub_1 (separate, const 1)");
275
276 SETUP_INPLACE ();
277 got_c = mpn_sec_sub_1 (got, got, data[i].size,
278 CNST_LIMB(1), scratch);
279 VERIFY ("check_sec_sub_1 (in-place, const 1)");
280 }
281
282 /* Same again on functions, not inlines. */
283 SETUP ();
284 got_c = (*fudge(mpn_sub_1)) (got, data[i].src, data[i].size, data[i].n);
285 VERIFY ("check_sub_1 (function, separate)");
286
287 SETUP_INPLACE ();
288 got_c = (*fudge(mpn_sub_1)) (got, got, data[i].size, data[i].n);
289 VERIFY ("check_sub_1 (function, in-place)");
290 }
291 }
292
293 /* Try to prevent the optimizer inlining. */
294 mpn_aors_1_t
295 fudge (mpn_aors_1_t f)
296 {
297 return f;
298 }
299
300 int
301 main (void)
302 {
303 tests_start ();
304 mp_trace_base = -16;
305
306 check_add_1 ();
307 check_sub_1 ();
308
309 tests_end ();
310 exit (0);
311 }
312