1 /* Test mpf_eq.
2 
3 Copyright 2009, 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 
23 #include "gmp.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 #define SZ (2 * sizeof(mp_limb_t))
28 
29 void insert_random_low_zero_limbs (mpf_t, gmp_randstate_ptr);
30 void dump_abort (mpf_t, mpf_t, int, int, int, int, int, long);
31 void hexdump (mpf_t);
32 
33 void
check_data(void)34 check_data (void)
35 {
36   static const struct
37   {
38     struct {
39       int        exp, size;
40       mp_limb_t  d[10];
41     } x, y;
42     mp_bitcnt_t bits;
43     int want;
44 
45   } data[] = {
46     { { 0, 0, { 0 } },             { 0, 0, { 0 } },    0, 1 },
47 
48     { { 0, 1, { 7 } },             { 0, 1, { 7 } },    0, 1 },
49     { { 0, 1, { 7 } },             { 0, 1, { 7 } },   17, 1 },
50     { { 0, 1, { 7 } },             { 0, 1, { 7 } }, 4711, 1 },
51 
52     { { 0, 1, { 7 } },             { 0, 1, { 6 } },    0, 1 },
53     { { 0, 1, { 7 } },             { 0, 1, { 6 } },    2, 1 },
54     { { 0, 1, { 7 } },             { 0, 1, { 6 } },    3, 0 },
55 
56     { { 0, 0, { 0 } },             { 0, 1, { 1 } },    0, 0 },
57     { { 0, 1, { 1 } },             { 0,-1 ,{ 1 } },    0, 0 },
58     { { 1, 1, { 1 } },             { 0, 1, { 1 } },    0, 0 },
59 
60     { { 0, 1, { 8 } },             { 0, 1, { 4 } },    0, 0 },
61 
62     { { 0, 2, { 0, 3 } },          { 0, 1, { 3 } }, 1000, 1 },
63   };
64 
65   mpf_t  x, y;
66   int got, got_swapped;
67   int i;
68   mp_trace_base = 16;
69 
70   for (i = 0; i < numberof (data); i++)
71     {
72       PTR(x) = (mp_ptr) data[i].x.d;
73       SIZ(x) = data[i].x.size;
74       EXP(x) = data[i].x.exp;
75       PREC(x) = numberof (data[i].x.d);
76       MPF_CHECK_FORMAT (x);
77 
78       PTR(y) = (mp_ptr) data[i].y.d;
79       SIZ(y) = data[i].y.size;
80       EXP(y) = data[i].y.exp;
81       PREC(y) = numberof (data[i].y.d);
82       MPF_CHECK_FORMAT (y);
83 
84       got         = mpf_eq (x, y, data[i].bits);
85       got_swapped = mpf_eq (y, x, data[i].bits);
86 
87       if (got != got_swapped || got != data[i].want)
88 	{
89 	  printf ("check_data() wrong result at data[%d]\n", i);
90 	  mpf_trace ("x   ", x);
91 	  mpf_trace ("y   ", y);
92 	  printf ("got         %d\n", got);
93 	  printf ("got_swapped %d\n", got_swapped);
94 	  printf ("want        %d\n", data[i].want);
95 	  abort ();
96         }
97     }
98 }
99 
100 void
check_random(long reps)101 check_random (long reps)
102 {
103   unsigned long test;
104   gmp_randstate_ptr rands = RANDS;
105   mpf_t a, b, x;
106   mpz_t ds;
107   int hibits, lshift1, lshift2;
108   int xtra;
109 
110 #define HIBITS 10
111 #define LSHIFT1 10
112 #define LSHIFT2 10
113 
114   mpf_set_default_prec ((1 << HIBITS) + (1 << LSHIFT1) + (1 << LSHIFT2));
115 
116   mpz_init (ds);
117   mpf_inits (a, b, x, NULL);
118 
119   for (test = 0; test < reps; test++)
120     {
121       mpz_urandomb (ds, rands, HIBITS);
122       hibits = mpz_get_ui (ds) + 1;
123       mpz_urandomb (ds, rands, hibits);
124       mpz_setbit (ds, hibits  - 1);	/* make sure msb is set */
125       mpf_set_z (a, ds);
126       mpf_set_z (b, ds);
127 
128       mpz_urandomb (ds, rands, LSHIFT1);
129       lshift1 = mpz_get_ui (ds);
130       mpf_mul_2exp (a, a, lshift1 + 1);
131       mpf_mul_2exp (b, b, lshift1 + 1);
132       mpf_add_ui (a, a, 1);	/* make a one-bit difference */
133 
134       mpz_urandomb (ds, rands, LSHIFT2);
135       lshift2 = mpz_get_ui (ds);
136       mpf_mul_2exp (a, a, lshift2);
137       mpf_mul_2exp (b, b, lshift2);
138       mpz_urandomb (ds, rands, lshift2);
139       mpf_set_z (x, ds);
140       mpf_add (a, a, x);
141       mpf_add (b, b, x);
142 
143       insert_random_low_zero_limbs (a, rands);
144       insert_random_low_zero_limbs (b, rands);
145 
146       if (mpf_eq (a, b, lshift1 + hibits) == 0 ||
147 	  mpf_eq (b, a, lshift1 + hibits) == 0)
148 	{
149 	  dump_abort (a, b, lshift1 + hibits, lshift1, lshift2, hibits, 1, test);
150 	}
151       for (xtra = 1; xtra < 100; xtra++)
152 	if (mpf_eq (a, b, lshift1 + hibits + xtra) != 0 ||
153 	    mpf_eq (b, a, lshift1 + hibits + xtra) != 0)
154 	  {
155 	    dump_abort (a, b, lshift1 + hibits + xtra, lshift1, lshift2, hibits, 0, test);
156 	  }
157     }
158 
159   mpf_clears (a, b, x, NULL);
160   mpz_clear (ds);
161 }
162 
163 void
insert_random_low_zero_limbs(mpf_t x,gmp_randstate_ptr rands)164 insert_random_low_zero_limbs (mpf_t x, gmp_randstate_ptr rands)
165 {
166   mp_size_t max = PREC(x) - SIZ(x);
167   mp_size_t s;
168   mpz_t ds; mpz_init (ds);
169   mpz_urandomb (ds, rands, 32);
170   s = mpz_get_ui (ds) % (max + 1);
171   MPN_COPY_DECR (PTR(x) + s, PTR(x), SIZ(x));
172   MPN_ZERO (PTR(x), s);
173   SIZ(x) += s;
174   mpz_clear (ds);
175 }
176 
177 void
dump_abort(mpf_t a,mpf_t b,int cmp_prec,int lshift1,int lshift2,int hibits,int want,long test)178 dump_abort (mpf_t a, mpf_t b, int cmp_prec, int lshift1, int lshift2, int hibits, int want, long test)
179 {
180   printf ("ERROR in test %ld\n", test);
181   printf ("want %d got %d from mpf_eq\n", want, 1-want);
182   printf ("cmp_prec = %d\n", cmp_prec);
183   printf ("lshift1 = %d\n", lshift1);
184   printf ("lshift2 = %d\n", lshift2);
185   printf ("hibits = %d\n", hibits);
186   hexdump (a); puts ("");
187   hexdump (b); puts ("");
188   abort ();
189 }
190 
191 void
hexdump(mpf_t x)192 hexdump (mpf_t x)
193 {
194   mp_size_t i;
195   for (i = ABSIZ(x) - 1; i >= 0; i--)
196     {
197       gmp_printf ("%0*MX", SZ, PTR(x)[i]);
198       if (i != 0)
199 	printf (" ");
200     }
201 }
202 
203 int
main(int argc,char * argv[])204 main (int argc, char *argv[])
205 {
206   long reps = 10000;
207 
208   if (argc == 2)
209     reps = strtol (argv[1], 0, 0);
210 
211   tests_start ();
212 
213   check_data ();
214   check_random (reps);
215 
216   tests_end ();
217   exit (0);
218 }
219