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