1 /* Test of splitting a 'long double' into fraction and mantissa.
2    Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
18 
19 #include <config.h>
20 
21 #include "printf-frexpl.h"
22 
23 #include <float.h>
24 
25 #include "fpucw.h"
26 #include "macros.h"
27 
28 /* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable
29    exponent for 'long double' is -964.  Similarly, on PowerPC machines,
30    LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double'
31    is -968.  For exponents below that, the precision may be truncated to the
32    precision used for 'double'.  */
33 #ifdef __sgi
34 # define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57)
35 # define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP
36 #elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__
37 # define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53)
38 # define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP
39 #else
40 # define MIN_NORMAL_EXP LDBL_MIN_EXP
41 # define MIN_SUBNORMAL_EXP (LDBL_MIN_EXP - 100)
42 #endif
43 
44 static long double
my_ldexp(long double x,int d)45 my_ldexp (long double x, int d)
46 {
47   for (; d > 0; d--)
48     x *= 2.0L;
49   for (; d < 0; d++)
50     x *= 0.5L;
51   return x;
52 }
53 
54 int
main()55 main ()
56 {
57   int i;
58   long double x;
59   DECL_LONG_DOUBLE_ROUNDING
60 
61   BEGIN_LONG_DOUBLE_ROUNDING ();
62 
63   for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
64     {
65       int exp = -9999;
66       long double mantissa = printf_frexpl (x, &exp);
67       ASSERT (exp == i - 1);
68       ASSERT (mantissa == 1.0L);
69     }
70   for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
71     {
72       int exp = -9999;
73       long double mantissa = printf_frexpl (x, &exp);
74       ASSERT (exp == i - 1);
75       ASSERT (mantissa == 1.0L);
76     }
77   for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
78     {
79       int exp = -9999;
80       long double mantissa = printf_frexpl (x, &exp);
81       ASSERT (exp == LDBL_MIN_EXP - 1);
82       ASSERT (mantissa == my_ldexp (1.0L, i - LDBL_MIN_EXP));
83     }
84 
85   for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
86     {
87       int exp = -9999;
88       long double mantissa = printf_frexpl (x, &exp);
89       ASSERT (exp == i - 1);
90       ASSERT (mantissa == 1.01L);
91     }
92   for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
93     {
94       int exp = -9999;
95       long double mantissa = printf_frexpl (x, &exp);
96       ASSERT (exp == i - 1);
97       ASSERT (mantissa == 1.01L);
98     }
99   for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
100     {
101       int exp = -9999;
102       long double mantissa = printf_frexpl (x, &exp);
103       ASSERT (exp == LDBL_MIN_EXP - 1);
104       ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP));
105       ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP));
106       ASSERT (mantissa == my_ldexp (x, - exp));
107     }
108 
109   for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
110     {
111       int exp = -9999;
112       long double mantissa = printf_frexpl (x, &exp);
113       ASSERT (exp == i - 1);
114       ASSERT (mantissa == 1.73205L);
115     }
116   for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
117     {
118       int exp = -9999;
119       long double mantissa = printf_frexpl (x, &exp);
120       ASSERT (exp == i - 1);
121       ASSERT (mantissa == 1.73205L);
122     }
123   for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
124     {
125       int exp = -9999;
126       long double mantissa = printf_frexpl (x, &exp);
127       ASSERT (exp == LDBL_MIN_EXP - 1);
128       ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP));
129       ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP));
130       ASSERT (mantissa == my_ldexp (x, - exp));
131     }
132 
133   return 0;
134 }
135