1 /* Copyright (C) 1995-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library 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 GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include "gmp.h"
19 #include "gmp-impl.h"
20 #include "longlong.h"
21 #include <ieee754.h>
22 #include <float.h>
23 #include <math.h>
24 #include <stdlib.h>
25 
26 /* Convert a `long double' in IBM extended format to a multi-precision
27    integer representing the significand scaled up by its number of
28    bits (106 for long double) and an integral power of two (MPN
29    frexpl). */
30 
31 
32 /* When signs differ, the actual value is the difference between the
33    significant double and the less significant double.  Sometimes a
34    bit can be lost when we borrow from the significant mantissa.  */
35 #define EXTRA_INTERNAL_PRECISION (7)
36 
37 mp_size_t
__mpn_extract_long_double(mp_ptr res_ptr,mp_size_t size,int * expt,int * is_neg,long double value)38 __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
39 			   int *expt, int *is_neg,
40 			   long double value)
41 {
42   union ibm_extended_long_double u;
43   unsigned long long hi, lo;
44   int ediff;
45 
46   u.ld = value;
47 
48   *is_neg = u.d[0].ieee.negative;
49   *expt = (int) u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS;
50 
51   lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
52   hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
53 
54   /* Hold 7 extra bits of precision in the mantissa.  This allows
55      the normalizing shifts below to prevent losing precision when
56      the signs differ and the exponents are sufficiently far apart.  */
57   lo <<= EXTRA_INTERNAL_PRECISION;
58 
59   /* If the lower double is not a denormal or zero then set the hidden
60      53rd bit.  */
61   if (u.d[1].ieee.exponent != 0)
62     lo |= 1ULL << (52 + EXTRA_INTERNAL_PRECISION);
63   else
64     lo = lo << 1;
65 
66   /* The lower double is normalized separately from the upper.  We may
67      need to adjust the lower manitissa to reflect this.  */
68   ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;
69   if (ediff > 0)
70     {
71       if (ediff < 64)
72 	lo = lo >> ediff;
73       else
74 	lo = 0;
75     }
76   else if (ediff < 0)
77     lo = lo << -ediff;
78 
79   /* The high double may be rounded and the low double reflects the
80      difference between the long double and the rounded high double
81      value.  This is indicated by a differnce between the signs of the
82      high and low doubles.  */
83   if (u.d[0].ieee.negative != u.d[1].ieee.negative
84       && lo != 0)
85     {
86       lo = (1ULL << (53 + EXTRA_INTERNAL_PRECISION)) - lo;
87       if (hi == 0)
88 	{
89 	  /* we have a borrow from the hidden bit, so shift left 1.  */
90 	  hi = 0x000ffffffffffffeLL | (lo >> (52 + EXTRA_INTERNAL_PRECISION));
91 	  lo = 0x0fffffffffffffffLL & (lo << 1);
92 	  (*expt)--;
93 	}
94       else
95 	hi--;
96     }
97 #if BITS_PER_MP_LIMB == 32
98   /* Combine the mantissas to be contiguous.  */
99   res_ptr[0] = lo >> EXTRA_INTERNAL_PRECISION;
100   res_ptr[1] = (hi << (53 - 32)) | (lo >> (32 + EXTRA_INTERNAL_PRECISION));
101   res_ptr[2] = hi >> 11;
102   res_ptr[3] = hi >> (32 + 11);
103   #define N 4
104 #elif BITS_PER_MP_LIMB == 64
105   /* Combine the two mantissas to be contiguous.  */
106   res_ptr[0] = (hi << 53) | (lo >> EXTRA_INTERNAL_PRECISION);
107   res_ptr[1] = hi >> 11;
108   #define N 2
109 #else
110   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
111 #endif
112 /* The format does not fill the last limb.  There are some zeros.  */
113 #define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
114 			   - (LDBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
115 
116   if (u.d[0].ieee.exponent == 0)
117     {
118       /* A biased exponent of zero is a special case.
119 	 Either it is a zero or it is a denormal number.  */
120       if (res_ptr[0] == 0 && res_ptr[1] == 0
121 	  && res_ptr[N - 2] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=4.  */
122 	/* It's zero.  */
123 	*expt = 0;
124       else
125 	{
126 	  /* It is a denormal number, meaning it has no implicit leading
127 	     one bit, and its exponent is in fact the format minimum.  We
128 	     use DBL_MIN_EXP instead of LDBL_MIN_EXP below because the
129 	     latter describes the properties of both parts together, but
130 	     the exponent is computed from the high part only.  */
131 	  int cnt;
132 
133 #if N == 2
134 	  if (res_ptr[N - 1] != 0)
135 	    {
136 	      count_leading_zeros (cnt, res_ptr[N - 1]);
137 	      cnt -= NUM_LEADING_ZEROS;
138 	      res_ptr[N - 1] = res_ptr[N - 1] << cnt
139 			       | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
140 	      res_ptr[0] <<= cnt;
141 	      *expt = DBL_MIN_EXP - 1 - cnt;
142 	    }
143 	  else
144 	    {
145 	      count_leading_zeros (cnt, res_ptr[0]);
146 	      if (cnt >= NUM_LEADING_ZEROS)
147 		{
148 		  res_ptr[N - 1] = res_ptr[0] << (cnt - NUM_LEADING_ZEROS);
149 		  res_ptr[0] = 0;
150 		}
151 	      else
152 		{
153 		  res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
154 		  res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
155 		}
156 	      *expt = DBL_MIN_EXP - 1
157 		- (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
158 	    }
159 #else
160 	  int j, k, l;
161 
162 	  for (j = N - 1; j > 0; j--)
163 	    if (res_ptr[j] != 0)
164 	      break;
165 
166 	  count_leading_zeros (cnt, res_ptr[j]);
167 	  cnt -= NUM_LEADING_ZEROS;
168 	  l = N - 1 - j;
169 	  if (cnt < 0)
170 	    {
171 	      cnt += BITS_PER_MP_LIMB;
172 	      l--;
173 	    }
174 	  if (!cnt)
175 	    for (k = N - 1; k >= l; k--)
176 	      res_ptr[k] = res_ptr[k-l];
177 	  else
178 	    {
179 	      for (k = N - 1; k > l; k--)
180 		res_ptr[k] = res_ptr[k-l] << cnt
181 			     | res_ptr[k-l-1] >> (BITS_PER_MP_LIMB - cnt);
182 	      res_ptr[k--] = res_ptr[0] << cnt;
183 	    }
184 
185 	  for (; k >= 0; k--)
186 	    res_ptr[k] = 0;
187 	  *expt = DBL_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
188 #endif
189 	}
190     }
191   else
192     /* Add the implicit leading one bit for a normalized number.  */
193     res_ptr[N - 1] |= (mp_limb_t) 1 << (LDBL_MANT_DIG - 1
194 					- ((N - 1) * BITS_PER_MP_LIMB));
195 
196   return N;
197 }
198