Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* Copyright (C) 2007-2015 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. }
  217.