1 /* Copyright (C) 2007 Free Software Foundation, Inc.
3 This file is part of GCC.
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 2, or (at your option) any later
10 In addition to the permissions in the GNU General Public License, the
11 Free Software Foundation gives you unlimited permission to link the
12 compiled version of this file into combinations with other programs,
13 and to distribute those combinations without any restriction coming
14 from the use of this file. (The General Public License restrictions
15 do apply in other respects; for example, they cover modification of
16 the file, and distribution when not linked into a combine
19 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING. If not, write to the Free
26 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29 /*****************************************************************************
31 *****************************************************************************
33 * Algorithm description:
35 * if(exponent_x < exponent_y)
36 * scale coefficient_y so exponents are aligned
37 * perform coefficient divide (64-bit integer divide), unless
38 * coefficient_y is longer than 64 bits (clearly larger
40 * else // exponent_x > exponent_y
41 * use a loop to scale coefficient_x to 18_digits, divide by
42 * coefficient_y (64-bit integer divide), calculate remainder
43 * as new_coefficient_x and repeat until final remainder is obtained
44 * (when new_exponent_x < exponent_y)
46 ****************************************************************************/
48 #include "bid_internal.h"
50 #define MAX_FORMAT_DIGITS 16
51 #define DECIMAL_EXPONENT_BIAS 398
52 #define MASK_BINARY_EXPONENT 0x7ff0000000000000ull
53 #define BINARY_EXPONENT_BIAS 0x3ff
54 #define UPPER_EXPON_LIMIT 51
56 #if DECIMAL_CALL_BY_REFERENCE
59 bid64_rem (UINT64
* pres
, UINT64
* px
,
61 py _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM
) {
67 UINT64 y _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM
) {
70 UINT64 sign_x
, sign_y
, coefficient_x
, coefficient_y
, res
;
71 UINT64 Q
, R
, R2
, T
, valid_y
, valid_x
;
73 int exponent_x
, exponent_y
, bin_expon
, e_scale
;
74 int digits_x
, diff_expon
;
76 #if DECIMAL_CALL_BY_REFERENCE
81 valid_y
= unpack_BID64 (&sign_y
, &exponent_y
, &coefficient_y
, y
);
82 valid_x
= unpack_BID64 (&sign_x
, &exponent_x
, &coefficient_x
, x
);
84 // unpack arguments, check for NaN or Infinity
86 // x is Inf. or NaN or 0
87 #ifdef SET_STATUS_FLAGS
88 if ((y
& SNAN_MASK64
) == SNAN_MASK64
) // y is sNaN
89 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
93 if ((x
& 0x7c00000000000000ull
) == 0x7c00000000000000ull
) {
94 #ifdef SET_STATUS_FLAGS
95 if (((x
& SNAN_MASK64
) == SNAN_MASK64
))
96 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
98 res
= coefficient_x
& QUIET_MASK64
;;
102 if ((x
& 0x7800000000000000ull
) == 0x7800000000000000ull
) {
103 if (((y
& NAN_MASK64
) != NAN_MASK64
)) {
104 #ifdef SET_STATUS_FLAGS
105 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
108 res
= 0x7c00000000000000ull
;
113 // return x if y != 0
114 if (((y
& 0x7800000000000000ull
) < 0x7800000000000000ull
) &&
116 if ((y
& 0x6000000000000000ull
) == 0x6000000000000000ull
)
117 exponent_y
= (y
>> 51) & 0x3ff;
119 exponent_y
= (y
>> 53) & 0x3ff;
121 if (exponent_y
< exponent_x
)
122 exponent_x
= exponent_y
;
136 if ((y
& 0x7c00000000000000ull
) == 0x7c00000000000000ull
) {
137 #ifdef SET_STATUS_FLAGS
138 if (((y
& SNAN_MASK64
) == SNAN_MASK64
))
139 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
141 res
= coefficient_y
& QUIET_MASK64
;;
145 if ((y
& 0x7800000000000000ull
) == 0x7800000000000000ull
) {
146 res
= very_fast_get_BID64 (sign_x
, exponent_x
, coefficient_x
);
149 // y is 0, return NaN
151 #ifdef SET_STATUS_FLAGS
152 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
154 res
= 0x7c00000000000000ull
;
160 diff_expon
= exponent_x
- exponent_y
;
161 if (diff_expon
<= 0) {
162 diff_expon
= -diff_expon
;
164 if (diff_expon
> 16) {
165 // |x|<|y| in this case
169 // set exponent of y to exponent_x, scale coefficient_y
170 T
= power10_table_128
[diff_expon
].w
[0];
171 __mul_64x64_to_128 (CY
, coefficient_y
, T
);
173 if (CY
.w
[1] || CY
.w
[0] > (coefficient_x
<< 1)) {
178 Q
= coefficient_x
/ CY
.w
[0];
179 R
= coefficient_x
- Q
* CY
.w
[0];
182 if (R2
> CY
.w
[0] || (R2
== CY
.w
[0] && (Q
& 1))) {
184 sign_x
^= 0x8000000000000000ull
;
187 res
= very_fast_get_BID64 (sign_x
, exponent_x
, R
);
192 while (diff_expon
> 0) {
193 // get number of digits in coeff_x
194 tempx
.d
= (float) coefficient_x
;
195 bin_expon
= ((tempx
.i
>> 23) & 0xff) - 0x7f;
196 digits_x
= estimate_decimal_digits
[bin_expon
];
197 // will not use this test, dividend will have 18 or 19 digits
198 //if(coefficient_x >= power10_table_128[digits_x].w[0])
201 e_scale
= 18 - digits_x
;
202 if (diff_expon
>= e_scale
) {
203 diff_expon
-= e_scale
;
205 e_scale
= diff_expon
;
209 // scale dividend to 18 or 19 digits
210 coefficient_x
*= power10_table_128
[e_scale
].w
[0];
213 Q
= coefficient_x
/ coefficient_y
;
215 coefficient_x
-= Q
* coefficient_y
;
217 // check for remainder == 0
218 if (!coefficient_x
) {
219 res
= very_fast_get_BID64_small_mantissa (sign_x
, exponent_y
, 0);
224 R2
= coefficient_x
+ coefficient_x
;
225 if (R2
> coefficient_y
|| (R2
== coefficient_y
&& (Q
& 1))) {
226 coefficient_x
= coefficient_y
- coefficient_x
;
227 sign_x
^= 0x8000000000000000ull
;
230 res
= very_fast_get_BID64 (sign_x
, exponent_y
, coefficient_x
);