1 /* Test mpz_limbs_* functions
2
3 Copyright 2013 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 <stdlib.h>
21 #include <stdio.h>
22
23 #include "gmp-impl.h"
24 #include "tests.h"
25
26 #define COUNT 100
27 #define BITSIZE 500
28
29 /* Like mpz_add. For simplicity, support positive inputs only. */
30 static void
alt_add(mpz_ptr r,mpz_srcptr a,mpz_srcptr b)31 alt_add (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
32 {
33 mp_size_t an = mpz_size (a);
34 mp_size_t bn = mpz_size (b);
35 mp_ptr rp;
36
37 ASSERT (an > 0);
38 ASSERT (bn > 0);
39 if (an < bn)
40 {
41 MP_SIZE_T_SWAP (an, bn);
42 MPZ_SRCPTR_SWAP (a, b);
43 }
44 rp = mpz_limbs_modify (r, an + 1);
45 rp[an] = mpn_add (rp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn);
46 mpz_limbs_finish (r, an + 1);
47 }
48
49 static void
check_funcs(const char * name,void (* f)(mpz_ptr,mpz_srcptr,mpz_srcptr),void (* ref_f)(mpz_ptr,mpz_srcptr,mpz_srcptr),mpz_srcptr a,mpz_srcptr b)50 check_funcs (const char *name,
51 void (*f)(mpz_ptr, mpz_srcptr, mpz_srcptr),
52 void (*ref_f)(mpz_ptr, mpz_srcptr, mpz_srcptr),
53 mpz_srcptr a, mpz_srcptr b)
54 {
55 mpz_t r, ref;
56 mpz_inits (r, ref, NULL);
57
58 ref_f (ref, a, b);
59 MPZ_CHECK_FORMAT (ref);
60 f (r, a, b);
61 MPZ_CHECK_FORMAT (r);
62
63 if (mpz_cmp (r, ref) != 0)
64 {
65 printf ("%s failed, abits %u, bbits %u\n",
66 name,
67 (unsigned) mpz_sizeinbase (a, 2),
68 (unsigned) mpz_sizeinbase (b, 2));
69 gmp_printf ("a = %Zx\n", a);
70 gmp_printf ("b = %Zx\n", b);
71 gmp_printf ("r = %Zx (bad)\n", r);
72 gmp_printf ("ref = %Zx\n", ref);
73 abort ();
74 }
75 mpz_clears (r, ref, NULL);
76 }
77
78 static void
check_add(void)79 check_add (void)
80 {
81 gmp_randstate_ptr rands = RANDS;
82 mpz_t bs, a, b;
83 unsigned i;
84 mpz_inits (bs, a, b, NULL);
85 for (i = 0; i < COUNT; i++)
86 {
87 mpz_urandomb (bs, rands, 32);
88 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
89 mpz_urandomb (bs, rands, 32);
90 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
91
92 check_funcs ("add", alt_add, mpz_add, a, b);
93 }
94 mpz_clears (bs, a, b, NULL);
95 }
96
97 static void
alt_mul(mpz_ptr r,mpz_srcptr a,mpz_srcptr b)98 alt_mul (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
99 {
100 mp_size_t an = mpz_size (a);
101 mp_size_t bn = mpz_size (b);
102 mp_srcptr ap, bp;
103 TMP_DECL;
104
105 TMP_MARK;
106
107 ASSERT (an > 0);
108 ASSERT (bn > 0);
109 if (an < bn)
110 {
111 MP_SIZE_T_SWAP (an, bn);
112 MPZ_SRCPTR_SWAP (a, b);
113 }
114 /* NOTE: This copying seems unnecessary; better to allocate new
115 result area, and free the old area when done. */
116 if (r == a)
117 {
118 mp_ptr tp = TMP_ALLOC_LIMBS (an);
119 MPN_COPY (tp, mpz_limbs_read (a), an);
120 ap = tp;
121 bp = (a == b) ? ap : mpz_limbs_read (b);
122 }
123 else if (r == b)
124 {
125 mp_ptr tp = TMP_ALLOC_LIMBS (bn);
126 MPN_COPY (tp, mpz_limbs_read (b), bn);
127 bp = tp;
128 ap = mpz_limbs_read (a);
129 }
130 else
131 {
132 ap = mpz_limbs_read (a);
133 bp = mpz_limbs_read (b);
134 }
135 mpn_mul (mpz_limbs_write (r, an + bn),
136 ap, an, bp, bn);
137
138 mpz_limbs_finish (r, an + bn);
139 }
140
141 void
check_mul(void)142 check_mul (void)
143 {
144 gmp_randstate_ptr rands = RANDS;
145 mpz_t bs, a, b;
146 unsigned i;
147 mpz_inits (bs, a, b, NULL);
148 for (i = 0; i < COUNT; i++)
149 {
150 mpz_urandomb (bs, rands, 32);
151 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
152 mpz_urandomb (bs, rands, 32);
153 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
154
155 check_funcs ("mul", alt_mul, mpz_mul, a, b);
156 }
157 mpz_clears (bs, a, b, NULL);
158 }
159
160 #define MAX_SIZE 100
161
162 static void
check_roinit(void)163 check_roinit (void)
164 {
165 gmp_randstate_ptr rands = RANDS;
166 mpz_t bs, a, b, r, ref;
167 unsigned i;
168
169 mpz_inits (bs, a, b, r, ref, NULL);
170
171 for (i = 0; i < COUNT; i++)
172 {
173 mp_srcptr ap, bp;
174 mp_size_t an, bn;
175 mpz_urandomb (bs, rands, 32);
176 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
177 mpz_urandomb (bs, rands, 32);
178 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
179
180 an = mpz_size (a);
181 ap = mpz_limbs_read (a);
182 bn = mpz_size (b);
183 bp = mpz_limbs_read (b);
184
185 mpz_add (ref, a, b);
186 {
187 mpz_t a1, b1;
188 #if __STDC_VERSION__ >= 199901
189 const mpz_t a2 = MPZ_ROINIT_N ( (mp_ptr) ap, an);
190 const mpz_t b2 = MPZ_ROINIT_N ( (mp_ptr) bp, bn);
191
192 mpz_set_ui (r, 0);
193 mpz_add (r, a2, b2);
194 if (mpz_cmp (r, ref) != 0)
195 {
196 printf ("MPZ_ROINIT_N failed\n");
197 gmp_printf ("a = %Zx\n", a);
198 gmp_printf ("b = %Zx\n", b);
199 gmp_printf ("r = %Zx (bad)\n", r);
200 gmp_printf ("ref = %Zx\n", ref);
201 abort ();
202 }
203 #endif
204 mpz_set_ui (r, 0);
205 mpz_add (r, mpz_roinit_n (a1, ap, an), mpz_roinit_n (b1, bp, bn));
206 if (mpz_cmp (r, ref) != 0)
207 {
208 printf ("mpz_roinit_n failed\n");
209 gmp_printf ("a = %Zx\n", a);
210 gmp_printf ("b = %Zx\n", b);
211 gmp_printf ("r = %Zx (bad)\n", r);
212 gmp_printf ("ref = %Zx\n", ref);
213 abort ();
214 }
215 }
216 }
217 mpz_clears (bs, a, b, r, ref, NULL);
218 }
219
220 int
main(int argc,char * argv[])221 main (int argc, char *argv[])
222 {
223 tests_start ();
224 tests_end ();
225
226 check_add ();
227 check_mul ();
228 check_roinit ();
229
230 return 0;
231
232 }
233