xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-limbs.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
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