Upload Tizen:Base source
[external/gmp.git] / tests / mpz / t-get_d_2exp.c
1 /* Test mpz_get_d_2exp.
2
3 Copyright 2002, 2003 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along 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
27 static void
28 check_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. */
79 static void
80 check_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
134 static void
135 check_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
184 int
185 main (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 }