(root)/
gcc-13.2.0/
libgcc/
config/
libbid/
bid32_to_bid64.c
       1  /* Copyright (C) 2007-2023 Free Software Foundation, Inc.
       2  
       3  This file is part of GCC.
       4  
       5  GCC is free software; you can redistribute it and/or modify it under
       6  the terms of the GNU General Public License as published by the Free
       7  Software Foundation; either version 3, or (at your option) any later
       8  version.
       9  
      10  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13  for more details.
      14  
      15  Under Section 7 of GPL version 3, you are granted additional
      16  permissions described in the GCC Runtime Library Exception, version
      17  3.1, as published by the Free Software Foundation.
      18  
      19  You should have received a copy of the GNU General Public License and
      20  a copy of the GCC Runtime Library Exception along with this program;
      21  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22  <http://www.gnu.org/licenses/>.  */
      23  
      24  #include "bid_internal.h"
      25  
      26  /*
      27   * Takes a BID32 as input and converts it to a BID64 and returns it.
      28   */
      29  TYPE0_FUNCTION_ARGTYPE1_NORND (UINT64, bid32_to_bid64, UINT32, x)
      30  
      31       UINT64 res;
      32       UINT32 sign_x;
      33       int exponent_x;
      34       UINT32 coefficient_x;
      35  
      36  if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) {
      37      // Inf, NaN, 0
      38  if (((x) & 0x78000000) == 0x78000000) {
      39    if (((x) & 0x7e000000) == 0x7e000000) {	// sNaN
      40  #ifdef SET_STATUS_FLAGS
      41      __set_status_flags (pfpsf, INVALID_EXCEPTION);
      42  #endif
      43    }
      44    res = (coefficient_x & 0x000fffff);
      45    res *= 1000000000;
      46    res |= ((((UINT64) coefficient_x) << 32) & 0xfc00000000000000ull);
      47  
      48    BID_RETURN (res);
      49  }
      50  }
      51  
      52  res =
      53  very_fast_get_BID64_small_mantissa (((UINT64) sign_x) << 32,
      54  				    exponent_x +
      55  				    DECIMAL_EXPONENT_BIAS -
      56  				    DECIMAL_EXPONENT_BIAS_32,
      57  				    (UINT64) coefficient_x);
      58  BID_RETURN (res);
      59  }	// convert_bid32_to_bid64
      60  
      61  
      62  /*
      63   * Takes a BID64 as input and converts it to a BID32 and returns it.
      64   */
      65  #if DECIMAL_CALL_BY_REFERENCE
      66  
      67  void
      68  bid64_to_bid32 (UINT32 * pres,
      69  		UINT64 *
      70  		px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
      71  		_EXC_INFO_PARAM) {
      72    UINT64 x;
      73  #else
      74  
      75  UINT32
      76  bid64_to_bid32 (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
      77  		_EXC_MASKS_PARAM _EXC_INFO_PARAM) {
      78  #endif
      79    UINT128 Q;
      80    UINT64 sign_x, coefficient_x, remainder_h, carry, Stemp;
      81    UINT32 res;
      82    int_float tempx;
      83    int exponent_x, bin_expon_cx, extra_digits, rmode = 0, amount;
      84    unsigned status = 0;
      85  
      86  #if DECIMAL_CALL_BY_REFERENCE
      87  #if !DECIMAL_GLOBAL_ROUNDING
      88    _IDEC_round rnd_mode = *prnd_mode;
      89  #endif
      90    x = *px;
      91  #endif
      92  
      93    // unpack arguments, check for NaN or Infinity, 0
      94    if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) {
      95      if (((x) & 0x7800000000000000ull) == 0x7800000000000000ull) {
      96        res = (coefficient_x & 0x0003ffffffffffffull);
      97        res /= 1000000000ull;
      98        res |= ((coefficient_x >> 32) & 0xfc000000);
      99  #ifdef SET_STATUS_FLAGS
     100        if ((x & SNAN_MASK64) == SNAN_MASK64)	// sNaN
     101  	__set_status_flags (pfpsf, INVALID_EXCEPTION);
     102  #endif
     103        BID_RETURN (res);
     104      }
     105      exponent_x =
     106        exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32;
     107      if (exponent_x < 0)
     108        exponent_x = 0;
     109      if (exponent_x > DECIMAL_MAX_EXPON_32)
     110        exponent_x = DECIMAL_MAX_EXPON_32;
     111      res = (sign_x >> 32) | (exponent_x << 23);
     112      BID_RETURN (res);
     113    }
     114  
     115    exponent_x =
     116      exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32;
     117  
     118    // check number of digits
     119    if (coefficient_x >= 10000000) {
     120      tempx.d = (float) coefficient_x;
     121      bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
     122      extra_digits = estimate_decimal_digits[bin_expon_cx] - 7;
     123      // add test for range
     124      if (coefficient_x >= power10_index_binexp[bin_expon_cx])
     125        extra_digits++;
     126  
     127  #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
     128  #ifndef IEEE_ROUND_NEAREST
     129      rmode = rnd_mode;
     130      if (sign_x && (unsigned) (rmode - 1) < 2)
     131        rmode = 3 - rmode;
     132  #else
     133      rmode = 0;
     134  #endif
     135  #else
     136      rmode = 0;
     137  #endif
     138  
     139      exponent_x += extra_digits;
     140      if ((exponent_x < 0) && (exponent_x + MAX_FORMAT_DIGITS_32 >= 0)) {
     141        status = UNDERFLOW_EXCEPTION;
     142        if (exponent_x == -1)
     143  	if (coefficient_x + round_const_table[rmode][extra_digits] >=
     144  	    power10_table_128[extra_digits + 7].w[0])
     145  	  status = 0;
     146        extra_digits -= exponent_x;
     147        exponent_x = 0;
     148      }
     149      coefficient_x += round_const_table[rmode][extra_digits];
     150      __mul_64x64_to_128 (Q, coefficient_x,
     151  			reciprocals10_64[extra_digits]);
     152  
     153      // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
     154      amount = short_recip_scale[extra_digits];
     155  
     156      coefficient_x = Q.w[1] >> amount;
     157  
     158  #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
     159  #ifndef IEEE_ROUND_NEAREST
     160      if (rmode == 0)	//ROUNDING_TO_NEAREST
     161  #endif
     162        if (coefficient_x & 1) {
     163  	// check whether fractional part of initial_P/10^extra_digits 
     164  	// is exactly .5
     165  
     166  	// get remainder
     167  	remainder_h = Q.w[1] << (64 - amount);
     168  
     169  	if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
     170  	  coefficient_x--;
     171        }
     172  #endif
     173  
     174  #ifdef SET_STATUS_FLAGS
     175  
     176      {
     177        status |= INEXACT_EXCEPTION;
     178        // get remainder
     179        remainder_h = Q.w[1] << (64 - amount);
     180  
     181        switch (rmode) {
     182        case ROUNDING_TO_NEAREST:
     183        case ROUNDING_TIES_AWAY:
     184  	// test whether fractional part is 0
     185  	if (remainder_h == 0x8000000000000000ull
     186  	    && (Q.w[0] < reciprocals10_64[extra_digits]))
     187  	  status = EXACT_STATUS;
     188  	break;
     189        case ROUNDING_DOWN:
     190        case ROUNDING_TO_ZERO:
     191  	if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
     192  	  status = EXACT_STATUS;
     193  	break;
     194        default:
     195  	// round up
     196  	__add_carry_out (Stemp, carry, Q.w[0],
     197  			 reciprocals10_64[extra_digits]);
     198  	if ((remainder_h >> (64 - amount)) + carry >=
     199  	    (((UINT64) 1) << amount))
     200  	  status = EXACT_STATUS;
     201        }
     202  
     203        if (status != EXACT_STATUS)
     204  	__set_status_flags (pfpsf, status);
     205      }
     206  
     207  #endif
     208  
     209    }
     210  
     211    res =
     212      get_BID32 ((UINT32) (sign_x >> 32),
     213  	       exponent_x, coefficient_x, rnd_mode, pfpsf);
     214    BID_RETURN (res);
     215  
     216  }