1415SN/A/* Test mpf_eq.
2553SN/A
3415SN/ACopyright 2009, 2012 Free Software Foundation, Inc.
4415SN/A
5415SN/AThis file is part of the GNU MP Library test suite.
6415SN/A
7553SN/AThe GNU MP Library test suite is free software; you can redistribute it
8415SN/Aand/or modify it under the terms of the GNU General Public License as
9553SN/Apublished by the Free Software Foundation; either version 3 of the License,
10415SN/Aor (at your option) any later version.
11415SN/A
12415SN/AThe GNU MP Library test suite is distributed in the hope that it will be
13415SN/Auseful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14415SN/AMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15415SN/APublic License for more details.
16415SN/A
17415SN/AYou should have received a copy of the GNU General Public License along with
18415SN/Athe GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19415SN/A
20415SN/A#include <stdio.h>
21553SN/A#include <stdlib.h>
22553SN/A
23553SN/A#include "gmp-impl.h"
24415SN/A#include "tests.h"
25415SN/A
26415SN/A#define SZ (2 * sizeof(mp_limb_t))
27415SN/A
28415SN/Avoid insert_random_low_zero_limbs (mpf_t, gmp_randstate_ptr);
29415SN/Avoid dump_abort (mpf_t, mpf_t, int, int, int, int, int, long);
30415SN/Avoid hexdump (mpf_t);
31415SN/A
32415SN/Avoid
33415SN/Acheck_data (void)
34415SN/A{
35415SN/A  static const struct
36415SN/A  {
37415SN/A    struct {
38415SN/A      int        exp, size;
39415SN/A      mp_limb_t  d[10];
40415SN/A    } x, y;
41415SN/A    mp_bitcnt_t bits;
422601Sjlahoda    int want;
432601Sjlahoda
442601Sjlahoda  } data[] = {
45415SN/A    { { 0, 0, { 0 } },             { 0, 0, { 0 } },    0, 1 },
46580SN/A
47415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 7 } },    0, 1 },
48415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 7 } },   17, 1 },
49415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 7 } }, 4711, 1 },
50415SN/A
51415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 6 } },    0, 1 },
52415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 6 } },    2, 1 },
53415SN/A    { { 0, 1, { 7 } },             { 0, 1, { 6 } },    3, 0 },
54415SN/A
55415SN/A    { { 0, 0, { 0 } },             { 0, 1, { 1 } },    0, 0 },
56415SN/A    { { 0, 1, { 1 } },             { 0,-1 ,{ 1 } },    0, 0 },
57415SN/A    { { 1, 1, { 1 } },             { 0, 1, { 1 } },    0, 0 },
58415SN/A
59415SN/A    { { 0, 1, { 8 } },             { 0, 1, { 4 } },    0, 0 },
60415SN/A
61415SN/A    { { 0, 2, { 0, 3 } },          { 0, 1, { 3 } }, 1000, 1 },
62415SN/A  };
63415SN/A
64415SN/A  mpf_t  x, y;
652601Sjlahoda  int got, got_swapped;
66415SN/A  int i;
67415SN/A  mp_trace_base = 16;
68415SN/A
69415SN/A  for (i = 0; i < numberof (data); i++)
70415SN/A    {
71415SN/A      PTR(x) = (mp_ptr) data[i].x.d;
72415SN/A      SIZ(x) = data[i].x.size;
73415SN/A      EXP(x) = data[i].x.exp;
74415SN/A      PREC(x) = numberof (data[i].x.d);
75415SN/A      MPF_CHECK_FORMAT (x);
762601Sjlahoda
77415SN/A      PTR(y) = (mp_ptr) data[i].y.d;
78415SN/A      SIZ(y) = data[i].y.size;
79415SN/A      EXP(y) = data[i].y.exp;
80415SN/A      PREC(y) = numberof (data[i].y.d);
812601Sjlahoda      MPF_CHECK_FORMAT (y);
82415SN/A
832229SN/A      got         = mpf_eq (x, y, data[i].bits);
842229SN/A      got_swapped = mpf_eq (y, x, data[i].bits);
852229SN/A
86415SN/A      if (got != got_swapped || got != data[i].want)
87415SN/A	{
88415SN/A	  printf ("check_data() wrong result at data[%d]\n", i);
89415SN/A	  mpf_trace ("x   ", x);
90	  mpf_trace ("y   ", y);
91	  printf ("got         %d\n", got);
92	  printf ("got_swapped %d\n", got_swapped);
93	  printf ("want        %d\n", data[i].want);
94	  abort ();
95        }
96    }
97}
98
99void
100check_random (long reps)
101{
102  unsigned long test;
103  gmp_randstate_ptr rands = RANDS;
104  mpf_t a, b, x;
105  mpz_t ds;
106  int hibits, lshift1, lshift2;
107  int xtra;
108
109#define HIBITS 10
110#define LSHIFT1 10
111#define LSHIFT2 10
112
113  mpf_set_default_prec ((1 << HIBITS) + (1 << LSHIFT1) + (1 << LSHIFT2));
114
115  mpz_init (ds);
116  mpf_inits (a, b, x, NULL);
117
118  for (test = 0; test < reps; test++)
119    {
120      mpz_urandomb (ds, rands, HIBITS);
121      hibits = mpz_get_ui (ds) + 1;
122      mpz_urandomb (ds, rands, hibits);
123      mpz_setbit (ds, hibits  - 1);	/* make sure msb is set */
124      mpf_set_z (a, ds);
125      mpf_set_z (b, ds);
126
127      mpz_urandomb (ds, rands, LSHIFT1);
128      lshift1 = mpz_get_ui (ds);
129      mpf_mul_2exp (a, a, lshift1 + 1);
130      mpf_mul_2exp (b, b, lshift1 + 1);
131      mpf_add_ui (a, a, 1);	/* make a one-bit difference */
132
133      mpz_urandomb (ds, rands, LSHIFT2);
134      lshift2 = mpz_get_ui (ds);
135      mpf_mul_2exp (a, a, lshift2);
136      mpf_mul_2exp (b, b, lshift2);
137      mpz_urandomb (ds, rands, lshift2);
138      mpf_set_z (x, ds);
139      mpf_add (a, a, x);
140      mpf_add (b, b, x);
141
142      insert_random_low_zero_limbs (a, rands);
143      insert_random_low_zero_limbs (b, rands);
144
145      if (mpf_eq (a, b, lshift1 + hibits) == 0 ||
146	  mpf_eq (b, a, lshift1 + hibits) == 0)
147	{
148	  dump_abort (a, b, lshift1 + hibits, lshift1, lshift2, hibits, 1, test);
149	}
150      for (xtra = 1; xtra < 100; xtra++)
151	if (mpf_eq (a, b, lshift1 + hibits + xtra) != 0 ||
152	    mpf_eq (b, a, lshift1 + hibits + xtra) != 0)
153	  {
154	    dump_abort (a, b, lshift1 + hibits + xtra, lshift1, lshift2, hibits, 0, test);
155	  }
156    }
157
158  mpf_clears (a, b, x, NULL);
159  mpz_clear (ds);
160}
161
162void
163insert_random_low_zero_limbs (mpf_t x, gmp_randstate_ptr rands)
164{
165  mp_size_t max = PREC(x) - SIZ(x);
166  mp_size_t s;
167  mpz_t ds; mpz_init (ds);
168  mpz_urandomb (ds, rands, 32);
169  s = mpz_get_ui (ds) % (max + 1);
170  MPN_COPY_DECR (PTR(x) + s, PTR(x), SIZ(x));
171  MPN_ZERO (PTR(x), s);
172  SIZ(x) += s;
173  mpz_clear (ds);
174}
175
176void
177dump_abort (mpf_t a, mpf_t b, int cmp_prec, int lshift1, int lshift2, int hibits, int want, long test)
178{
179  printf ("ERROR in test %ld\n", test);
180  printf ("want %d got %d from mpf_eq\n", want, 1-want);
181  printf ("cmp_prec = %d\n", cmp_prec);
182  printf ("lshift1 = %d\n", lshift1);
183  printf ("lshift2 = %d\n", lshift2);
184  printf ("hibits = %d\n", hibits);
185  hexdump (a); puts ("");
186  hexdump (b); puts ("");
187  abort ();
188}
189
190void
191hexdump (mpf_t x)
192{
193  mp_size_t i;
194  for (i = ABSIZ(x) - 1; i >= 0; i--)
195    {
196      gmp_printf ("%0*MX", SZ, PTR(x)[i]);
197      if (i != 0)
198	printf (" ");
199    }
200}
201
202int
203main (int argc, char *argv[])
204{
205  long reps = 10000;
206
207  if (argc == 2)
208    reps = strtol (argv[1], 0, 0);
209
210  tests_start ();
211
212  check_data ();
213  check_random (reps);
214
215  tests_end ();
216  exit (0);
217}
218