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.  *  BID64_round_integral_exact
  28.  ****************************************************************************/
  29.  
  30. #if DECIMAL_CALL_BY_REFERENCE
  31. void
  32. bid64_from_int32 (UINT64 * pres,
  33.                   int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  34.   int x = *px;
  35. #else
  36. UINT64
  37. bid64_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  38. #endif
  39.   UINT64 res;
  40.  
  41.   // if integer is negative, put the absolute value
  42.   // in the lowest 32bits of the result
  43.   if ((x & SIGNMASK32) == SIGNMASK32) {
  44.     // negative int32
  45.     x = ~x + 1; // 2's complement of x
  46.     res = (unsigned int) x | 0xb1c0000000000000ull;
  47.     // (exp << 53)) = biased exp. is 0
  48.   } else {      // positive int32
  49.     res = x | 0x31c0000000000000ull;    // (exp << 53)) = biased exp. is 0
  50.   }
  51.   BID_RETURN (res);
  52. }
  53.  
  54. #if DECIMAL_CALL_BY_REFERENCE
  55. void
  56. bid64_from_uint32 (UINT64 * pres, unsigned int *px
  57.                    _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  58.   unsigned int x = *px;
  59. #else
  60. UINT64
  61. bid64_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  62. #endif
  63.   UINT64 res;
  64.  
  65.   res = x | 0x31c0000000000000ull;      // (exp << 53)) = biased exp. is 0
  66.   BID_RETURN (res);
  67. }
  68.  
  69. #if DECIMAL_CALL_BY_REFERENCE
  70. void
  71. bid64_from_int64 (UINT64 * pres, SINT64 * px
  72.                   _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  73.                   _EXC_INFO_PARAM) {
  74.   SINT64 x = *px;
  75. #if !DECIMAL_GLOBAL_ROUNDING
  76.   unsigned int rnd_mode = *prnd_mode;
  77. #endif
  78. #else
  79. UINT64
  80. bid64_from_int64 (SINT64 x
  81.                   _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  82.                   _EXC_INFO_PARAM) {
  83. #endif
  84.  
  85.   UINT64 res;
  86.   UINT64 x_sign, C;
  87.   unsigned int q, ind;
  88.   int incr_exp = 0;
  89.   int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
  90.   int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
  91.  
  92.   x_sign = x & 0x8000000000000000ull;
  93.   // if the integer is negative, use the absolute value
  94.   if (x_sign)
  95.     C = ~((UINT64) x) + 1;
  96.   else
  97.     C = x;
  98.   if (C <= BID64_SIG_MAX) {     // |C| <= 10^16-1 and the result is exact
  99.     if (C < 0x0020000000000000ull) {    // C < 2^53
  100.       res = x_sign | 0x31c0000000000000ull | C;
  101.     } else {    // C >= 2^53
  102.       res =
  103.         x_sign | 0x6c70000000000000ull | (C & 0x0007ffffffffffffull);
  104.     }
  105.   } else {      // |C| >= 10^16 and the result may be inexact
  106.     // the smallest |C| is 10^16 which has 17 decimal digits
  107.     // the largest |C| is 0x8000000000000000 = 9223372036854775808 w/ 19 digits
  108.     if (C < 0x16345785d8a0000ull) {     // x < 10^17
  109.       q = 17;
  110.       ind = 1;  // number of digits to remove for q = 17
  111.     } else if (C < 0xde0b6b3a7640000ull) {      // C < 10^18
  112.       q = 18;
  113.       ind = 2;  // number of digits to remove for q = 18
  114.     } else {    // C < 10^19
  115.       q = 19;
  116.       ind = 3;  // number of digits to remove for q = 19
  117.     }
  118.     // overflow and underflow are not possible
  119.     // Note: performace can be improved by inlining this call
  120.     round64_2_18 (      // will work for 19 digits too if C fits in 64 bits
  121.                    q, ind, C, &res, &incr_exp,
  122.                    &is_midpoint_lt_even, &is_midpoint_gt_even,
  123.                    &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  124.     if (incr_exp)
  125.       ind++;
  126.     // set the inexact flag
  127.     if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
  128.         is_midpoint_lt_even || is_midpoint_gt_even)
  129.       *pfpsf |= INEXACT_EXCEPTION;
  130.     // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
  131.     if (rnd_mode != ROUNDING_TO_NEAREST) {
  132.       if ((!x_sign
  133.            && ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint)
  134.                ||
  135.                ((rnd_mode == ROUNDING_TIES_AWAY
  136.                  || rnd_mode == ROUNDING_UP) && is_midpoint_gt_even)))
  137.           || (x_sign
  138.               && ((rnd_mode == ROUNDING_DOWN && is_inexact_lt_midpoint)
  139.                   ||
  140.                   ((rnd_mode == ROUNDING_TIES_AWAY
  141.                     || rnd_mode == ROUNDING_DOWN)
  142.                    && is_midpoint_gt_even)))) {
  143.         res = res + 1;
  144.         if (res == 0x002386f26fc10000ull) {     // res = 10^16 => rounding overflow
  145.           res = 0x00038d7ea4c68000ull;  // 10^15
  146.           ind = ind + 1;
  147.         }
  148.       } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
  149.                  ((x_sign && (rnd_mode == ROUNDING_UP ||
  150.                               rnd_mode == ROUNDING_TO_ZERO)) ||
  151.                   (!x_sign && (rnd_mode == ROUNDING_DOWN ||
  152.                                rnd_mode == ROUNDING_TO_ZERO)))) {
  153.         res = res - 1;
  154.         // check if we crossed into the lower decade
  155.         if (res == 0x00038d7ea4c67fffull) {     // 10^15 - 1
  156.           res = 0x002386f26fc0ffffull;  // 10^16 - 1
  157.           ind = ind - 1;
  158.         }
  159.       } else {
  160.         ;       // exact, the result is already correct
  161.       }
  162.     }
  163.     if (res < 0x0020000000000000ull) {  // res < 2^53
  164.       res = x_sign | (((UINT64) ind + 398) << 53) | res;
  165.     } else {    // res >= 2^53
  166.       res =
  167.         x_sign | 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
  168.         (res & 0x0007ffffffffffffull);
  169.     }
  170.   }
  171.   BID_RETURN (res);
  172. }
  173.  
  174. #if DECIMAL_CALL_BY_REFERENCE
  175. void
  176. bid64_from_uint64 (UINT64 * pres, UINT64 * px
  177.                    _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  178.                    _EXC_INFO_PARAM) {
  179.   UINT64 x = *px;
  180. #if !DECIMAL_GLOBAL_ROUNDING
  181.   unsigned int rnd_mode = *prnd_mode;
  182. #endif
  183. #else
  184. UINT64
  185. bid64_from_uint64 (UINT64 x
  186.                    _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  187.                    _EXC_INFO_PARAM) {
  188. #endif
  189.  
  190.   UINT64 res;
  191.   UINT128 x128, res128;
  192.   unsigned int q, ind;
  193.   int incr_exp = 0;
  194.   int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
  195.   int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
  196.  
  197.   if (x <= BID64_SIG_MAX) {     // x <= 10^16-1 and the result is exact
  198.     if (x < 0x0020000000000000ull) {    // x < 2^53
  199.       res = 0x31c0000000000000ull | x;
  200.     } else {    // x >= 2^53
  201.       res = 0x6c70000000000000ull | (x & 0x0007ffffffffffffull);
  202.     }
  203.   } else {      // x >= 10^16 and the result may be inexact
  204.     // the smallest x is 10^16 which has 17 decimal digits
  205.     // the largest x is 0xffffffffffffffff = 18446744073709551615 w/ 20 digits
  206.     if (x < 0x16345785d8a0000ull) {     // x < 10^17
  207.       q = 17;
  208.       ind = 1;  // number of digits to remove for q = 17
  209.     } else if (x < 0xde0b6b3a7640000ull) {      // x < 10^18
  210.       q = 18;
  211.       ind = 2;  // number of digits to remove for q = 18
  212.     } else if (x < 0x8ac7230489e80000ull) {     // x < 10^19
  213.       q = 19;
  214.       ind = 3;  // number of digits to remove for q = 19
  215.     } else {    // x < 10^20
  216.       q = 20;
  217.       ind = 4;  // number of digits to remove for q = 20
  218.     }
  219.     // overflow and underflow are not possible
  220.     // Note: performace can be improved by inlining this call
  221.     if (q <= 19) {
  222.       round64_2_18 (    // will work for 20 digits too if x fits in 64 bits
  223.                      q, ind, x, &res, &incr_exp,
  224.                      &is_midpoint_lt_even, &is_midpoint_gt_even,
  225.                      &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  226.     } else {    // q = 20
  227.       x128.w[1] = 0x0;
  228.       x128.w[0] = x;
  229.       round128_19_38 (q, ind, x128, &res128, &incr_exp,
  230.                       &is_midpoint_lt_even, &is_midpoint_gt_even,
  231.                       &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  232.       res = res128.w[0];        // res.w[1] is 0
  233.     }
  234.     if (incr_exp)
  235.       ind++;
  236.     // set the inexact flag
  237.     if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
  238.         is_midpoint_lt_even || is_midpoint_gt_even)
  239.       *pfpsf |= INEXACT_EXCEPTION;
  240.     // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
  241.     if (rnd_mode != ROUNDING_TO_NEAREST) {
  242.       if ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint) ||
  243.           ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_UP)
  244.            && is_midpoint_gt_even)) {
  245.         res = res + 1;
  246.         if (res == 0x002386f26fc10000ull) {     // res = 10^16 => rounding overflow
  247.           res = 0x00038d7ea4c68000ull;  // 10^15
  248.           ind = ind + 1;
  249.         }
  250.       } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
  251.                  (rnd_mode == ROUNDING_DOWN ||
  252.                   rnd_mode == ROUNDING_TO_ZERO)) {
  253.         res = res - 1;
  254.         // check if we crossed into the lower decade
  255.         if (res == 0x00038d7ea4c67fffull) {     // 10^15 - 1
  256.           res = 0x002386f26fc0ffffull;  // 10^16 - 1
  257.           ind = ind - 1;
  258.         }
  259.       } else {
  260.         ;       // exact, the result is already correct
  261.       }
  262.     }
  263.     if (res < 0x0020000000000000ull) {  // res < 2^53
  264.       res = (((UINT64) ind + 398) << 53) | res;
  265.     } else {    // res >= 2^53
  266.       res = 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
  267.         (res & 0x0007ffffffffffffull);
  268.     }
  269.   }
  270.   BID_RETURN (res);
  271. }
  272.  
  273. #if DECIMAL_CALL_BY_REFERENCE
  274. void
  275. bid128_from_int32 (UINT128 * pres,
  276.                    int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  277.   int x = *px;
  278. #else
  279. UINT128
  280. bid128_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  281. #endif
  282.   UINT128 res;
  283.  
  284.   // if integer is negative, use the absolute value
  285.   if ((x & SIGNMASK32) == SIGNMASK32) {
  286.     res.w[HIGH_128W] = 0xb040000000000000ull;
  287.     res.w[LOW_128W] = ~((unsigned int) x) + 1;  // 2's complement of x
  288.   } else {
  289.     res.w[HIGH_128W] = 0x3040000000000000ull;
  290.     res.w[LOW_128W] = (unsigned int) x;
  291.   }
  292.   BID_RETURN (res);
  293. }
  294.  
  295. #if DECIMAL_CALL_BY_REFERENCE
  296. void
  297. bid128_from_uint32 (UINT128 * pres, unsigned int *px
  298.                     _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  299.   unsigned int x = *px;
  300. #else
  301. UINT128
  302. bid128_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  303. #endif
  304.   UINT128 res;
  305.  
  306.   res.w[HIGH_128W] = 0x3040000000000000ull;
  307.   res.w[LOW_128W] = x;
  308.   BID_RETURN (res);
  309. }
  310.  
  311. #if DECIMAL_CALL_BY_REFERENCE
  312. void
  313. bid128_from_int64 (UINT128 * pres, SINT64 * px
  314.                    _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  315.   SINT64 x = *px;
  316. #else
  317. UINT128
  318. bid128_from_int64 (SINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  319. #endif
  320.  
  321.   UINT128 res;
  322.  
  323.   // if integer is negative, use the absolute value
  324.   if ((x & SIGNMASK64) == SIGNMASK64) {
  325.     res.w[HIGH_128W] = 0xb040000000000000ull;
  326.     res.w[LOW_128W] = ~x + 1;   // 2's complement of x
  327.   } else {
  328.     res.w[HIGH_128W] = 0x3040000000000000ull;
  329.     res.w[LOW_128W] = x;
  330.   }
  331.   BID_RETURN (res);
  332. }
  333.  
  334. #if DECIMAL_CALL_BY_REFERENCE
  335. void
  336. bid128_from_uint64 (UINT128 * pres, UINT64 * px
  337.                     _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  338.   UINT64 x = *px;
  339. #else
  340. UINT128
  341. bid128_from_uint64 (UINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  342. #endif
  343.  
  344.   UINT128 res;
  345.  
  346.   res.w[HIGH_128W] = 0x3040000000000000ull;
  347.   res.w[LOW_128W] = x;
  348.   BID_RETURN (res);
  349. }
  350.