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