xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpf/t-sub.c (revision 4fee23f98c45552038ad6b5bd05124a41302fb01)
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 }
207