xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpq/reuse.c (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
1 /* Test that routines allow reusing a source variable as destination.
2 
3 Copyright 1996, 2000-2002, 2012, 2015 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 #include <string.h>
23 
24 #include "gmp.h"
25 #include "gmp-impl.h"
26 #include "tests.h"
27 
28 #if __GMP_LIBGMP_DLL
29 
30 /* FIXME: When linking to a DLL libgmp, mpq_add etc can't be used as
31    initializers for global variables because they're effectively global
32    variables (function pointers) themselves.  Perhaps calling a test
33    function successively with mpq_add etc would be better.  */
34 
35 int
36 main (void)
37 {
38   printf ("Test suppressed for windows DLL\n");
39   exit (0);
40 }
41 
42 
43 #else /* ! DLL_EXPORT */
44 
45 #ifndef SIZE
46 #define SIZE 16
47 #endif
48 
49 void dump_abort (const char *, mpq_t, mpq_t);
50 
51 typedef void (*dss_func) (mpq_ptr, mpq_srcptr, mpq_srcptr);
52 
53 dss_func dss_funcs[] =
54 {
55   mpq_div, mpq_add, mpq_mul, mpq_sub,
56 };
57 
58 const char *dss_func_names[] =
59 {
60   "mpq_div", "mpq_add", "mpq_mul", "mpq_sub",
61 };
62 
63 typedef void (*ds_func) (mpq_ptr, mpq_srcptr);
64 
65 ds_func ds_funcs[] =
66 {
67   mpq_abs, mpq_neg,
68 };
69 
70 const char *ds_func_names[] =
71 {
72   "mpq_abs", "mpq_neg",
73 };
74 
75 typedef void (*dsi_func) (mpq_ptr, mpq_srcptr, unsigned long int);
76 
77 dsi_func dsi_funcs[] =
78 {
79   mpq_mul_2exp, mpq_div_2exp
80 };
81 
82 const char *dsi_func_names[] =
83 {
84   "mpq_mul_2exp", "mpq_div_2exp"
85 };
86 
87 int
88 main (int argc, char **argv)
89 {
90   int i;
91   int pass, reps = 100;
92   mpq_t in1, in2, out1;
93   unsigned long int randbits, in2i;
94   mpq_t res1, res2;
95   gmp_randstate_ptr  rands;
96 
97   tests_start ();
98 
99   if (argc > 1)
100     reps = strtol (argv[1], 0, 0);
101 
102   rands = RANDS;
103 
104   mpq_init (in1);
105   mpq_init (in2);
106   mpq_init (out1);
107   mpq_init (res1);
108   mpq_init (res2);
109 
110   for (pass = 1; pass <= reps; pass++)
111     {
112       randbits = urandom ();
113 
114       if (randbits & 1)
115 	{
116 	  mpq_clear (in1);
117 	  mpq_init (in1);
118 	}
119       randbits >>= 1;
120       mpz_errandomb (mpq_numref(in1), rands, 512L);
121       mpz_errandomb_nonzero (mpq_denref(in1), rands, 512L);
122       if (randbits & 1)
123 	mpz_neg (mpq_numref(in1),mpq_numref(in1));
124       randbits >>= 1;
125       mpq_canonicalize (in1);
126 
127       if (randbits & 1)
128 	{
129 	  mpq_clear (in2);
130 	  mpq_init (in2);
131 	}
132       randbits >>= 1;
133       mpz_errandomb (mpq_numref(in2), rands, 512L);
134       mpz_errandomb_nonzero (mpq_denref(in2), rands, 512L);
135       if (randbits & 1)
136 	mpz_neg (mpq_numref(in2),mpq_numref(in2));
137       randbits >>= 1;
138       mpq_canonicalize (in2);
139 
140       for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
141 	{
142 	  /* Don't divide by 0.  */
143 	  if (i == 0 && mpq_cmp_ui (in2, 0, 1) == 0)
144 	    continue;
145 
146 	  if (randbits & 1)
147 	    {
148 	      mpq_clear (res1);
149 	      mpq_init (res1);
150 	    }
151 	  randbits >>= 1;
152 
153 	  (dss_funcs[i]) (res1, in1, in2);
154 	  MPQ_CHECK_FORMAT(res1);
155 
156 	  mpq_set (out1, in1);
157 	  (dss_funcs[i]) (out1, out1, in2);
158 	  MPQ_CHECK_FORMAT(out1);
159 
160 	  if (mpq_cmp (res1, out1) != 0)
161 	    dump_abort (dss_func_names[i], res1, out1);
162 
163 	  mpq_set (out1, in2);
164 	  (dss_funcs[i]) (out1, in1, out1);
165 	  MPQ_CHECK_FORMAT(out1);
166 
167 	  if (mpq_cmp (res1, out1) != 0)
168 	    dump_abort (dss_func_names[i], res1, out1);
169 
170 	  mpq_set (out1, in2);
171 	  (dss_funcs[i]) (res1, out1, in2);
172 	  MPQ_CHECK_FORMAT(res1);
173 
174 	  (dss_funcs[i]) (res2, in2, in2);
175 	  MPQ_CHECK_FORMAT(res2);
176 
177 	  (dss_funcs[i]) (out1, out1, out1);
178 	  MPQ_CHECK_FORMAT(out1);
179 
180 	  if (mpq_cmp (res1, res2) != 0)
181 	    dump_abort (dss_func_names[i], res1, res2);
182 	  if (mpq_cmp (res1, out1) != 0)
183 	    dump_abort (dss_func_names[i], res1, out1);
184 	}
185 
186       for (i = 0; i < sizeof (ds_funcs) / sizeof (ds_func); i++)
187 	{
188 	  if (randbits & 1)
189 	    {
190 	      mpq_clear (res1);
191 	      mpq_init (res1);
192 	    }
193 	  randbits >>= 1;
194 	  (ds_funcs[i]) (res1, in1);
195 	  MPQ_CHECK_FORMAT(res1);
196 
197 	  mpq_set (out1, in1);
198 	  (ds_funcs[i]) (out1, out1);
199 	  MPQ_CHECK_FORMAT(out1);
200 
201 	  if (mpq_cmp (res1, out1) != 0)
202 	    dump_abort (ds_func_names[i], res1, out1);
203 	}
204 
205       in2i = urandom () % 65536;
206       for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
207 	{
208 	  if (randbits & 1)
209 	    {
210 	      mpq_clear (res1);
211 	      mpq_init (res1);
212 	    }
213 	  randbits >>= 1;
214 
215 	  (dsi_funcs[i]) (res1, in1, in2i);
216 	  MPQ_CHECK_FORMAT(res1);
217 
218 	  mpq_set (out1, in1);
219 	  (dsi_funcs[i]) (out1, out1, in2i);
220 	  MPQ_CHECK_FORMAT(out1);
221 
222 	  if (mpq_cmp (res1, out1) != 0)
223 	    dump_abort (dsi_func_names[i], res1, out1);
224 	}
225 
226     }
227 
228   mpq_clear (in1);
229   mpq_clear (in2);
230   mpq_clear (out1);
231   mpq_clear (res1);
232   mpq_clear (res2);
233 
234   tests_end ();
235   exit (0);
236 }
237 
238 void
239 dump_abort (const char *name, mpq_t res1, mpq_t res2)
240 {
241   printf ("failure in %s:\n", name);
242   mpq_trace ("  res1  ", res1);
243   mpq_trace ("  res2  ", res2);
244   abort ();
245 }
246 
247 #endif /* ! DLL_EXPORT */
248