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-impl.h"
24 #include "tests.h"
25
26 #define SZ (2 * sizeof(mp_limb_t))
27
28 void insert_random_low_zero_limbs (mpf_t, gmp_randstate_ptr);
29 void dump_abort (mpf_t, mpf_t, int, int, int, int, int, long);
30 void hexdump (mpf_t);
31
32 void
check_data(void)33 check_data (void)
34 {
35 static const struct
36 {
37 struct {
38 int exp, size;
39 mp_limb_t d[10];
40 } x, y;
41 mp_bitcnt_t bits;
42 int want;
43
44 } data[] = {
45 { { 0, 0, { 0 } }, { 0, 0, { 0 } }, 0, 1 },
46
47 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 0, 1 },
48 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 17, 1 },
49 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 4711, 1 },
50
51 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 0, 1 },
52 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 2, 1 },
53 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 3, 0 },
54
55 { { 0, 0, { 0 } }, { 0, 1, { 1 } }, 0, 0 },
56 { { 0, 1, { 1 } }, { 0,-1 ,{ 1 } }, 0, 0 },
57 { { 1, 1, { 1 } }, { 0, 1, { 1 } }, 0, 0 },
58
59 { { 0, 1, { 8 } }, { 0, 1, { 4 } }, 0, 0 },
60
61 { { 0, 2, { 0, 3 } }, { 0, 1, { 3 } }, 1000, 1 },
62 };
63
64 mpf_t x, y;
65 int got, got_swapped;
66 int i;
67 mp_trace_base = 16;
68
69 for (i = 0; i < numberof (data); i++)
70 {
71 PTR(x) = (mp_ptr) data[i].x.d;
72 SIZ(x) = data[i].x.size;
73 EXP(x) = data[i].x.exp;
74 PREC(x) = numberof (data[i].x.d);
75 MPF_CHECK_FORMAT (x);
76
77 PTR(y) = (mp_ptr) data[i].y.d;
78 SIZ(y) = data[i].y.size;
79 EXP(y) = data[i].y.exp;
80 PREC(y) = numberof (data[i].y.d);
81 MPF_CHECK_FORMAT (y);
82
83 got = mpf_eq (x, y, data[i].bits);
84 got_swapped = mpf_eq (y, x, data[i].bits);
85
86 if (got != got_swapped || got != data[i].want)
87 {
88 printf ("check_data() wrong result at data[%d]\n", i);
89 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
99 void
check_random(long reps)100 check_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
162 void
insert_random_low_zero_limbs(mpf_t x,gmp_randstate_ptr rands)163 insert_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
176 void
dump_abort(mpf_t a,mpf_t b,int cmp_prec,int lshift1,int lshift2,int hibits,int want,long test)177 dump_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
190 void
hexdump(mpf_t x)191 hexdump (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
202 int
main(int argc,char * argv[])203 main (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