1/* Test mpf_trunc, mpf_ceil, mpf_floor. 2 3Copyright 2001, 2002, 2020 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 (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 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} 271