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