1 /* Copyright (C) 2007-2014 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 3, or (at your option) any later
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
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.
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/>. */
24 /*****************************************************************************
26 *****************************************************************************
28 * Algorithm description:
30 * if multiplication is guranteed exact (short coefficients)
31 * call the unpacked arg. equivalent of bid64_add(x*y, z)
33 * get full coefficient_x*coefficient_y product
34 * call subroutine to perform addition of 64-bit argument
37 ****************************************************************************/
39 #include "bid_inline_add.h"
41 #if DECIMAL_CALL_BY_REFERENCE
42 extern void bid64_mul (UINT64
* pres
, UINT64
* px
,
44 py _RND_MODE_PARAM _EXC_FLAGS_PARAM
45 _EXC_MASKS_PARAM _EXC_INFO_PARAM
);
48 extern UINT64
bid64_mul (UINT64 x
,
49 UINT64 y _RND_MODE_PARAM
50 _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
54 #if DECIMAL_CALL_BY_REFERENCE
57 bid64_fma (UINT64
* pres
, UINT64
* px
, UINT64
* py
,
59 pz _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
65 bid64_fma (UINT64 x
, UINT64 y
,
66 UINT64 z _RND_MODE_PARAM _EXC_FLAGS_PARAM
67 _EXC_MASKS_PARAM _EXC_INFO_PARAM
) {
69 UINT128 P
, PU
, CT
, CZ
;
70 UINT64 sign_x
, sign_y
, coefficient_x
, coefficient_y
, sign_z
,
72 UINT64 C64
, remainder_y
, res
;
73 UINT64 CYh
, CY0L
, T
, valid_x
, valid_y
, valid_z
;
74 int_double tempx
, tempy
;
75 int extra_digits
, exponent_x
, exponent_y
, bin_expon_cx
, bin_expon_cy
,
76 bin_expon_product
, rmode
;
77 int digits_p
, bp
, final_exponent
, exponent_z
, digits_z
, ez
, ey
,
80 #if DECIMAL_CALL_BY_REFERENCE
81 #if !DECIMAL_GLOBAL_ROUNDING
82 _IDEC_round rnd_mode
= *prnd_mode
;
89 valid_x
= unpack_BID64 (&sign_x
, &exponent_x
, &coefficient_x
, x
);
90 valid_y
= unpack_BID64 (&sign_y
, &exponent_y
, &coefficient_y
, y
);
91 valid_z
= unpack_BID64 (&sign_z
, &exponent_z
, &coefficient_z
, z
);
93 // unpack arguments, check for NaN, Infinity, or 0
94 if (!valid_x
|| !valid_y
|| !valid_z
) {
96 if ((y
& MASK_NAN
) == MASK_NAN
) { // y is NAN
97 // if x = {0, f, inf, NaN}, y = NaN, z = {0, f, inf, NaN} then res = Q (y)
98 // check first for non-canonical NaN payload
99 y
= y
& 0xfe03ffffffffffffull
; // clear G6-G12
100 if ((y
& 0x0003ffffffffffffull
) > 999999999999999ull) {
101 y
= y
& 0xfe00000000000000ull
; // clear G6-G12 and the payload bits
103 if ((y
& MASK_SNAN
) == MASK_SNAN
) { // y is SNAN
105 *pfpsf
|= INVALID_EXCEPTION
;
107 res
= y
& 0xfdffffffffffffffull
;
108 } else { // y is QNaN
111 // if z = SNaN or x = SNaN signal invalid exception
112 if ((z
& MASK_SNAN
) == MASK_SNAN
113 || (x
& MASK_SNAN
) == MASK_SNAN
) {
115 *pfpsf
|= INVALID_EXCEPTION
;
119 } else if ((z
& MASK_NAN
) == MASK_NAN
) { // z is NAN
120 // if x = {0, f, inf, NaN}, y = {0, f, inf}, z = NaN then res = Q (z)
121 // check first for non-canonical NaN payload
122 z
= z
& 0xfe03ffffffffffffull
; // clear G6-G12
123 if ((z
& 0x0003ffffffffffffull
) > 999999999999999ull) {
124 z
= z
& 0xfe00000000000000ull
; // clear G6-G12 and the payload bits
126 if ((z
& MASK_SNAN
) == MASK_SNAN
) { // z is SNAN
128 *pfpsf
|= INVALID_EXCEPTION
;
130 res
= z
& 0xfdffffffffffffffull
;
131 } else { // z is QNaN
134 // if x = SNaN signal invalid exception
135 if ((x
& MASK_SNAN
) == MASK_SNAN
) {
137 *pfpsf
|= INVALID_EXCEPTION
;
141 } else if ((x
& MASK_NAN
) == MASK_NAN
) { // x is NAN
142 // if x = NaN, y = {0, f, inf}, z = {0, f, inf} then res = Q (x)
143 // check first for non-canonical NaN payload
144 x
= x
& 0xfe03ffffffffffffull
; // clear G6-G12
145 if ((x
& 0x0003ffffffffffffull
) > 999999999999999ull) {
146 x
= x
& 0xfe00000000000000ull
; // clear G6-G12 and the payload bits
148 if ((x
& MASK_SNAN
) == MASK_SNAN
) { // x is SNAN
150 *pfpsf
|= INVALID_EXCEPTION
;
152 res
= x
& 0xfdffffffffffffffull
;
153 } else { // x is QNaN
155 res
= x
; // clear out G[6]-G[16]
164 if ((x
& 0x7800000000000000ull
) == 0x7800000000000000ull
) {
166 if (!coefficient_y
) {
168 #ifdef SET_STATUS_FLAGS
169 if ((z
& 0x7e00000000000000ull
) != 0x7c00000000000000ull
)
170 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
172 BID_RETURN (0x7c00000000000000ull
);
174 // test if z is Inf of oposite sign
175 if (((z
& 0x7c00000000000000ull
) == 0x7800000000000000ull
)
176 && (((x
^ y
) ^ z
) & 0x8000000000000000ull
)) {
178 #ifdef SET_STATUS_FLAGS
179 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
181 BID_RETURN (0x7c00000000000000ull
);
183 // otherwise return +/-Inf
184 BID_RETURN (((x
^ y
) & 0x8000000000000000ull
) |
185 0x7800000000000000ull
);
188 if (((y
& 0x7800000000000000ull
) != 0x7800000000000000ull
)
189 && ((z
& 0x7800000000000000ull
) != 0x7800000000000000ull
)) {
192 exponent_y
= exponent_x
- DECIMAL_EXPONENT_BIAS
+ exponent_y
;
194 sign_z
= z
& 0x8000000000000000ull
;
196 if (exponent_y
>= exponent_z
)
199 add_zero64 (exponent_y
, sign_z
, exponent_z
, coefficient_z
,
209 if ((y
& 0x7800000000000000ull
) == 0x7800000000000000ull
) {
211 if (!coefficient_x
) {
213 #ifdef SET_STATUS_FLAGS
214 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
216 BID_RETURN (0x7c00000000000000ull
);
218 // test if z is Inf of oposite sign
219 if (((z
& 0x7c00000000000000ull
) == 0x7800000000000000ull
)
220 && (((x
^ y
) ^ z
) & 0x8000000000000000ull
)) {
221 #ifdef SET_STATUS_FLAGS
222 __set_status_flags (pfpsf
, INVALID_EXCEPTION
);
225 BID_RETURN (0x7c00000000000000ull
);
227 // otherwise return +/-Inf
228 BID_RETURN (((x
^ y
) & 0x8000000000000000ull
) |
229 0x7800000000000000ull
);
232 if (((z
& 0x7800000000000000ull
) != 0x7800000000000000ull
)) {
235 exponent_y
+= exponent_x
- DECIMAL_EXPONENT_BIAS
;
237 sign_z
= z
& 0x8000000000000000ull
;
239 if (exponent_y
>= exponent_z
)
242 add_zero64 (exponent_y
, sign_z
, exponent_z
, coefficient_z
,
252 // test if y is NaN/Inf
253 if ((z
& 0x7800000000000000ull
) == 0x7800000000000000ull
) {
254 BID_RETURN (coefficient_z
& QUIET_MASK64
);
256 // z is 0, return x*y
257 if ((!coefficient_x
) || (!coefficient_y
)) {
259 exponent_x
+= exponent_y
- DECIMAL_EXPONENT_BIAS
;
260 if (exponent_x
> DECIMAL_MAX_EXPON_64
)
261 exponent_x
= DECIMAL_MAX_EXPON_64
;
262 else if (exponent_x
< 0)
264 if (exponent_x
<= exponent_z
)
265 res
= ((UINT64
) exponent_x
) << 53;
267 res
= ((UINT64
) exponent_z
) << 53;
268 if ((sign_x
^ sign_y
) == sign_z
)
270 #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
271 #ifndef IEEE_ROUND_NEAREST
272 else if (rnd_mode
== ROUNDING_DOWN
)
273 res
|= 0x8000000000000000ull
;
281 /* get binary coefficients of x and y */
283 //--- get number of bits in the coefficients of x and y ---
284 // version 2 (original)
285 tempx
.d
= (double) coefficient_x
;
286 bin_expon_cx
= ((tempx
.i
& MASK_BINARY_EXPONENT
) >> 52);
288 tempy
.d
= (double) coefficient_y
;
289 bin_expon_cy
= ((tempy
.i
& MASK_BINARY_EXPONENT
) >> 52);
291 // magnitude estimate for coefficient_x*coefficient_y is
292 // 2^(unbiased_bin_expon_cx + unbiased_bin_expon_cx)
293 bin_expon_product
= bin_expon_cx
+ bin_expon_cy
;
295 // check if coefficient_x*coefficient_y<2^(10*k+3)
296 // equivalent to unbiased_bin_expon_cx + unbiased_bin_expon_cx < 10*k+1
297 if (bin_expon_product
< UPPER_EXPON_LIMIT
+ 2 * BINARY_EXPONENT_BIAS
) {
299 C64
= coefficient_x
* coefficient_y
;
300 final_exponent
= exponent_x
+ exponent_y
- DECIMAL_EXPONENT_BIAS
;
301 if ((final_exponent
> 0) || (!coefficient_z
)) {
303 get_add64 (sign_x
^ sign_y
,
304 final_exponent
, C64
, sign_z
, exponent_z
, coefficient_z
, rnd_mode
, pfpsf
);
312 if (!coefficient_z
) {
313 #if DECIMAL_CALL_BY_REFERENCE
315 py _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
320 y _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
325 // get 128-bit product: coefficient_x*coefficient_y
326 __mul_64x64_to_128 (P
, coefficient_x
, coefficient_y
);
328 // tighten binary range of P: leading bit is 2^bp
329 // unbiased_bin_expon_product <= bp <= unbiased_bin_expon_product+1
330 bin_expon_product
-= 2 * BINARY_EXPONENT_BIAS
;
331 __tight_bin_range_128 (bp
, P
, bin_expon_product
);
333 // get number of decimal digits in the product
334 digits_p
= estimate_decimal_digits
[bp
];
335 if (!(__unsigned_compare_gt_128 (power10_table_128
[digits_p
], P
)))
336 digits_p
++; // if power10_table_128[digits_p] <= P
338 // determine number of decimal digits to be rounded out
339 extra_digits
= digits_p
- MAX_FORMAT_DIGITS
;
341 exponent_x
+ exponent_y
+ extra_digits
- DECIMAL_EXPONENT_BIAS
;
344 if (((unsigned) final_exponent
) >= 3 * 256) {
345 if (final_exponent
< 0) {
346 //--- get number of bits in the coefficients of z ---
347 tempx
.d
= (double) coefficient_z
;
348 bin_expon_cx
= ((tempx
.i
& MASK_BINARY_EXPONENT
) >> 52) - 0x3ff;
349 // get number of decimal digits in the coeff_x
350 digits_z
= estimate_decimal_digits
[bin_expon_cx
];
351 if (coefficient_z
>= power10_table_128
[digits_z
].w
[0])
354 if ((final_exponent
+ 16 < 0)
355 || (exponent_z
+ digits_z
> 33 + final_exponent
)) {
357 BID_normalize (sign_z
, exponent_z
, coefficient_z
,
358 sign_x
^ sign_y
, 1, rnd_mode
, pfpsf
);
362 ez
= exponent_z
+ digits_z
- 16;
365 scale_z
= exponent_z
- ez
;
366 coefficient_z
*= power10_table_128
[scale_z
].w
[0];
367 ey
= final_exponent
- extra_digits
;
368 extra_digits
= ez
- ey
;
369 if (extra_digits
> 33) {
371 BID_normalize (sign_z
, exponent_z
, coefficient_z
,
372 sign_x
^ sign_y
, 1, rnd_mode
, pfpsf
);
375 //else // extra_digits<=32
377 if (extra_digits
> 17) {
378 CYh
= __truncate (P
, 16);
380 T
= power10_table_128
[16].w
[0];
381 __mul_64x64_to_64 (CY0L
, CYh
, T
);
382 remainder_y
= P
.w
[0] - CY0L
;
390 // align coeff_x, CYh
391 __mul_64x64_to_128 (CZ
, coefficient_z
,
392 power10_table_128
[extra_digits
].w
[0]);
394 if (sign_z
== (sign_y
^ sign_x
)) {
395 __add_128_128 (CT
, CZ
, P
);
396 if (__unsigned_compare_ge_128
397 (CT
, power10_table_128
[16 + extra_digits
])) {
402 if (remainder_y
&& (__unsigned_compare_ge_128 (CZ
, P
))) {
407 __sub_128_128 (CT
, CZ
, P
);
408 if (((SINT64
) CT
.w
[1]) < 0) {
409 sign_z
= sign_y
^ sign_x
;
410 CT
.w
[0] = 0 - CT
.w
[0];
411 CT
.w
[1] = 0 - CT
.w
[1];
414 } else if(!(CT
.w
[1]|CT
.w
[0]))
415 sign_z
= (rnd_mode
!=ROUNDING_DOWN
)? 0: 0x8000000000000000ull
;
418 (__unsigned_compare_gt_128
419 (power10_table_128
[15 + extra_digits
], CT
))) {
425 #ifdef SET_STATUS_FLAGS
429 __unsigned_compare_gt_128 (power10_table_128
430 [extra_digits
+ 15], CT
)) {
432 if (sign_z
&& (unsigned) (rmode
- 1) < 2)
434 //__add_128_64(PU, CT, round_const_table[rmode][extra_digits]);
435 PU
= power10_table_128
[extra_digits
+ 15];
437 if (__unsigned_compare_gt_128 (PU
, CT
)
438 || (rmode
== ROUNDING_DOWN
)
439 || (rmode
== ROUNDING_TO_ZERO
))
440 uf_status
= UNDERFLOW_EXCEPTION
;
441 else if (extra_digits
< 2) {
442 if ((rmode
== ROUNDING_UP
)) {
444 uf_status
= UNDERFLOW_EXCEPTION
;
446 if (remainder_y
&& (sign_z
!= (sign_y
^ sign_x
)))
447 remainder_y
= power10_table_128
[16].w
[0] - remainder_y
;
449 if (power10_table_128
[15].w
[0] > remainder_y
)
450 uf_status
= UNDERFLOW_EXCEPTION
;
452 } else // RN or RN_away
454 if (remainder_y
&& (sign_z
!= (sign_y
^ sign_x
)))
455 remainder_y
= power10_table_128
[16].w
[0] - remainder_y
;
458 remainder_y
+= round_const_table
[rmode
][15];
459 if (remainder_y
< power10_table_128
[16].w
[0])
460 uf_status
= UNDERFLOW_EXCEPTION
;
462 if (remainder_y
< round_const_table
[rmode
][16])
463 uf_status
= UNDERFLOW_EXCEPTION
;
466 //__set_status_flags (pfpsf, uf_status);
471 __bid_full_round64_remainder (sign_z
, ez
- extra_digits
, CT
,
472 extra_digits
, remainder_y
,
473 rnd_mode
, pfpsf
, uf_status
);
477 if ((sign_z
== (sign_x
^ sign_y
))
478 || (final_exponent
> 3 * 256 + 15)) {
480 fast_get_BID64_check_OF (sign_x
^ sign_y
, final_exponent
,
481 1000000000000000ull, rnd_mode
,
489 if (extra_digits
> 0) {
491 get_add128 (sign_z
, exponent_z
, coefficient_z
, sign_x
^ sign_y
,
492 final_exponent
, P
, extra_digits
, rnd_mode
, pfpsf
);
495 // go to convert_format and exit
500 get_add64 (sign_x
^ sign_y
,
501 exponent_x
+ exponent_y
- DECIMAL_EXPONENT_BIAS
, C64
,
502 sign_z
, exponent_z
, coefficient_z
,