(root)/
gmp-6.3.0/
tests/
mpf/
t-trunc.c
       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
      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
      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
      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
     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
     262  main (void)
     263  {
     264    tests_start ();
     265  
     266    check_various ();
     267  
     268    tests_end ();
     269    exit (0);
     270  }