Home | History | Annotate | Line # | Download | only in mpf
      1      1.1  mrg /* Test mpf_get_d_2exp.
      2      1.1  mrg 
      3  1.1.1.5  mrg Copyright 2002, 2003, 2017, 2020 Free Software Foundation, Inc.
      4      1.1  mrg 
      5  1.1.1.2  mrg This file is part of the GNU MP Library test suite.
      6      1.1  mrg 
      7  1.1.1.2  mrg The GNU MP Library test suite is free software; you can redistribute it
      8  1.1.1.2  mrg and/or modify it under the terms of the GNU General Public License as
      9  1.1.1.2  mrg published by the Free Software Foundation; either version 3 of the License,
     10  1.1.1.2  mrg or (at your option) any later version.
     11  1.1.1.2  mrg 
     12  1.1.1.2  mrg The GNU MP Library test suite is distributed in the hope that it will be
     13  1.1.1.2  mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1.1.2  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     15  1.1.1.2  mrg Public License for more details.
     16      1.1  mrg 
     17  1.1.1.2  mrg You should have received a copy of the GNU General Public License along with
     18  1.1.1.3  mrg the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     19      1.1  mrg 
     20      1.1  mrg #include <stdio.h>
     21      1.1  mrg #include <stdlib.h>
     22      1.1  mrg #include "gmp-impl.h"
     23      1.1  mrg #include "tests.h"
     24      1.1  mrg 
     25      1.1  mrg 
     26      1.1  mrg static void
     27  1.1.1.4  mrg check_data (void)
     28      1.1  mrg {
     29      1.1  mrg   mpf_t   f;
     30      1.1  mrg   double  got, want;
     31  1.1.1.4  mrg   long    got_exp;
     32  1.1.1.4  mrg   long    exp;
     33  1.1.1.4  mrg   struct {
     34  1.1.1.4  mrg     int base;
     35  1.1.1.4  mrg     int shift;
     36  1.1.1.4  mrg   } data[] = {
     37  1.1.1.4  mrg    {-1, 1}, {-3, 2}, {-5, 3}, {-7, 3}, { 1, 1}, { 3, 2}, { 5, 3}, { 7, 3}
     38  1.1.1.4  mrg   };
     39      1.1  mrg 
     40  1.1.1.4  mrg   mpf_init2 (f, 3);
     41      1.1  mrg 
     42  1.1.1.5  mrg   got = mpf_get_d_2exp (&got_exp, f);
     43  1.1.1.5  mrg   if (got != 0 || got_exp != 0)
     44  1.1.1.5  mrg     {
     45  1.1.1.5  mrg       printf    ("mpf_get_d_2exp wrong on zero\n");
     46  1.1.1.5  mrg       mpf_trace ("   f    ", f);
     47  1.1.1.5  mrg       d_trace   ("   got  ", got);
     48  1.1.1.5  mrg       printf    ("   got exp  %ld\n", got_exp);
     49  1.1.1.5  mrg       abort();
     50  1.1.1.5  mrg     }
     51  1.1.1.5  mrg 
     52  1.1.1.4  mrg   for (exp = -513; exp <= 513; exp++)
     53      1.1  mrg     {
     54  1.1.1.4  mrg       size_t i;
     55  1.1.1.4  mrg       for (i = 0; i < numberof (data); i++)
     56  1.1.1.4  mrg 	{
     57  1.1.1.4  mrg 	  want = (double) data[i].base / (1 << data[i].shift);
     58  1.1.1.4  mrg 	  mpf_set_d (f, want);
     59  1.1.1.4  mrg 
     60  1.1.1.4  mrg 	  if (exp >= 0)
     61  1.1.1.4  mrg 	    mpf_mul_2exp (f, f, exp);
     62  1.1.1.4  mrg 	  else
     63  1.1.1.4  mrg 	    mpf_div_2exp (f, f, -exp);
     64  1.1.1.4  mrg 
     65  1.1.1.4  mrg 	  got = mpf_get_d_2exp (&got_exp, f);
     66  1.1.1.4  mrg 	  if (got != want || got_exp != exp)
     67  1.1.1.4  mrg 	    {
     68  1.1.1.4  mrg 	      printf    ("mpf_get_d_2exp wrong on 2**%ld\n", exp);
     69  1.1.1.4  mrg 	      mpf_trace ("   f    ", f);
     70  1.1.1.4  mrg 	      d_trace   ("   want ", want);
     71  1.1.1.4  mrg 	      d_trace   ("   got  ", got);
     72  1.1.1.4  mrg 	      printf    ("   want exp %ld\n", exp);
     73  1.1.1.4  mrg 	      printf    ("   got exp  %ld\n", got_exp);
     74  1.1.1.4  mrg 	      abort();
     75  1.1.1.4  mrg 	    }
     76  1.1.1.4  mrg 	}
     77      1.1  mrg     }
     78      1.1  mrg   mpf_clear (f);
     79      1.1  mrg }
     80      1.1  mrg 
     81      1.1  mrg /* Check that hardware rounding doesn't make mpf_get_d_2exp return a value
     82      1.1  mrg    outside its defined range. */
     83      1.1  mrg static void
     84      1.1  mrg check_round (void)
     85      1.1  mrg {
     86      1.1  mrg   static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 };
     87      1.1  mrg   mpf_t   f;
     88      1.1  mrg   double  got;
     89      1.1  mrg   long    got_exp;
     90      1.1  mrg   int     i, rnd_mode, old_rnd_mode;
     91      1.1  mrg 
     92      1.1  mrg   mpf_init2 (f, 1024L);
     93      1.1  mrg   old_rnd_mode = tests_hardware_getround ();
     94      1.1  mrg 
     95      1.1  mrg   for (rnd_mode = 0; rnd_mode < 4; rnd_mode++)
     96      1.1  mrg     {
     97      1.1  mrg       tests_hardware_setround (rnd_mode);
     98      1.1  mrg 
     99      1.1  mrg       for (i = 0; i < numberof (data); i++)
    100      1.1  mrg         {
    101      1.1  mrg           mpf_set_ui (f, 1L);
    102      1.1  mrg           mpf_mul_2exp (f, f, data[i]);
    103      1.1  mrg           mpf_sub_ui (f, f, 1L);
    104      1.1  mrg 
    105      1.1  mrg           got = mpf_get_d_2exp (&got_exp, f);
    106      1.1  mrg           if (got < 0.5 || got >= 1.0)
    107      1.1  mrg             {
    108      1.1  mrg               printf    ("mpf_get_d_2exp bad on 2**%lu-1\n", data[i]);
    109      1.1  mrg               printf    ("result out of range, expect 0.5 <= got < 1.0\n");
    110      1.1  mrg               printf    ("   rnd_mode = %d\n", rnd_mode);
    111      1.1  mrg               printf    ("   data[i]  = %lu\n", data[i]);
    112      1.1  mrg               mpf_trace ("   f    ", f);
    113      1.1  mrg               d_trace   ("   got  ", got);
    114      1.1  mrg               printf    ("   got exp  %ld\n", got_exp);
    115      1.1  mrg               abort();
    116      1.1  mrg             }
    117      1.1  mrg         }
    118      1.1  mrg     }
    119      1.1  mrg 
    120      1.1  mrg   mpf_clear (f);
    121      1.1  mrg   tests_hardware_setround (old_rnd_mode);
    122      1.1  mrg }
    123      1.1  mrg 
    124      1.1  mrg 
    125      1.1  mrg int
    126      1.1  mrg main (void)
    127      1.1  mrg {
    128      1.1  mrg   tests_start ();
    129      1.1  mrg   mp_trace_base = 16;
    130      1.1  mrg 
    131  1.1.1.4  mrg   check_data ();
    132      1.1  mrg   check_round ();
    133      1.1  mrg 
    134      1.1  mrg   tests_end ();
    135      1.1  mrg   exit (0);
    136      1.1  mrg }
    137