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