(root)/
mpfr-4.2.1/
tests/
tget_ld_2exp.c
       1  /* Test mpfr_get_ld_2exp.
       2  
       3  Copyright 2006-2023 Free Software Foundation, Inc.
       4  Contributed by the AriC and Caramba projects, INRIA.
       5  
       6  This file is part of the GNU MPFR Library.
       7  
       8  The GNU MPFR Library is free software; you can redistribute it and/or modify
       9  it under the terms of the GNU Lesser General Public License as published by
      10  the Free Software Foundation; either version 3 of the License, or (at your
      11  option) any later version.
      12  
      13  The GNU MPFR Library is distributed in the hope that it will be useful, but
      14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      15  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      16  License for more details.
      17  
      18  You should have received a copy of the GNU Lesser General Public License
      19  along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
      20  https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
      21  51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
      22  
      23  #include <float.h>
      24  
      25  #include "mpfr-test.h"
      26  
      27  /* Check that hardware rounding doesn't make mpfr_get_ld_2exp return a value
      28     outside its defined range. */
      29  static void
      30  check_round (void)
      31  {
      32    static const unsigned long data[] = {1, 32, 53, 54, 63, 64, 65, 127, 128, 256, 512 };
      33    mpfr_t  f;
      34    long double  got;
      35    long    got_exp;
      36    int     i, rnd_mode, neg;
      37  
      38    mpfr_init2 (f, 1024L);
      39  
      40    RND_LOOP (rnd_mode)
      41      {
      42        for (i = 0; i < (int) numberof (data); i++)
      43          {
      44            mpfr_set_ui (f, 1L, MPFR_RNDZ);
      45            mpfr_mul_2ui (f, f, data[i], MPFR_RNDZ);
      46            mpfr_sub_ui (f, f, 1L, MPFR_RNDZ);
      47  
      48            for (neg = 0; neg <= 1; neg++)
      49              {
      50                got = mpfr_get_ld_2exp (&got_exp, f, (mpfr_rnd_t) rnd_mode);
      51  
      52                if (neg == 0
      53                    ? (got < 0.5 || got >= 1.0)
      54                    : (got <= -1.0 || got > -0.5))
      55                  {
      56                    printf  ("mpfr_get_ld_2exp wrong on 2**%lu-1\n", data[i]);
      57                    printf  ("result out of range, expect 0.5 <= got < 1.0\n");
      58                    printf  ("   rnd_mode = %d\n", rnd_mode);
      59                    printf  ("   data[i]  = %lu\n", data[i]);
      60                    printf  ("   f    ");
      61                    mpfr_out_str (stdout, 2, 0, f, MPFR_RNDN);
      62                    printf  ("\n");
      63                    ld_trace ("   got  ", got);
      64                    printf  ("   got exp  %ld\n", got_exp);
      65                    exit(1);
      66                  }
      67  
      68                mpfr_neg (f, f, MPFR_RNDZ);
      69              }
      70          }
      71      }
      72  
      73    mpfr_clear (f);
      74  }
      75  
      76  
      77  static void
      78  check_inf_nan (void)
      79  {
      80  #if !defined(MPFR_ERRDIVZERO)
      81    mpfr_t  x;
      82    double  d;
      83    long    exp;
      84  
      85    mpfr_init2 (x, 123);
      86  
      87    mpfr_set_inf (x, 1);
      88    d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
      89    MPFR_ASSERTN (d > 0);
      90    MPFR_ASSERTN (DOUBLE_ISINF (d));
      91  
      92    mpfr_set_inf (x, -1);
      93    d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
      94    MPFR_ASSERTN (d < 0);
      95    MPFR_ASSERTN (DOUBLE_ISINF (d));
      96  
      97    mpfr_set_nan (x);
      98    d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
      99    MPFR_ASSERTN (DOUBLE_ISNAN (d));
     100  
     101    mpfr_clear (x);
     102  #endif
     103  }
     104  
     105  static void
     106  bug20090520 (void)
     107  {
     108    mpfr_t x;
     109    long double d, e;
     110    int i;
     111  
     112    mpfr_init (x);
     113    mpfr_set_ui (x, 1, MPFR_RNDN);
     114    d = 1.0;
     115    mpfr_div_2ui (x, x, 16383, MPFR_RNDN);
     116    for (i = 0; i < 16383; i++)
     117      d *= 0.5;
     118    e = mpfr_get_ld (x, MPFR_RNDN);
     119    if (e != d)
     120      {
     121        printf ("mpfr_get_ld(1e-16383) failed\n");
     122        printf ("expected %.20Le\n", d);
     123        printf ("got      %.20Le\n", e);
     124        exit (1);
     125      }
     126    mpfr_clear (x);
     127  }
     128  
     129  static void
     130  bug20180904 (void)
     131  {
     132  #if defined(HAVE_LDOUBLE_IEEE_EXT_LITTLE) || \
     133      defined(HAVE_LDOUBLE_IEEE_EXT_BIG)
     134    mpfr_t x;
     135    long double d = 5.450797408381041489264061250159e-4937L;
     136    long double e;
     137  
     138    mpfr_init2 (x, 64);
     139    mpfr_set_str_binary (x, "0.1000100000000000000000000000000000000000000000000000000000000000E-16397");
     140    e = mpfr_get_ld (x, MPFR_RNDN);
     141    if (e != d)
     142      {
     143        printf ("Error in bug20180904:\n");
     144        printf ("expected %.30Le\n", d);
     145        printf ("got      %.30Le\n", e);
     146        exit (1);
     147      }
     148    mpfr_clear (x);
     149  #endif
     150  }
     151  
     152  int
     153  main (void)
     154  {
     155    tests_start_mpfr ();
     156    mpfr_test_init ();
     157  
     158    bug20180904 ();
     159    bug20090520 ();
     160  
     161    check_round ();
     162    check_inf_nan ();
     163  
     164    tests_end_mpfr ();
     165    return 0;
     166  }