xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpf/t-trunc.c (revision eceb233b9bd0dfebb902ed73b531ae6964fa3f9b)
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 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 #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 }
272