(root)/
gmp-6.3.0/
tests/
mpf/
t-get_d_2exp.c
       1  /* Test mpf_get_d_2exp.
       2  
       3  Copyright 2002, 2003, 2017, 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  static void
      27  check_data (void)
      28  {
      29    mpf_t   f;
      30    double  got, want;
      31    long    got_exp;
      32    long    exp;
      33    struct {
      34      int base;
      35      int shift;
      36    } data[] = {
      37     {-1, 1}, {-3, 2}, {-5, 3}, {-7, 3}, { 1, 1}, { 3, 2}, { 5, 3}, { 7, 3}
      38    };
      39  
      40    mpf_init2 (f, 3);
      41  
      42    got = mpf_get_d_2exp (&got_exp, f);
      43    if (got != 0 || got_exp != 0)
      44      {
      45        printf    ("mpf_get_d_2exp wrong on zero\n");
      46        mpf_trace ("   f    ", f);
      47        d_trace   ("   got  ", got);
      48        printf    ("   got exp  %ld\n", got_exp);
      49        abort();
      50      }
      51  
      52    for (exp = -513; exp <= 513; exp++)
      53      {
      54        size_t i;
      55        for (i = 0; i < numberof (data); i++)
      56  	{
      57  	  want = (double) data[i].base / (1 << data[i].shift);
      58  	  mpf_set_d (f, want);
      59  
      60  	  if (exp >= 0)
      61  	    mpf_mul_2exp (f, f, exp);
      62  	  else
      63  	    mpf_div_2exp (f, f, -exp);
      64  
      65  	  got = mpf_get_d_2exp (&got_exp, f);
      66  	  if (got != want || got_exp != exp)
      67  	    {
      68  	      printf    ("mpf_get_d_2exp wrong on 2**%ld\n", exp);
      69  	      mpf_trace ("   f    ", f);
      70  	      d_trace   ("   want ", want);
      71  	      d_trace   ("   got  ", got);
      72  	      printf    ("   want exp %ld\n", exp);
      73  	      printf    ("   got exp  %ld\n", got_exp);
      74  	      abort();
      75  	    }
      76  	}
      77      }
      78    mpf_clear (f);
      79  }
      80  
      81  /* Check that hardware rounding doesn't make mpf_get_d_2exp return a value
      82     outside its defined range. */
      83  static void
      84  check_round (void)
      85  {
      86    static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 };
      87    mpf_t   f;
      88    double  got;
      89    long    got_exp;
      90    int     i, rnd_mode, old_rnd_mode;
      91  
      92    mpf_init2 (f, 1024L);
      93    old_rnd_mode = tests_hardware_getround ();
      94  
      95    for (rnd_mode = 0; rnd_mode < 4; rnd_mode++)
      96      {
      97        tests_hardware_setround (rnd_mode);
      98  
      99        for (i = 0; i < numberof (data); i++)
     100          {
     101            mpf_set_ui (f, 1L);
     102            mpf_mul_2exp (f, f, data[i]);
     103            mpf_sub_ui (f, f, 1L);
     104  
     105            got = mpf_get_d_2exp (&got_exp, f);
     106            if (got < 0.5 || got >= 1.0)
     107              {
     108                printf    ("mpf_get_d_2exp bad on 2**%lu-1\n", data[i]);
     109                printf    ("result out of range, expect 0.5 <= got < 1.0\n");
     110                printf    ("   rnd_mode = %d\n", rnd_mode);
     111                printf    ("   data[i]  = %lu\n", data[i]);
     112                mpf_trace ("   f    ", f);
     113                d_trace   ("   got  ", got);
     114                printf    ("   got exp  %ld\n", got_exp);
     115                abort();
     116              }
     117          }
     118      }
     119  
     120    mpf_clear (f);
     121    tests_hardware_setround (old_rnd_mode);
     122  }
     123  
     124  
     125  int
     126  main (void)
     127  {
     128    tests_start ();
     129    mp_trace_base = 16;
     130  
     131    check_data ();
     132    check_round ();
     133  
     134    tests_end ();
     135    exit (0);
     136  }