xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpq/reuse.c (revision 49d8c9ecf4abd21261269266ef64939f71b3cd09)
1 /* Test that routines allow reusing a source variable as destination.
2 
3 Copyright 1996, 2000, 2001, 2002, 2012 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 http://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, res3;
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   mpq_init (res3);
110 
111   for (pass = 1; pass <= reps; pass++)
112     {
113       randbits = urandom ();
114 
115       if (randbits & 1)
116 	{
117 	  mpq_clear (in1);
118 	  mpq_init (in1);
119 	}
120       randbits >>= 1;
121       mpz_errandomb (mpq_numref(in1), rands, 512L);
122       mpz_errandomb_nonzero (mpq_denref(in1), rands, 512L);
123       if (randbits & 1)
124 	mpz_neg (mpq_numref(in1),mpq_numref(in1));
125       randbits >>= 1;
126       mpq_canonicalize (in1);
127 
128       if (randbits & 1)
129 	{
130 	  mpq_clear (in2);
131 	  mpq_init (in2);
132 	}
133       randbits >>= 1;
134       mpz_errandomb (mpq_numref(in2), rands, 512L);
135       mpz_errandomb_nonzero (mpq_denref(in2), rands, 512L);
136       if (randbits & 1)
137 	mpz_neg (mpq_numref(in2),mpq_numref(in2));
138       randbits >>= 1;
139       mpq_canonicalize (in2);
140 
141       for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
142 	{
143 	  /* Don't divide by 0.  */
144 	  if (i == 0 && mpq_cmp_ui (in2, 0, 1) == 0)
145 	    continue;
146 
147 	  if (randbits & 1)
148 	    {
149 	      mpq_clear (res1);
150 	      mpq_init (res1);
151 	    }
152 	  randbits >>= 1;
153 
154 	  (dss_funcs[i]) (res1, in1, in2);
155 
156 	  mpq_set (out1, in1);
157 	  (dss_funcs[i]) (out1, out1, in2);
158 	  mpq_set (res2, out1);
159 
160 	  mpq_set (out1, in2);
161 	  (dss_funcs[i]) (out1, in1, out1);
162 	  mpq_set (res3, out1);
163 
164 	  if (mpq_cmp (res1, res2) != 0)
165 	    dump_abort (dss_func_names[i], res1, res2);
166 	  if (mpq_cmp (res1, res3) != 0)
167 	    dump_abort (dss_func_names[i], res1, res3);
168 	}
169 
170       for (i = 0; i < sizeof (ds_funcs) / sizeof (ds_func); i++)
171 	{
172 	  if (randbits & 1)
173 	    {
174 	      mpq_clear (res1);
175 	      mpq_init (res1);
176 	    }
177 	  randbits >>= 1;
178 	  (ds_funcs[i]) (res1, in1);
179 
180 	  mpq_set (out1, in1);
181 	  (ds_funcs[i]) (out1, out1);
182 	  mpq_set (res2, out1);
183 
184 	  if (mpq_cmp (res1, res2) != 0)
185 	    dump_abort (ds_func_names[i], res1, res2);
186 	}
187 
188       in2i = urandom () % 65536;
189       for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
190 	{
191 	  if (randbits & 1)
192 	    {
193 	      mpq_clear (res1);
194 	      mpq_init (res1);
195 	    }
196 	  randbits >>= 1;
197 
198 	  (dsi_funcs[i]) (res1, in1, in2i);
199 
200 	  mpq_set (out1, in1);
201 	  (dsi_funcs[i]) (out1, out1, in2i);
202 	  mpq_set (res2, out1);
203 
204 	  if (mpq_cmp (res1, res2) != 0)
205 	    dump_abort (dsi_func_names[i], res1, res2);
206 	}
207 
208     }
209 
210   mpq_clear (in1);
211   mpq_clear (in2);
212   mpq_clear (out1);
213   mpq_clear (res1);
214   mpq_clear (res2);
215   mpq_clear (res3);
216 
217   tests_end ();
218   exit (0);
219 }
220 
221 void
222 dump_abort (const char *name, mpq_t res1, mpq_t res2)
223 {
224   printf ("failure in %s:\n", name);
225   mpq_trace ("  res1  ", res1);
226   mpq_trace ("  res2  ", res2);
227   abort ();
228 }
229 
230 #endif /* ! DLL_EXPORT */
231