blob: 31fc2bd3f299c3894c94df2e361495c729ebdf9c [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001/* Test mpf_trunc, mpf_ceil, mpf_floor.
2
3Copyright 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the 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
26void
27check_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
41void
42check_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 (ABSIZ(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
90void
91check_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
108void
109check_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
261int
262main (void)
263{
264 tests_start ();
265
266 check_various ();
267
268 tests_end ();
269 exit (0);
270}