Tizen 2.1 base
[external/gmp.git] / tests / mpf / t-trunc.c
1 /* Test mpf_trunc, mpf_ceil, mpf_floor.
2
3 Copyright 2001, 2002 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 void
28 check_print (mpf_srcptr src, mpf_srcptr got, mpf_srcptr want)
29 {
30   mp_trace_base = 16;
31   mpf_trace ("src ", src);
32   mpf_trace ("got ", got);
33   mpf_trace ("want", want);
34
35   printf ("got  size=%d exp=%ld\n", SIZ(got), EXP(got));
36   mpn_trace ("     limbs=", PTR(got), (mp_size_t) ABSIZ(got));
37
38   printf ("want size=%d exp=%ld\n", SIZ(want), EXP(want));
39   mpn_trace ("     limbs=", PTR(want), (mp_size_t) ABSIZ(want));
40 }
41
42 void
43 check_one (mpf_srcptr src, mpf_srcptr trunc, mpf_srcptr ceil, mpf_srcptr floor)
44 {
45   mpf_t  got;
46
47   mpf_init2 (got, mpf_get_prec (trunc));
48   ASSERT_ALWAYS (PREC(got) == PREC(trunc));
49   ASSERT_ALWAYS (PREC(got) == PREC(ceil));
50   ASSERT_ALWAYS (PREC(got) == PREC(floor));
51
52 #define CHECK_SEP(name, fun, want)              \
53   mpf_set_ui (got, 54321L); /* initial junk */  \
54   fun (got, src);                               \
55   MPF_CHECK_FORMAT (got);                       \
56   if (mpf_cmp (got, want) != 0)                 \
57     {                                           \
58         printf ("%s wrong\n", name);            \
59         check_print (src, got, want);           \
60         abort ();                               \
61     }
62
63   CHECK_SEP ("mpf_trunc", mpf_trunc, trunc);
64   CHECK_SEP ("mpf_ceil",  mpf_ceil,  ceil);
65   CHECK_SEP ("mpf_floor", mpf_floor, floor);
66
67 #define CHECK_INPLACE(name, fun, want)  \
68   mpf_set (got, src);                   \
69   fun (got, got);                       \
70   MPF_CHECK_FORMAT (got);               \
71   if (mpf_cmp (got, want) != 0)         \
72     {                                   \
73         printf ("%s wrong\n", name);    \
74         check_print (src, got, want);   \
75         abort ();                       \
76     }
77
78   CHECK_INPLACE ("mpf_trunc", mpf_trunc, trunc);
79
80   /* Can't do these unconditionally in case truncation by mpf_set strips
81      some low non-zero limbs which would have rounded the result.  */
82   if (ABSIZ(src) <= PREC(trunc)+1)
83     {
84       CHECK_INPLACE ("mpf_ceil",  mpf_ceil,  ceil);
85       CHECK_INPLACE ("mpf_floor", mpf_floor, floor);
86     }
87
88   mpf_clear (got);
89 }
90
91 void
92 check_all (mpf_ptr src, mpf_ptr trunc, mpf_ptr ceil, mpf_ptr floor)
93 {
94   /* some of these values are generated with direct field assignments */
95   MPF_CHECK_FORMAT (src);
96   MPF_CHECK_FORMAT (trunc);
97   MPF_CHECK_FORMAT (ceil);
98   MPF_CHECK_FORMAT (floor);
99
100   check_one (src, trunc, ceil, floor);
101
102   mpf_neg (src,   src);
103   mpf_neg (trunc, trunc);
104   mpf_neg (ceil,  ceil);
105   mpf_neg (floor, floor);
106   check_one (src, trunc, floor, ceil);
107 }
108
109 void
110 check_various (void)
111 {
112   mpf_t  src, trunc, ceil, floor;
113   int    n, i;
114
115   mpf_init2 (src, 512L);
116   mpf_init2 (trunc, 256L);
117   mpf_init2 (ceil,  256L);
118   mpf_init2 (floor, 256L);
119
120   /* 0 */
121   mpf_set_ui (src, 0L);
122   mpf_set_ui (trunc, 0L);
123   mpf_set_ui (ceil, 0L);
124   mpf_set_ui (floor, 0L);
125   check_all (src, trunc, ceil, floor);
126
127   /* 1 */
128   mpf_set_ui (src, 1L);
129   mpf_set_ui (trunc, 1L);
130   mpf_set_ui (ceil, 1L);
131   mpf_set_ui (floor, 1L);
132   check_all (src, trunc, ceil, floor);
133
134   /* 2^1024 */
135   mpf_set_ui (src, 1L);
136   mpf_mul_2exp (src,   src,   1024L);
137   mpf_set (trunc, src);
138   mpf_set (ceil,  src);
139   mpf_set (floor, src);
140   check_all (src, trunc, ceil, floor);
141
142   /* 1/2^1024, fraction only */
143   mpf_set_ui (src, 1L);
144   mpf_div_2exp (src,  src, 1024L);
145   mpf_set_si (trunc, 0L);
146   mpf_set_si (ceil, 1L);
147   mpf_set_si (floor, 0L);
148   check_all (src, trunc, ceil, floor);
149
150   /* 1/2 */
151   mpf_set_ui (src, 1L);
152   mpf_div_2exp (src,  src, 1L);
153   mpf_set_si (trunc, 0L);
154   mpf_set_si (ceil, 1L);
155   mpf_set_si (floor, 0L);
156   check_all (src, trunc, ceil, floor);
157
158   /* 123+1/2^64 */
159   mpf_set_ui (src, 1L);
160   mpf_div_2exp (src,  src, 64L);
161   mpf_add_ui (src,  src, 123L);
162   mpf_set_si (trunc, 123L);
163   mpf_set_si (ceil, 124L);
164   mpf_set_si (floor, 123L);
165   check_all (src, trunc, ceil, floor);
166
167   /* integer of full prec+1 limbs, unchanged */
168   n = PREC(trunc)+1;
169   ASSERT_ALWAYS (n <= PREC(src)+1);
170   EXP(src) = n;
171   SIZ(src) = n;
172   for (i = 0; i < SIZ(src); i++)
173     PTR(src)[i] = i+100;
174   mpf_set (trunc, src);
175   mpf_set (ceil, src);
176   mpf_set (floor, src);
177   check_all (src, trunc, ceil, floor);
178
179   /* full prec+1 limbs, 1 trimmed for integer */
180   n = PREC(trunc)+1;
181   ASSERT_ALWAYS (n <= PREC(src)+1);
182   EXP(src) = n-1;
183   SIZ(src) = n;
184   for (i = 0; i < SIZ(src); i++)
185     PTR(src)[i] = i+200;
186   EXP(trunc) = n-1;
187   SIZ(trunc) = n-1;
188   for (i = 0; i < SIZ(trunc); i++)
189     PTR(trunc)[i] = i+201;
190   mpf_set (floor, trunc);
191   mpf_add_ui (ceil, trunc, 1L);
192   check_all (src, trunc, ceil, floor);
193
194   /* prec+3 limbs, 2 trimmed for size */
195   n = PREC(trunc)+3;
196   ASSERT_ALWAYS (n <= PREC(src)+1);
197   EXP(src) = n;
198   SIZ(src) = n;
199   for (i = 0; i < SIZ(src); i++)
200     PTR(src)[i] = i+300;
201   EXP(trunc) = n;
202   SIZ(trunc) = n-2;
203   for (i = 0; i < SIZ(trunc); i++)
204     PTR(trunc)[i] = i+302;
205   mpf_set (floor, trunc);
206   mpf_set (ceil, trunc);
207   PTR(ceil)[0]++;
208   check_all (src, trunc, ceil, floor);
209
210   /* prec+4 limbs, 2 trimmed for size, 1 trimmed for integer */
211   n = PREC(trunc)+4;
212   ASSERT_ALWAYS (n <= PREC(src)+1);
213   EXP(src) = n-1;
214   SIZ(src) = n;
215   for (i = 0; i < SIZ(src); i++)
216     PTR(src)[i] = i+400;
217   EXP(trunc) = n-1;
218   SIZ(trunc) = n-3;
219   for (i = 0; i < SIZ(trunc); i++)
220     PTR(trunc)[i] = i+403;
221   mpf_set (floor, trunc);
222   mpf_set (ceil, trunc);
223   PTR(ceil)[0]++;
224   check_all (src, trunc, ceil, floor);
225
226   /* F.F, carry out of ceil */
227   EXP(src) = 1;
228   SIZ(src) = 2;
229   PTR(src)[0] = GMP_NUMB_MAX;
230   PTR(src)[1] = GMP_NUMB_MAX;
231   EXP(trunc) = 1;
232   SIZ(trunc) = 1;
233   PTR(trunc)[0] = GMP_NUMB_MAX;
234   mpf_set (floor, trunc);
235   EXP(ceil) = 2;
236   SIZ(ceil) = 1;
237   PTR(ceil)[0] = 1;
238   check_all (src, trunc, ceil, floor);
239
240   /* FF.F, carry out of ceil */
241   EXP(src) = 2;
242   SIZ(src) = 3;
243   PTR(src)[0] = GMP_NUMB_MAX;
244   PTR(src)[1] = GMP_NUMB_MAX;
245   PTR(src)[2] = GMP_NUMB_MAX;
246   EXP(trunc) = 2;
247   SIZ(trunc) = 2;
248   PTR(trunc)[0] = GMP_NUMB_MAX;
249   PTR(trunc)[1] = GMP_NUMB_MAX;
250   mpf_set (floor, trunc);
251   EXP(ceil) = 3;
252   SIZ(ceil) = 1;
253   PTR(ceil)[0] = 1;
254   check_all (src, trunc, ceil, floor);
255
256   mpf_clear (src);
257   mpf_clear (trunc);
258   mpf_clear (ceil);
259   mpf_clear (floor);
260 }
261
262 int
263 main (void)
264 {
265   tests_start ();
266
267   check_various ();
268
269   tests_end ();
270   exit (0);
271 }