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