Upload Tizen:Base source
[external/gmp.git] / tests / mpf / t-sub.c
1 /* Test mpf_sub.
2
3 Copyright 1996, 2001, 2004 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "gmp.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26
27 #ifndef SIZE
28 #define SIZE 16
29 #endif
30
31 void
32 check_rand (int argc, char **argv)
33 {
34   mp_size_t size;
35   mp_exp_t exp;
36   int reps = 20000;
37   int i;
38   mpf_t u, v, w, wref;
39   mp_size_t bprec = 100;
40   mpf_t rerr, max_rerr, limit_rerr;
41
42   if (argc > 1)
43     {
44       reps = strtol (argv[1], 0, 0);
45       if (argc > 2)
46         bprec = strtol (argv[2], 0, 0);
47     }
48
49   mpf_set_default_prec (bprec);
50
51   mpf_init_set_ui (limit_rerr, 1);
52   mpf_div_2exp (limit_rerr, limit_rerr, bprec);
53 #if VERBOSE
54   mpf_dump (limit_rerr);
55 #endif
56   mpf_init (rerr);
57   mpf_init_set_ui (max_rerr, 0);
58
59   mpf_init (u);
60   mpf_init (v);
61   mpf_init (w);
62   mpf_init (wref);
63   for (i = 0; i < reps; i++)
64     {
65       size = urandom () % (2 * SIZE) - SIZE;
66       exp = urandom () % SIZE;
67       mpf_random2 (u, size, exp);
68
69       size = urandom () % (2 * SIZE) - SIZE;
70       exp = urandom () % SIZE;
71       mpf_random2 (v, size, exp);
72
73       if ((urandom () & 1) != 0)
74         mpf_add_ui (u, v, 1);
75       else if ((urandom () & 1) != 0)
76         mpf_sub_ui (u, v, 1);
77
78       mpf_sub (w, u, v);
79       refmpf_sub (wref, u, v);
80
81       mpf_reldiff (rerr, w, wref);
82       if (mpf_cmp (rerr, max_rerr) > 0)
83         {
84           mpf_set (max_rerr, rerr);
85 #if VERBOSE
86           mpf_dump (max_rerr);
87 #endif
88           if (mpf_cmp (rerr, limit_rerr) > 0)
89             {
90               printf ("ERROR after %d tests\n", i);
91               printf ("   u = "); mpf_dump (u);
92               printf ("   v = "); mpf_dump (v);
93               printf ("wref = "); mpf_dump (wref);
94               printf ("   w = "); mpf_dump (w);
95               abort ();
96             }
97         }
98     }
99
100   mpf_clear (limit_rerr);
101   mpf_clear (rerr);
102   mpf_clear (max_rerr);
103
104   mpf_clear (u);
105   mpf_clear (v);
106   mpf_clear (w);
107   mpf_clear (wref);
108 }
109
110
111 void
112 check_data (void)
113 {
114   static const struct {
115     struct {
116       int        exp, size;
117       mp_limb_t  d[10];
118     } x, y, want;
119
120   } data[] = {
121     { { 123, 2, { 8, 9 } },             { 123, 1, { 9 } }, { 122, 1, { 8 } } },
122
123     /* f - f == 0, various sizes.
124        These exercise a past problem (gmp 4.1.3 and earlier) where the
125        result exponent was not zeroed on a zero result like this.  */
126     { { 0, 0 }, { 0, 0 }, { 0, 0 } },
127     { { 99, 1, { 1 } },             { 99, 1, { 1 } },             { 0, 0 } },
128     { { 99, 2, { 123, 456 } },      { 99, 2, { 123, 456 } },      { 0, 0 } },
129     { { 99, 3, { 123, 456, 789 } }, { 99, 3, { 123, 456, 789 } }, { 0, 0 } },
130
131     /* High limbs cancel, leaving just the low limbs of the longer operand.
132        This exercises a past problem (gmp 4.1.3 and earlier) where high zero
133        limbs on the remainder were not stripped before truncating to the
134        destination, causing loss of precision.  */
135     { { 123, 2, { 8, 9 } },             { 123, 1, { 9 } }, { 122, 1, { 8 } } },
136     { { 123, 3, { 8, 0, 9 } },          { 123, 1, { 9 } }, { 121, 1, { 8 } } },
137     { { 123, 4, { 8, 0, 0, 9 } },       { 123, 1, { 9 } }, { 120, 1, { 8 } } },
138     { { 123, 5, { 8, 0, 0, 0, 9 } },    { 123, 1, { 9 } }, { 119, 1, { 8 } } },
139     { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 118, 1, { 8 } } },
140
141   };
142
143   mpf_t  x, y, got, want;
144   int  i, swap;
145
146   mp_trace_base = 16;
147   mpf_init (got);
148
149   for (i = 0; i < numberof (data); i++)
150     {
151       for (swap = 0; swap <= 1; swap++)
152         {
153           PTR(x) = (mp_ptr) data[i].x.d;
154           SIZ(x) = data[i].x.size;
155           EXP(x) = data[i].x.exp;
156           PREC(x) = numberof (data[i].x.d);
157           MPF_CHECK_FORMAT (x);
158
159           PTR(y) = (mp_ptr) data[i].y.d;
160           SIZ(y) = data[i].y.size;
161           EXP(y) = data[i].y.exp;
162           PREC(y) = numberof (data[i].y.d);
163           MPF_CHECK_FORMAT (y);
164
165           PTR(want) = (mp_ptr) data[i].want.d;
166           SIZ(want) = data[i].want.size;
167           EXP(want) = data[i].want.exp;
168           PREC(want) = numberof (data[i].want.d);
169           MPF_CHECK_FORMAT (want);
170
171           if (swap)
172             {
173               mpf_swap (x, y);
174               SIZ(want) = - SIZ(want);
175             }
176
177           mpf_sub (got, x, y);
178 /*           MPF_CHECK_FORMAT (got); */
179
180           if (mpf_cmp (got, want) != 0)
181             {
182               printf ("check_data() wrong reault at data[%d] (operands%s swapped)\n", i, swap ? "" : " not");
183               mpf_trace ("x   ", x);
184               mpf_trace ("y   ", y);
185               mpf_trace ("got ", got);
186               mpf_trace ("want", want);
187               abort ();
188             }
189         }
190     }
191
192   mpf_clear (got);
193 }
194
195
196 int
197 main (int argc, char **argv)
198 {
199   tests_start ();
200
201   check_data ();
202   check_rand (argc, argv);
203
204   tests_end ();
205   exit (0);
206 }