1/* Test that routines allow reusing a source variable as destination.
2
3Copyright 1996, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library.  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, mpf_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 mpf_add etc would be better.  */
34
35int
36main (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#ifndef EXPO
50#define EXPO 32
51#endif
52
53void dump_abort __GMP_PROTO ((char *, mpf_t, mpf_t));
54
55typedef void (*dss_func) __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
56
57dss_func dss_funcs[] =
58{
59  mpf_div, mpf_add, mpf_mul, mpf_sub,
60};
61
62char *dss_func_names[] =
63{
64  "mpf_div", "mpf_add", "mpf_mul", "mpf_sub",
65};
66
67typedef void (*dsi_func) __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
68
69dsi_func dsi_funcs[] =
70{
71  mpf_div_ui, mpf_add_ui, mpf_mul_ui, mpf_sub_ui,
72  mpf_mul_2exp, mpf_div_2exp
73};
74
75char *dsi_func_names[] =
76{
77  "mpf_div_ui", "mpf_add_ui", "mpf_mul_ui", "mpf_sub_ui",
78  "mpf_mul_2exp", "mpf_div_2exp"
79};
80
81typedef void (*dis_func) __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr));
82
83dis_func dis_funcs[] =
84{
85  mpf_ui_div, mpf_ui_sub,
86};
87
88char *dis_func_names[] =
89{
90  "mpf_ui_div", "mpf_ui_sub",
91};
92
93int
94main (int argc, char **argv)
95{
96  int i;
97  int pass, reps = 10000;
98  mpf_t in1, in2, out1;
99  unsigned long int in1i, in2i;
100  mpf_t res1, res2, res3;
101  mp_size_t bprec = 100;
102
103  tests_start ();
104
105  if (argc > 1)
106    {
107      reps = strtol (argv[1], 0, 0);
108      if (argc > 2)
109	bprec = strtol (argv[2], 0, 0);
110    }
111
112  mpf_set_default_prec (bprec);
113
114  mpf_init (in1);
115  mpf_init (in2);
116  mpf_init (out1);
117  mpf_init (res1);
118  mpf_init (res2);
119  mpf_init (res3);
120
121  for (pass = 1; pass <= reps; pass++)
122    {
123      mpf_random2 (in1, urandom () % SIZE - SIZE/2, urandom () % EXPO);
124      mpf_random2 (in2, urandom () % SIZE - SIZE/2, urandom () % EXPO);
125
126      for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
127	{
128	  /* Don't divide by 0.  */
129	  if (i == 0 && mpf_cmp_ui (in2, 0) == 0)
130	    continue;
131
132	  (dss_funcs[i]) (res1, in1, in2);
133
134	  mpf_set (out1, in1);
135	  (dss_funcs[i]) (out1, out1, in2);
136	  mpf_set (res2, out1);
137
138	  mpf_set (out1, in2);
139	  (dss_funcs[i]) (out1, in1, out1);
140	  mpf_set (res3, out1);
141
142	  if (mpf_cmp (res1, res2) != 0)
143	    dump_abort (dss_func_names[i], res1, res2);
144	  if (mpf_cmp (res1, res3) != 0)
145	    dump_abort (dss_func_names[i], res1, res3);
146	}
147
148      in2i = urandom ();
149      for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
150	{
151	  /* Don't divide by 0.  */
152	  if (strcmp (dsi_func_names[i], "mpf_div_ui") == 0 && in2i == 0)
153	    continue;
154
155	  (dsi_funcs[i]) (res1, in1, in2i);
156
157	  mpf_set (out1, in1);
158	  (dsi_funcs[i]) (out1, out1, in2i);
159	  mpf_set (res2, out1);
160
161	  if (mpf_cmp (res1, res2) != 0)
162	    dump_abort (dsi_func_names[i], res1, res2);
163	}
164
165      in1i = urandom ();
166      for (i = 0; i < sizeof (dis_funcs) / sizeof (dis_func); i++)
167	{
168	  /* Don't divide by 0.  */
169	  if (strcmp (dis_func_names[i], "mpf_ui_div") == 0
170	      && mpf_cmp_ui (in2, 0) == 0)
171	    continue;
172
173	  (dis_funcs[i]) (res1, in1i, in2);
174
175	  mpf_set (out1, in2);
176	  (dis_funcs[i]) (out1, in1i, out1);
177	  mpf_set (res2, out1);
178
179	  if (mpf_cmp (res1, res2) != 0)
180	    dump_abort (dis_func_names[i], res1, res2);
181	}
182
183    }
184
185  mpf_clear (in1);
186  mpf_clear (in2);
187  mpf_clear (out1);
188  mpf_clear (res1);
189  mpf_clear (res2);
190  mpf_clear (res3);
191
192  tests_end ();
193  exit (0);
194}
195
196void
197dump_abort (char *name, mpf_t res1, mpf_t res2)
198{
199  printf ("failure in %s:\n", name);
200  mpf_dump (res1);
201  mpf_dump (res2);
202  abort ();
203}
204
205#if 0
206void mpf_abs		__GMP_PROTO ((mpf_ptr, mpf_srcptr));
207void mpf_sqrt		__GMP_PROTO ((mpf_ptr, mpf_srcptr));
208void mpf_neg		__GMP_PROTO ((mpf_ptr, mpf_srcptr));
209#endif
210
211#endif /* ! DLL_EXPORT */
212