t-get_d_2exp.c revision 1.1.1.2
1/* Test mpz_get_d_2exp.
2
3Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the GNU MP Library test suite.  If not, see http://www.gnu.org/licenses/.  */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include "gmp.h"
23#include "gmp-impl.h"
24#include "tests.h"
25
26
27static void
28check_zero (void)
29{
30  mpz_t   z;
31  double  got, want;
32  long    got_exp, want_exp;
33
34  mpz_init_set_ui (z, 0);
35
36  want = 0.0;
37  want_exp = 0;
38  got = mpz_get_d_2exp (&got_exp, z);
39  if (got != want || got_exp != want_exp)
40    {
41      printf    ("mpz_get_d_2exp wrong on zero\n");
42      mpz_trace ("   z    ", z);
43      d_trace   ("   want ", want);
44      d_trace   ("   got  ", got);
45      printf    ("   want exp %ld\n", want_exp);
46      printf    ("   got exp  %ld\n", got_exp);
47      abort();
48    }
49
50  mpz_clear (z);
51}
52
53static void
54check_onebit (void)
55{
56  static const unsigned long data[] = {
57    1, 32, 52, 53, 54, 63, 64, 65, 128, 256, 511, 512, 513
58  };
59  mpz_t   z;
60  double  got, want;
61  long    got_exp, want_exp;
62  int     i;
63
64  mpz_init (z);
65
66  for (i = 0; i < numberof (data); i++)
67    {
68      mpz_set_ui (z, 1L);
69      mpz_mul_2exp (z, z, data[i]);
70      want = 0.5;
71      want_exp = data[i] + 1;
72      got = mpz_get_d_2exp (&got_exp, z);
73      if (got != want || got_exp != want_exp)
74        {
75          printf    ("mpz_get_d_2exp wrong on 2**%ld\n", data[i]);
76          mpz_trace ("   z    ", z);
77          d_trace   ("   want ", want);
78          d_trace   ("   got  ", got);
79          printf    ("   want exp %ld\n", want_exp);
80          printf    ("   got exp  %ld\n", got_exp);
81          abort();
82        }
83
84      mpz_set_si (z, -1L);
85      mpz_mul_2exp (z, z, data[i]);
86      want = -0.5;
87      want_exp = data[i] + 1;
88      got = mpz_get_d_2exp (&got_exp, z);
89      if (got != want || got_exp != want_exp)
90        {
91          printf    ("mpz_get_d_2exp wrong on -2**%ld\n", data[i]);
92          mpz_trace ("   z    ", z);
93          d_trace   ("   want ", want);
94          d_trace   ("   got  ", got);
95          printf    ("   want exp %ld\n", want_exp);
96          printf    ("   got exp  %ld\n", got_exp);
97          abort();
98        }
99    }
100  mpz_clear (z);
101}
102
103/* Check that hardware rounding doesn't make mpz_get_d_2exp return a value
104   outside its defined range. */
105static void
106check_round (void)
107{
108  static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 };
109  mpz_t   z;
110  double  got;
111  long    got_exp;
112  int     i, rnd_mode, old_rnd_mode;
113
114  mpz_init (z);
115  old_rnd_mode = tests_hardware_getround ();
116
117  for (rnd_mode = 0; rnd_mode < 4; rnd_mode++)
118    {
119      tests_hardware_setround (rnd_mode);
120
121      for (i = 0; i < numberof (data); i++)
122        {
123          mpz_set_ui (z, 1L);
124          mpz_mul_2exp (z, z, data[i]);
125          mpz_sub_ui (z, z, 1L);
126
127          got = mpz_get_d_2exp (&got_exp, z);
128          if (got < 0.5 || got >= 1.0)
129            {
130              printf    ("mpz_get_d_2exp wrong on 2**%lu-1\n", data[i]);
131              printf    ("result out of range, expect 0.5 <= got < 1.0\n");
132              printf    ("   rnd_mode = %d\n", rnd_mode);
133              printf    ("   data[i]  = %lu\n", data[i]);
134              mpz_trace ("   z    ", z);
135              d_trace   ("   got  ", got);
136              printf    ("   got exp  %ld\n", got_exp);
137              abort();
138            }
139
140          mpz_neg (z, z);
141          got = mpz_get_d_2exp (&got_exp, z);
142          if (got <= -1.0 || got > -0.5)
143            {
144              printf    ("mpz_get_d_2exp wrong on -2**%lu-1\n", data[i]);
145              printf    ("result out of range, expect -1.0 < got <= -0.5\n");
146              printf    ("   rnd_mode = %d\n", rnd_mode);
147              printf    ("   data[i]  = %lu\n", data[i]);
148              mpz_trace ("   z    ", z);
149              d_trace   ("   got  ", got);
150              printf    ("   got exp  %ld\n", got_exp);
151              abort();
152            }
153        }
154    }
155
156  mpz_clear (z);
157  tests_hardware_setround (old_rnd_mode);
158}
159
160static void
161check_rand (void)
162{
163  gmp_randstate_ptr rands = RANDS;
164  int     i;
165  mpz_t   z;
166  double  got;
167  long    got_exp;
168  unsigned long  bits;
169
170  mpz_init (z);
171
172  for (i = 0; i < 200; i++)
173    {
174      bits = gmp_urandomm_ui (rands, 512L);
175      mpz_urandomb (z, rands, bits);
176
177      got = mpz_get_d_2exp (&got_exp, z);
178      if (mpz_sgn (z) == 0)
179        continue;
180      bits = mpz_sizeinbase (z, 2);
181
182      if (got < 0.5 || got >= 1.0)
183        {
184          printf    ("mpz_get_d_2exp out of range, expect 0.5 <= got < 1.0\n");
185          mpz_trace ("   z    ", z);
186          d_trace   ("   got  ", got);
187          printf    ("   got exp  %ld\n", got_exp);
188          abort();
189        }
190
191      /* FIXME: If mpz_get_d_2exp rounds upwards we might have got_exp ==
192         bits+1, so leave this test disabled until we decide if that's what
193         should happen, or not.  */
194#if 0
195      if (got_exp != bits)
196        {
197          printf    ("mpz_get_d_2exp wrong exponent\n", i);
198          mpz_trace ("   z    ", z);
199          d_trace   ("   bits ", bits);
200          d_trace   ("   got  ", got);
201          printf    ("   got exp  %ld\n", got_exp);
202          abort();
203        }
204#endif
205    }
206  mpz_clear (z);
207}
208
209
210int
211main (void)
212{
213  tests_start ();
214  mp_trace_base = -16;
215
216  check_zero ();
217  check_onebit ();
218  check_round ();
219  check_rand ();
220
221  tests_end ();
222  exit (0);
223}
224