(root)/
mpfr-4.2.1/
tests/
tget_d.c
       1  /* Test file for mpfr_get_d
       2  
       3  Copyright 1999-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  #include "ieee_floats.h"
      27  
      28  static int
      29  check_subnorm (void)
      30  {
      31    mpfr_rnd_t rnd_mode;
      32    mpfr_t x;
      33    double d, d2, dd, f;
      34    int fail = 0, k, n;
      35  
      36    mpfr_init2 (x, GMP_NUMB_BITS);
      37  
      38    rnd_mode = MPFR_RNDN;
      39    for (k = -17; k <= 17; k += 2)
      40      {
      41        d = (double) k * DBL_MIN; /* k * 2^(-1022) */
      42        f = 1.0;
      43        mpfr_set_si (x, k, MPFR_RNDN);
      44        mpfr_div_2ui (x, x, 1022, MPFR_RNDN); /* k * 2^(-1022) */
      45        for (n = 0; n <= 58; n++)
      46          {
      47            d2 = d * f;
      48            dd = mpfr_get_d (x, rnd_mode);
      49            if (d2 != dd) /* should be k * 2^(-1022-n) for n < 53 */
      50              {
      51                printf ("Wrong result for %d * 2^(%d), rnd_mode %d\n",
      52                        k, -1022-n, rnd_mode);
      53                printf ("got %.20e instead of %.20e\n", dd, d2);
      54                fail = 1;
      55              }
      56            f *= 0.5;
      57            mpfr_div_2ui (x, x, 1, MPFR_RNDN);
      58          }
      59      }
      60  
      61    mpfr_set_str_binary (x, "1e-1074");
      62    dd = mpfr_get_d (x, MPFR_RNDA);
      63    d2 = DBL_MIN; /* 2^(-1022) */
      64    for (k = 0; k < 52; k++)
      65      d2 *= 0.5;  /* 2^(-1074) */
      66    /* we first check that d2 is not zero (it could happen on a platform with
      67       no subnormals) */
      68    if (d2 != 0.0 && dd != d2)
      69      {
      70        printf ("Error for x=1e-1074, RNDA\n");
      71        exit (1);
      72      }
      73  
      74    mpfr_set_str_binary (x, "1e-1075");
      75    dd = mpfr_get_d (x, MPFR_RNDA);
      76    if (d2 != 0.0 && dd != d2)
      77      {
      78        printf ("Error for x=1e-1075, RNDA\n");
      79        printf ("expected %.16e\n", d2);
      80        printf ("got      %.16e\n", dd);
      81        exit (1);
      82      }
      83  
      84    mpfr_clear (x);
      85    return fail;
      86  }
      87  
      88  static void
      89  check_inf_nan (void)
      90  {
      91    /* only if nans and infs are available */
      92  #if !defined(MPFR_ERRDIVZERO)
      93    mpfr_t  x;
      94    double  d;
      95  
      96    mpfr_init2 (x, 123);
      97  
      98    mpfr_set_inf (x, 1);
      99    d = mpfr_get_d (x, MPFR_RNDZ);
     100    MPFR_ASSERTN (d > 0);
     101    MPFR_ASSERTN (DOUBLE_ISINF (d));
     102  
     103    mpfr_set_inf (x, -1);
     104    d = mpfr_get_d (x, MPFR_RNDZ);
     105    MPFR_ASSERTN (d < 0);
     106    MPFR_ASSERTN (DOUBLE_ISINF (d));
     107  
     108    mpfr_set_nan (x);
     109    d = mpfr_get_d (x, MPFR_RNDZ);
     110    if (!DOUBLE_ISNAN (d))
     111      {
     112        printf ("Error in check_inf_nan() for NaN, got %.17g\n", d);
     113        printf ("MPFR_DBL_NAN is %.17g (should be NaN)\n", MPFR_DBL_NAN);
     114        exit (1);
     115      }
     116  
     117    mpfr_clear (x);
     118  #endif
     119  }
     120  
     121  static void
     122  check_max (void)
     123  {
     124    double d, e;
     125    mpfr_t u;
     126  
     127    d = 1.0;
     128    while (d < (DBL_MAX / 2.0))
     129      d += d;
     130    mpfr_init (u);
     131    if (mpfr_set_d (u, d, MPFR_RNDN) == 0)
     132      {
     133        /* If setting is exact */
     134        e = (mpfr_get_d1) (u);
     135        if (e != d)
     136          {
     137            printf ("get_d(set_d)(1): %1.20e != %1.20e\n", d, e);
     138            exit (1);
     139          }
     140      }
     141  
     142    mpfr_set_str_binary (u, "-1E1024");
     143    d = mpfr_get_d (u, MPFR_RNDZ);
     144    MPFR_ASSERTN(d == -DBL_MAX);
     145    d = mpfr_get_d (u, MPFR_RNDU);
     146    MPFR_ASSERTN(d == -DBL_MAX);
     147  #if !defined(MPFR_ERRDIVZERO)
     148    d = mpfr_get_d (u, MPFR_RNDN);
     149    MPFR_ASSERTN(DOUBLE_ISINF(d) && d < 0.0);
     150    d = mpfr_get_d (u, MPFR_RNDD);
     151    MPFR_ASSERTN(DOUBLE_ISINF(d) && d < 0.0);
     152  #endif
     153  
     154    mpfr_set_str_binary (u, "1E1024");
     155    d = mpfr_get_d (u, MPFR_RNDZ);
     156    MPFR_ASSERTN(d == DBL_MAX);
     157    d = mpfr_get_d (u, MPFR_RNDD);
     158    MPFR_ASSERTN(d == DBL_MAX);
     159  #if !defined(MPFR_ERRDIVZERO)
     160    d = mpfr_get_d (u, MPFR_RNDN);
     161    MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0);
     162    d = mpfr_get_d (u, MPFR_RNDU);
     163    MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0);
     164  #endif
     165  
     166    mpfr_clear (u);
     167  }
     168  
     169  static void
     170  check_min(void)
     171  {
     172    double d, e;
     173    mpfr_t u;
     174  
     175    d = 1.0; while (d > (DBL_MIN * 2.0)) d /= 2.0;
     176    mpfr_init(u);
     177    if (mpfr_set_d(u, d, MPFR_RNDN) == 0)
     178      {
     179        /* If setting is exact */
     180        e = mpfr_get_d1(u);
     181        if (e != d)
     182          {
     183            printf("get_d(set_d)(2): %1.20e != %1.20e\n", d, e);
     184            exit(1);
     185          }
     186      }
     187    mpfr_clear(u);
     188  }
     189  
     190  static void
     191  check_get_d_2exp_inf_nan (void)
     192  {
     193  #if !defined(MPFR_ERRDIVZERO)
     194  
     195    double var_d;
     196    long exp;
     197    mpfr_t var;
     198  
     199    mpfr_init2 (var, MPFR_PREC_MIN);
     200  
     201    mpfr_set_nan (var);
     202    var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN);
     203    if (!DOUBLE_ISNAN (var_d))
     204      {
     205        printf ("mpfr_get_d_2exp on NaN returned a wrong value: %.17g\n",
     206                var_d);
     207        printf ("MPFR_DBL_NAN is %.17g (should be NaN)\n", MPFR_DBL_NAN);
     208        exit (1);
     209      }
     210  
     211    mpfr_set_zero (var, 1);
     212    var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN);
     213    if (exp != 0 || var_d != 0.0)
     214      {
     215        printf ("mpfr_get_d_2exp on +0.0 returned a wrong value:\n"
     216                " expected 0.0, got %.17g\n"
     217                " exp: expected 0, got %ld\n",
     218                var_d, exp);
     219        exit (1);
     220      }
     221  
     222    mpfr_set_zero (var, -1);
     223    var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN);
     224    /* Note: the sign of the negative zero (when supported) is not checked. */
     225    if (exp != 0 || var_d != DBL_NEG_ZERO)
     226      {
     227        printf ("mpfr_get_d_2exp on -0.0 returned a wrong value:\n"
     228                " expected %.17g, got %.17g\n"
     229                " exp: expected 0, got %ld\n",
     230                DBL_NEG_ZERO, var_d, exp);
     231        exit (1);
     232      }
     233  
     234    mpfr_set_inf (var, 1);
     235    var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN);
     236    if (var_d != MPFR_DBL_INFP)
     237      {
     238        printf ("mpfr_get_d_2exp on +Inf returned a wrong value:\n"
     239                " expected %g, got %g\n", MPFR_DBL_INFP, var_d);
     240        exit (1);
     241      }
     242  
     243    mpfr_set_inf (var, -1);
     244    var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN);
     245    if (var_d != MPFR_DBL_INFM)
     246      {
     247        printf ("mpfr_get_d_2exp on -Inf returned a wrong value:\n"
     248                " expected %g, got %g\n", MPFR_DBL_INFM, var_d);
     249        exit (1);
     250      }
     251  
     252    mpfr_clear (var);
     253  
     254  #endif
     255  }
     256  
     257  int
     258  main (void)
     259  {
     260    tests_start_mpfr ();
     261    mpfr_test_init ();
     262  
     263  #ifndef MPFR_DOUBLE_SPEC
     264    printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n"
     265            "that you do not have a conforming C implementation and problems\n"
     266            "may occur with conversions between MPFR numbers and standard\n"
     267            "floating-point types. Please contact the MPFR team.\n");
     268  #elif MPFR_DOUBLE_SPEC == 0
     269    /*
     270    printf ("The type 'double' of your C implementation does not seem to\n"
     271            "correspond to the IEEE-754 double precision. Though code has\n"
     272            "been written to support such implementations, tests have been\n"
     273            "done only on IEEE-754 double-precision implementations and\n"
     274            "conversions between MPFR numbers and standard floating-point\n"
     275            "types may be inaccurate. You may wish to contact the MPFR team\n"
     276            "for further testing.\n");
     277    */
     278    printf ("The type 'double' of your C implementation does not seem to\n"
     279            "correspond to the IEEE-754 double precision. Such particular\n"
     280            "implementations are not supported yet, and conversions between\n"
     281            "MPFR numbers and standard floating-point types may be very\n"
     282            "inaccurate.\n");
     283    printf ("FLT_RADIX    = %ld\n", (long) FLT_RADIX);
     284    printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG);
     285    printf ("DBL_MIN_EXP  = %ld\n", (long) DBL_MIN_EXP);
     286    printf ("DBL_MAX_EXP  = %ld\n", (long) DBL_MAX_EXP);
     287  #endif
     288  
     289    if (check_subnorm ())
     290      exit (1);
     291  
     292    check_inf_nan ();
     293    check_min();
     294    check_max();
     295  
     296    check_get_d_2exp_inf_nan ();
     297  
     298    tests_end_mpfr ();
     299    return 0;
     300  }
     301