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