xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpf/reuse.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /* Test that routines allow reusing a source variable as destination.
2 
3 Copyright 1996, 2000-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 https://www.gnu.org/licenses/.  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 #if __GMP_LIBGMP_DLL
28 
29 /* FIXME: When linking to a DLL libgmp, mpf_add etc can't be used as
30    initializers for global variables because they're effectively global
31    variables (function pointers) themselves.  Perhaps calling a test
32    function successively with mpf_add etc would be better.  */
33 
34 int
main(void)35 main (void)
36 {
37   printf ("Test suppressed for windows DLL\n");
38   exit (0);
39 }
40 
41 
42 #else /* ! DLL_EXPORT */
43 
44 #ifndef SIZE
45 #define SIZE 16
46 #endif
47 
48 #ifndef EXPO
49 #define EXPO 32
50 #endif
51 
52 void dump_abort (const char *, mpf_t, mpf_t);
53 
54 typedef void (*dss_func) (mpf_ptr, mpf_srcptr, mpf_srcptr);
55 
56 dss_func dss_funcs[] =
57 {
58   mpf_div, mpf_add, mpf_mul, mpf_sub,
59 };
60 
61 const char *dss_func_names[] =
62 {
63   "mpf_div", "mpf_add", "mpf_mul", "mpf_sub",
64 };
65 
66 typedef void (*dsi_func) (mpf_ptr, mpf_srcptr, unsigned long int);
67 
68 dsi_func dsi_funcs[] =
69 {
70   mpf_div_ui, mpf_add_ui, mpf_mul_ui, mpf_sub_ui,
71   mpf_mul_2exp, mpf_div_2exp, mpf_pow_ui
72 };
73 
74 const char *dsi_func_names[] =
75 {
76   "mpf_div_ui", "mpf_add_ui", "mpf_mul_ui", "mpf_sub_ui",
77   "mpf_mul_2exp", "mpf_div_2exp", "mpf_pow_ui"
78 };
79 
80 typedef void (*dis_func) (mpf_ptr, unsigned long int, mpf_srcptr);
81 
82 dis_func dis_funcs[] =
83 {
84   mpf_ui_div, mpf_ui_sub,
85 };
86 
87 const char *dis_func_names[] =
88 {
89   "mpf_ui_div", "mpf_ui_sub",
90 };
91 
92 int
main(int argc,char ** argv)93 main (int argc, char **argv)
94 {
95   int i;
96   int pass, reps = 10000;
97   mpf_t in1, in2, out1;
98   unsigned long int in1i, in2i;
99   mpf_t res1, res2, res3;
100   mp_size_t bprec = 100;
101 
102   tests_start ();
103 
104   if (argc > 1)
105     {
106       reps = strtol (argv[1], 0, 0);
107       if (argc > 2)
108 	bprec = strtol (argv[2], 0, 0);
109     }
110 
111   mpf_set_default_prec (bprec);
112 
113   mpf_init (in1);
114   mpf_init (in2);
115   mpf_init (out1);
116   mpf_init (res1);
117   mpf_init (res2);
118   mpf_init (res3);
119 
120   for (pass = 1; pass <= reps; pass++)
121     {
122       mpf_random2 (in1, urandom () % SIZE - SIZE/2, urandom () % EXPO);
123       mpf_random2 (in2, urandom () % SIZE - SIZE/2, urandom () % EXPO);
124 
125       for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
126 	{
127 	  /* Don't divide by 0.  */
128 	  if (i == 0 && mpf_cmp_ui (in2, 0) == 0)
129 	    continue;
130 
131 	  (dss_funcs[i]) (res1, in1, in2);
132 
133 	  mpf_set (out1, in1);
134 	  (dss_funcs[i]) (out1, out1, in2);
135 	  mpf_set (res2, out1);
136 
137 	  mpf_set (out1, in2);
138 	  (dss_funcs[i]) (out1, in1, out1);
139 	  mpf_set (res3, out1);
140 
141 	  if (mpf_cmp (res1, res2) != 0)
142 	    dump_abort (dss_func_names[i], res1, res2);
143 	  if (mpf_cmp (res1, res3) != 0)
144 	    dump_abort (dss_func_names[i], res1, res3);
145 	}
146 
147       in2i = urandom ();
148       for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
149 	{
150 	  unsigned long this_in2i = in2i;
151 
152 	  /* Don't divide by 0.  */
153 	  if (dsi_funcs[i] == mpf_div_ui && this_in2i == 0)
154 	    continue;
155 
156 	  /* Avoid overflow/underflow in the exponent.  */
157 	  if (dsi_funcs[i] == mpf_mul_2exp || dsi_funcs[i] == mpf_div_2exp)
158 	    this_in2i %= 0x100000;
159 	  else if (dsi_funcs[i] == mpf_pow_ui)
160 	    this_in2i %= 0x1000;
161 
162 	  (dsi_funcs[i]) (res1, in1, this_in2i);
163 
164 	  mpf_set (out1, in1);
165 	  (dsi_funcs[i]) (out1, out1, this_in2i);
166 	  mpf_set (res2, out1);
167 
168 	  if (mpf_cmp (res1, res2) != 0)
169 	    dump_abort (dsi_func_names[i], res1, res2);
170 	}
171 
172       in1i = urandom ();
173       for (i = 0; i < sizeof (dis_funcs) / sizeof (dis_func); i++)
174 	{
175 	  /* Don't divide by 0.  */
176 	  if (dis_funcs[i] == mpf_ui_div
177 	      && mpf_cmp_ui (in2, 0) == 0)
178 	    continue;
179 
180 	  (dis_funcs[i]) (res1, in1i, in2);
181 
182 	  mpf_set (out1, in2);
183 	  (dis_funcs[i]) (out1, in1i, out1);
184 	  mpf_set (res2, out1);
185 
186 	  if (mpf_cmp (res1, res2) != 0)
187 	    dump_abort (dis_func_names[i], res1, res2);
188 	}
189 
190     }
191 
192   mpf_clear (in1);
193   mpf_clear (in2);
194   mpf_clear (out1);
195   mpf_clear (res1);
196   mpf_clear (res2);
197   mpf_clear (res3);
198 
199   tests_end ();
200   exit (0);
201 }
202 
203 void
dump_abort(const char * name,mpf_t res1,mpf_t res2)204 dump_abort (const char *name, mpf_t res1, mpf_t res2)
205 {
206   printf ("failure in %s:\n", name);
207   mpf_dump (res1);
208   mpf_dump (res2);
209   abort ();
210 }
211 
212 #if 0
213 void mpf_abs		(mpf_ptr, mpf_srcptr);
214 void mpf_sqrt		(mpf_ptr, mpf_srcptr);
215 void mpf_neg		(mpf_ptr, mpf_srcptr);
216 #endif
217 
218 #endif /* ! DLL_EXPORT */
219