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. #define MAX_FORMAT_DIGITS     16
  27. #define DECIMAL_EXPONENT_BIAS 398
  28. #define MAX_DECIMAL_EXPONENT  767
  29.  
  30. #if DECIMAL_CALL_BY_REFERENCE
  31.  
  32. void
  33. bid64_quantize (UINT64 * pres, UINT64 * px,
  34.                 UINT64 *
  35.                 py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  36.                 _EXC_INFO_PARAM) {
  37.   UINT64 x, y;
  38. #else
  39.  
  40. UINT64
  41. bid64_quantize (UINT64 x,
  42.                 UINT64 y _RND_MODE_PARAM _EXC_FLAGS_PARAM
  43.                 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  44. #endif
  45.   UINT128 CT;
  46.   UINT64 sign_x, sign_y, coefficient_x, coefficient_y, remainder_h, C64,
  47.     valid_x;
  48.   UINT64 tmp, carry, res;
  49.   int_float tempx;
  50.   int exponent_x, exponent_y, digits_x, extra_digits, amount, amount2;
  51.   int expon_diff, total_digits, bin_expon_cx;
  52.   unsigned rmode, status;
  53.  
  54. #if DECIMAL_CALL_BY_REFERENCE
  55. #if !DECIMAL_GLOBAL_ROUNDING
  56.   _IDEC_round rnd_mode = *prnd_mode;
  57. #endif
  58.   x = *px;
  59.   y = *py;
  60. #endif
  61.  
  62.   valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x);
  63.   // unpack arguments, check for NaN or Infinity
  64.   if (!unpack_BID64 (&sign_y, &exponent_y, &coefficient_y, y)) {
  65.     // Inf. or NaN or 0
  66. #ifdef SET_STATUS_FLAGS
  67.     if ((x & SNAN_MASK64) == SNAN_MASK64)       // y is sNaN
  68.       __set_status_flags (pfpsf, INVALID_EXCEPTION);
  69. #endif
  70.  
  71.     // x=Inf, y=Inf?
  72.     if (((coefficient_x << 1) == 0xf000000000000000ull)
  73.         && ((coefficient_y << 1) == 0xf000000000000000ull)) {
  74.       res = coefficient_x;
  75.       BID_RETURN (res);
  76.     }
  77.     // Inf or NaN?
  78.     if ((y & 0x7800000000000000ull) == 0x7800000000000000ull) {
  79. #ifdef SET_STATUS_FLAGS
  80.       if (((y & 0x7e00000000000000ull) == 0x7e00000000000000ull)        // sNaN
  81.           || (((y & 0x7c00000000000000ull) == 0x7800000000000000ull) && //Inf
  82.               ((x & 0x7c00000000000000ull) < 0x7800000000000000ull)))
  83.         __set_status_flags (pfpsf, INVALID_EXCEPTION);
  84. #endif
  85.       if ((y & NAN_MASK64) != NAN_MASK64)
  86.         coefficient_y = 0;
  87.       if ((x & NAN_MASK64) != NAN_MASK64) {
  88.         res = 0x7c00000000000000ull | (coefficient_y & QUIET_MASK64);
  89.         if (((y & NAN_MASK64) != NAN_MASK64) && ((x & NAN_MASK64) == 0x7800000000000000ull))
  90.                 res = x;
  91.         BID_RETURN (res);
  92.       }
  93.     }
  94.   }
  95.   // unpack arguments, check for NaN or Infinity
  96.   if (!valid_x) {
  97.     // x is Inf. or NaN or 0
  98.  
  99.     // Inf or NaN?
  100.     if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
  101. #ifdef SET_STATUS_FLAGS
  102.       if (((x & 0x7e00000000000000ull) == 0x7e00000000000000ull)        // sNaN
  103.           || ((x & 0x7c00000000000000ull) == 0x7800000000000000ull))    //Inf
  104.         __set_status_flags (pfpsf, INVALID_EXCEPTION);
  105. #endif
  106.       if ((x & NAN_MASK64) != NAN_MASK64)
  107.         coefficient_x = 0;
  108.       res = 0x7c00000000000000ull | (coefficient_x & QUIET_MASK64);
  109.       BID_RETURN (res);
  110.     }
  111.  
  112.     res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, 0);
  113.     BID_RETURN (res);
  114.   }
  115.   // get number of decimal digits in coefficient_x
  116.   tempx.d = (float) coefficient_x;
  117.   bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
  118.   digits_x = estimate_decimal_digits[bin_expon_cx];
  119.   if (coefficient_x >= power10_table_128[digits_x].w[0])
  120.     digits_x++;
  121.  
  122.   expon_diff = exponent_x - exponent_y;
  123.   total_digits = digits_x + expon_diff;
  124.  
  125.   // check range of scaled coefficient
  126.   if ((UINT32) (total_digits + 1) <= 17) {
  127.     if (expon_diff >= 0) {
  128.       coefficient_x *= power10_table_128[expon_diff].w[0];
  129.       res = very_fast_get_BID64 (sign_x, exponent_y, coefficient_x);
  130.       BID_RETURN (res);
  131.     }
  132.     // must round off -expon_diff digits
  133.     extra_digits = -expon_diff;
  134. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  135. #ifndef IEEE_ROUND_NEAREST
  136.     rmode = rnd_mode;
  137.     if (sign_x && (unsigned) (rmode - 1) < 2)
  138.       rmode = 3 - rmode;
  139. #else
  140.     rmode = 0;
  141. #endif
  142. #else
  143.     rmode = 0;
  144. #endif
  145.     coefficient_x += round_const_table[rmode][extra_digits];
  146.  
  147.     // get P*(2^M[extra_digits])/10^extra_digits
  148.     __mul_64x64_to_128 (CT, coefficient_x,
  149.                         reciprocals10_64[extra_digits]);
  150.  
  151.     // now get P/10^extra_digits: shift C64 right by M[extra_digits]-128
  152.     amount = short_recip_scale[extra_digits];
  153.     C64 = CT.w[1] >> amount;
  154. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  155. #ifndef IEEE_ROUND_NEAREST
  156.     if (rnd_mode == 0)
  157. #endif
  158.       if (C64 & 1) {
  159.         // check whether fractional part of initial_P/10^extra_digits
  160.         // is exactly .5
  161.         // this is the same as fractional part of
  162.         //   (initial_P + 0.5*10^extra_digits)/10^extra_digits is exactly zero
  163.  
  164.         // get remainder
  165.         amount2 = 64 - amount;
  166.         remainder_h = 0;
  167.         remainder_h--;
  168.         remainder_h >>= amount2;
  169.         remainder_h = remainder_h & CT.w[1];
  170.  
  171.         // test whether fractional part is 0
  172.         if (!remainder_h && (CT.w[0] < reciprocals10_64[extra_digits])) {
  173.           C64--;
  174.         }
  175.       }
  176. #endif
  177.  
  178. #ifdef SET_STATUS_FLAGS
  179.     status = INEXACT_EXCEPTION;
  180.     // get remainder
  181.     remainder_h = CT.w[1] << (64 - amount);
  182.     switch (rmode) {
  183.     case ROUNDING_TO_NEAREST:
  184.     case ROUNDING_TIES_AWAY:
  185.       // test whether fractional part is 0
  186.       if ((remainder_h == 0x8000000000000000ull)
  187.           && (CT.w[0] < reciprocals10_64[extra_digits]))
  188.         status = EXACT_STATUS;
  189.       break;
  190.     case ROUNDING_DOWN:
  191.     case ROUNDING_TO_ZERO:
  192.       if (!remainder_h && (CT.w[0] < reciprocals10_64[extra_digits]))
  193.         status = EXACT_STATUS;
  194.       //if(!C64 && rmode==ROUNDING_DOWN) sign_s=sign_y;
  195.       break;
  196.     default:
  197.       // round up
  198.       __add_carry_out (tmp, carry, CT.w[0],
  199.                        reciprocals10_64[extra_digits]);
  200.       if ((remainder_h >> (64 - amount)) + carry >=
  201.           (((UINT64) 1) << amount))
  202.         status = EXACT_STATUS;
  203.       break;
  204.     }
  205.     __set_status_flags (pfpsf, status);
  206. #endif
  207.  
  208.     res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, C64);
  209.     BID_RETURN (res);
  210.   }
  211.  
  212.   if (total_digits < 0) {
  213. #ifdef SET_STATUS_FLAGS
  214.     __set_status_flags (pfpsf, INEXACT_EXCEPTION);
  215. #endif
  216.     C64 = 0;
  217. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  218. #ifndef IEEE_ROUND_NEAREST
  219.     rmode = rnd_mode;
  220.     if (sign_x && (unsigned) (rmode - 1) < 2)
  221.       rmode = 3 - rmode;
  222.     if (rmode == ROUNDING_UP)
  223.       C64 = 1;
  224. #endif
  225. #endif
  226.     res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, C64);
  227.     BID_RETURN (res);
  228.   }
  229.   // else  more than 16 digits in coefficient
  230. #ifdef SET_STATUS_FLAGS
  231.   __set_status_flags (pfpsf, INVALID_EXCEPTION);
  232. #endif
  233.   res = 0x7c00000000000000ull;
  234.   BID_RETURN (res);
  235.  
  236. }
  237.