(root)/
glibc-2.38/
sysdeps/
ieee754/
ldbl-128ibm/
ldbl2mpn.c
       1  /* Copyright (C) 1995-2023 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
      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 difference 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  }