xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpf/t-get_d_2exp.c (revision 1daf83e636cd998f45e5597a8f995a540e2d5b4a)
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
check_data(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
check_round(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
main(void)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 }
137