comparison libgcc/config/libbid/bid128_div.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 04ced10e8804
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* Copyright (C) 2007, 2009 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 #define BID_128RES
25 #include "bid_div_macros.h"
26 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
27 #include <fenv.h>
28
29 #define FE_ALL_FLAGS FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW|FE_INEXACT
30 #endif
31
32 extern UINT32 convert_table[5][128][2];
33 extern SINT8 factors[][2];
34 extern UINT8 packed_10000_zeros[];
35
36 BID128_FUNCTION_ARG2 (bid128_div, x, y)
37
38 UINT256 CA4, CA4r, P256;
39 UINT128 CX, CY, T128, CQ, CR, CA, TP128, Qh, Ql, res;
40 UINT64 sign_x, sign_y, T, carry64, D, Q_high, Q_low, QX, PD,
41 valid_y;
42 int_float fx, fy, f64;
43 UINT32 QX32, tdigit[3], digit, digit_h, digit_low;
44 int exponent_x, exponent_y, bin_index, bin_expon, diff_expon, ed2,
45 digits_q, amount;
46 int nzeros, i, j, k, d5;
47 unsigned rmode;
48 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
49 fexcept_t binaryflags = 0;
50 #endif
51
52 valid_y = unpack_BID128_value (&sign_y, &exponent_y, &CY, y);
53
54 // unpack arguments, check for NaN or Infinity
55 if (!unpack_BID128_value (&sign_x, &exponent_x, &CX, x)) {
56 // test if x is NaN
57 if ((x.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
58 #ifdef SET_STATUS_FLAGS
59 if ((x.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull || // sNaN
60 (y.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull)
61 __set_status_flags (pfpsf, INVALID_EXCEPTION);
62 #endif
63 res.w[1] = (CX.w[1]) & QUIET_MASK64;
64 res.w[0] = CX.w[0];
65 BID_RETURN (res);
66 }
67 // x is Infinity?
68 if ((x.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
69 // check if y is Inf.
70 if (((y.w[1] & 0x7c00000000000000ull) == 0x7800000000000000ull))
71 // return NaN
72 {
73 #ifdef SET_STATUS_FLAGS
74 __set_status_flags (pfpsf, INVALID_EXCEPTION);
75 #endif
76 res.w[1] = 0x7c00000000000000ull;
77 res.w[0] = 0;
78 BID_RETURN (res);
79 }
80 // y is NaN?
81 if (((y.w[1] & 0x7c00000000000000ull) != 0x7c00000000000000ull))
82 // return NaN
83 {
84 // return +/-Inf
85 res.w[1] = ((x.w[1] ^ y.w[1]) & 0x8000000000000000ull) |
86 0x7800000000000000ull;
87 res.w[0] = 0;
88 BID_RETURN (res);
89 }
90 }
91 // x is 0
92 if ((y.w[1] & 0x7800000000000000ull) < 0x7800000000000000ull) {
93 if ((!CY.w[0]) && !(CY.w[1] & 0x0001ffffffffffffull)) {
94 #ifdef SET_STATUS_FLAGS
95 __set_status_flags (pfpsf, INVALID_EXCEPTION);
96 #endif
97 // x=y=0, return NaN
98 res.w[1] = 0x7c00000000000000ull;
99 res.w[0] = 0;
100 BID_RETURN (res);
101 }
102 // return 0
103 res.w[1] = (x.w[1] ^ y.w[1]) & 0x8000000000000000ull;
104 exponent_x = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS_128;
105 if (exponent_x > DECIMAL_MAX_EXPON_128)
106 exponent_x = DECIMAL_MAX_EXPON_128;
107 else if (exponent_x < 0)
108 exponent_x = 0;
109 res.w[1] |= (((UINT64) exponent_x) << 49);
110 res.w[0] = 0;
111 BID_RETURN (res);
112 }
113 }
114 if (!valid_y) {
115 // y is Inf. or NaN
116
117 // test if y is NaN
118 if ((y.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
119 #ifdef SET_STATUS_FLAGS
120 if ((y.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) // sNaN
121 __set_status_flags (pfpsf, INVALID_EXCEPTION);
122 #endif
123 res.w[1] = CY.w[1] & QUIET_MASK64;
124 res.w[0] = CY.w[0];
125 BID_RETURN (res);
126 }
127 // y is Infinity?
128 if ((y.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
129 // return +/-0
130 res.w[1] = sign_x ^ sign_y;
131 res.w[0] = 0;
132 BID_RETURN (res);
133 }
134 // y is 0, return +/-Inf
135 #ifdef SET_STATUS_FLAGS
136 __set_status_flags (pfpsf, ZERO_DIVIDE_EXCEPTION);
137 #endif
138 res.w[1] =
139 ((x.w[1] ^ y.w[1]) & 0x8000000000000000ull) | 0x7800000000000000ull;
140 res.w[0] = 0;
141 BID_RETURN (res);
142 }
143 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
144 (void) fegetexceptflag (&binaryflags, FE_ALL_FLAGS);
145 #endif
146 diff_expon = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS_128;
147
148 if (__unsigned_compare_gt_128 (CY, CX)) {
149 // CX < CY
150
151 // 2^64
152 f64.i = 0x5f800000;
153
154 // fx ~ CX, fy ~ CY
155 fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
156 fy.d = (float) CY.w[1] * f64.d + (float) CY.w[0];
157 // expon_cy - expon_cx
158 bin_index = (fy.i - fx.i) >> 23;
159
160 if (CX.w[1]) {
161 T = power10_index_binexp_128[bin_index].w[0];
162 __mul_64x128_short (CA, T, CX);
163 } else {
164 T128 = power10_index_binexp_128[bin_index];
165 __mul_64x128_short (CA, CX.w[0], T128);
166 }
167
168 ed2 = 33;
169 if (__unsigned_compare_gt_128 (CY, CA))
170 ed2++;
171
172 T128 = power10_table_128[ed2];
173 __mul_128x128_to_256 (CA4, CA, T128);
174
175 ed2 += estimate_decimal_digits[bin_index];
176 CQ.w[0] = CQ.w[1] = 0;
177 diff_expon = diff_expon - ed2;
178
179 } else {
180 // get CQ = CX/CY
181 __div_128_by_128 (&CQ, &CR, CX, CY);
182
183 if (!CR.w[1] && !CR.w[0]) {
184 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,
185 pfpsf);
186 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
187 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
188 #endif
189 BID_RETURN (res);
190 }
191 // get number of decimal digits in CQ
192 // 2^64
193 f64.i = 0x5f800000;
194 fx.d = (float) CQ.w[1] * f64.d + (float) CQ.w[0];
195 // binary expon. of CQ
196 bin_expon = (fx.i - 0x3f800000) >> 23;
197
198 digits_q = estimate_decimal_digits[bin_expon];
199 TP128.w[0] = power10_index_binexp_128[bin_expon].w[0];
200 TP128.w[1] = power10_index_binexp_128[bin_expon].w[1];
201 if (__unsigned_compare_ge_128 (CQ, TP128))
202 digits_q++;
203
204 ed2 = 34 - digits_q;
205 T128.w[0] = power10_table_128[ed2].w[0];
206 T128.w[1] = power10_table_128[ed2].w[1];
207 __mul_128x128_to_256 (CA4, CR, T128);
208 diff_expon = diff_expon - ed2;
209 __mul_128x128_low (CQ, CQ, T128);
210
211 }
212
213 __div_256_by_128 (&CQ, &CA4, CY);
214
215 #ifdef SET_STATUS_FLAGS
216 if (CA4.w[0] || CA4.w[1]) {
217 // set status flags
218 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
219 }
220 #ifndef LEAVE_TRAILING_ZEROS
221 else
222 #endif
223 #else
224 #ifndef LEAVE_TRAILING_ZEROS
225 if (!CA4.w[0] && !CA4.w[1])
226 #endif
227 #endif
228 #ifndef LEAVE_TRAILING_ZEROS
229 // check whether result is exact
230 {
231 // check whether CX, CY are short
232 if (!CX.w[1] && !CY.w[1] && (CX.w[0] <= 1024) && (CY.w[0] <= 1024)) {
233 i = (int) CY.w[0] - 1;
234 j = (int) CX.w[0] - 1;
235 // difference in powers of 2 factors for Y and X
236 nzeros = ed2 - factors[i][0] + factors[j][0];
237 // difference in powers of 5 factors
238 d5 = ed2 - factors[i][1] + factors[j][1];
239 if (d5 < nzeros)
240 nzeros = d5;
241 // get P*(2^M[extra_digits])/10^extra_digits
242 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
243
244 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
245 amount = recip_scale[nzeros];
246 __shr_128_long (CQ, Qh, amount);
247
248 diff_expon += nzeros;
249 } else {
250 // decompose Q as Qh*10^17 + Ql
251 //T128 = reciprocals10_128[17];
252 T128.w[0] = 0x44909befeb9fad49ull;
253 T128.w[1] = 0x000b877aa3236a4bull;
254 __mul_128x128_to_256 (P256, CQ, T128);
255 //amount = recip_scale[17];
256 Q_high = (P256.w[2] >> 44) | (P256.w[3] << (64 - 44));
257 Q_low = CQ.w[0] - Q_high * 100000000000000000ull;
258
259 if (!Q_low) {
260 diff_expon += 17;
261
262 tdigit[0] = Q_high & 0x3ffffff;
263 tdigit[1] = 0;
264 QX = Q_high >> 26;
265 QX32 = QX;
266 nzeros = 0;
267
268 for (j = 0; QX32; j++, QX32 >>= 7) {
269 k = (QX32 & 127);
270 tdigit[0] += convert_table[j][k][0];
271 tdigit[1] += convert_table[j][k][1];
272 if (tdigit[0] >= 100000000) {
273 tdigit[0] -= 100000000;
274 tdigit[1]++;
275 }
276 }
277
278 if (tdigit[1] >= 100000000) {
279 tdigit[1] -= 100000000;
280 if (tdigit[1] >= 100000000)
281 tdigit[1] -= 100000000;
282 }
283
284 digit = tdigit[0];
285 if (!digit && !tdigit[1])
286 nzeros += 16;
287 else {
288 if (!digit) {
289 nzeros += 8;
290 digit = tdigit[1];
291 }
292 // decompose digit
293 PD = (UINT64) digit *0x068DB8BBull;
294 digit_h = (UINT32) (PD >> 40);
295 digit_low = digit - digit_h * 10000;
296
297 if (!digit_low)
298 nzeros += 4;
299 else
300 digit_h = digit_low;
301
302 if (!(digit_h & 1))
303 nzeros +=
304 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
305 (digit_h & 7));
306 }
307
308 if (nzeros) {
309 __mul_64x64_to_128 (CQ, Q_high, reciprocals10_64[nzeros]);
310
311 // now get P/10^extra_digits: shift C64 right by M[extra_digits]-64
312 amount = short_recip_scale[nzeros];
313 CQ.w[0] = CQ.w[1] >> amount;
314 } else
315 CQ.w[0] = Q_high;
316 CQ.w[1] = 0;
317
318 diff_expon += nzeros;
319 } else {
320 tdigit[0] = Q_low & 0x3ffffff;
321 tdigit[1] = 0;
322 QX = Q_low >> 26;
323 QX32 = QX;
324 nzeros = 0;
325
326 for (j = 0; QX32; j++, QX32 >>= 7) {
327 k = (QX32 & 127);
328 tdigit[0] += convert_table[j][k][0];
329 tdigit[1] += convert_table[j][k][1];
330 if (tdigit[0] >= 100000000) {
331 tdigit[0] -= 100000000;
332 tdigit[1]++;
333 }
334 }
335
336 if (tdigit[1] >= 100000000) {
337 tdigit[1] -= 100000000;
338 if (tdigit[1] >= 100000000)
339 tdigit[1] -= 100000000;
340 }
341
342 digit = tdigit[0];
343 if (!digit && !tdigit[1])
344 nzeros += 16;
345 else {
346 if (!digit) {
347 nzeros += 8;
348 digit = tdigit[1];
349 }
350 // decompose digit
351 PD = (UINT64) digit *0x068DB8BBull;
352 digit_h = (UINT32) (PD >> 40);
353 digit_low = digit - digit_h * 10000;
354
355 if (!digit_low)
356 nzeros += 4;
357 else
358 digit_h = digit_low;
359
360 if (!(digit_h & 1))
361 nzeros +=
362 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
363 (digit_h & 7));
364 }
365
366 if (nzeros) {
367 // get P*(2^M[extra_digits])/10^extra_digits
368 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
369
370 //now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
371 amount = recip_scale[nzeros];
372 __shr_128 (CQ, Qh, amount);
373 }
374 diff_expon += nzeros;
375
376 }
377 }
378 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode, pfpsf);
379 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
380 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
381 #endif
382 BID_RETURN (res);
383 }
384 #endif
385
386 if (diff_expon >= 0) {
387 #ifdef IEEE_ROUND_NEAREST
388 // rounding
389 // 2*CA4 - CY
390 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
391 CA4r.w[0] = CA4.w[0] + CA4.w[0];
392 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
393 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
394
395 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
396 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
397
398 CQ.w[0] += carry64;
399 if (CQ.w[0] < carry64)
400 CQ.w[1]++;
401 #else
402 #ifdef IEEE_ROUND_NEAREST_TIES_AWAY
403 // rounding
404 // 2*CA4 - CY
405 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
406 CA4r.w[0] = CA4.w[0] + CA4.w[0];
407 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
408 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
409
410 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
411 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
412
413 CQ.w[0] += carry64;
414 if (CQ.w[0] < carry64)
415 CQ.w[1]++;
416 #else
417 rmode = rnd_mode;
418 if (sign_x ^ sign_y && (unsigned) (rmode - 1) < 2)
419 rmode = 3 - rmode;
420 switch (rmode) {
421 case ROUNDING_TO_NEAREST: // round to nearest code
422 // rounding
423 // 2*CA4 - CY
424 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
425 CA4r.w[0] = CA4.w[0] + CA4.w[0];
426 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
427 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
428 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
429 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
430 CQ.w[0] += carry64;
431 if (CQ.w[0] < carry64)
432 CQ.w[1]++;
433 break;
434 case ROUNDING_TIES_AWAY:
435 // rounding
436 // 2*CA4 - CY
437 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
438 CA4r.w[0] = CA4.w[0] + CA4.w[0];
439 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
440 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
441 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
442 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
443 CQ.w[0] += carry64;
444 if (CQ.w[0] < carry64)
445 CQ.w[1]++;
446 break;
447 case ROUNDING_DOWN:
448 case ROUNDING_TO_ZERO:
449 break;
450 default: // rounding up
451 CQ.w[0]++;
452 if (!CQ.w[0])
453 CQ.w[1]++;
454 break;
455 }
456 #endif
457 #endif
458
459 } else {
460 #ifdef SET_STATUS_FLAGS
461 if (CA4.w[0] || CA4.w[1]) {
462 // set status flags
463 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
464 }
465 #endif
466
467 handle_UF_128_rem (&res, sign_x ^ sign_y, diff_expon, CQ,
468 CA4.w[1] | CA4.w[0], &rnd_mode, pfpsf);
469 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
470 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
471 #endif
472 BID_RETURN (res);
473
474 }
475
476 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode, pfpsf);
477 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
478 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
479 #endif
480 BID_RETURN (res);
481 }
482
483
484 //#define LEAVE_TRAILING_ZEROS
485
486 TYPE0_FUNCTION_ARGTYPE1_ARGTYPE2 (UINT128, bid128dd_div, UINT64, x,
487 UINT64, y)
488
489 UINT256 CA4, CA4r, P256;
490 UINT128 CX, CY, T128, CQ, CR, CA, TP128, Qh, Ql, res;
491 UINT64 sign_x, sign_y, T, carry64, D, Q_high, Q_low, QX, PD,
492 valid_y;
493 int_float fx, fy, f64;
494 UINT32 QX32, tdigit[3], digit, digit_h, digit_low;
495 int exponent_x, exponent_y, bin_index, bin_expon, diff_expon, ed2,
496 digits_q, amount;
497 int nzeros, i, j, k, d5;
498 unsigned rmode;
499 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
500 fexcept_t binaryflags = 0;
501 #endif
502
503 valid_y = unpack_BID64 (&sign_y, &exponent_y, &CY.w[0], y);
504
505 // unpack arguments, check for NaN or Infinity
506 CX.w[1] = 0;
507 if (!unpack_BID64 (&sign_x, &exponent_x, &CX.w[0], (x))) {
508 #ifdef SET_STATUS_FLAGS
509 if ((y & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
510 __set_status_flags (pfpsf, INVALID_EXCEPTION);
511 #endif
512
513 // test if x is NaN
514 if ((x & NAN_MASK64) == NAN_MASK64) {
515 #ifdef SET_STATUS_FLAGS
516 if ((x & SNAN_MASK64) == SNAN_MASK64) // sNaN
517 __set_status_flags (pfpsf, INVALID_EXCEPTION);
518 #endif
519 res.w[0] = (CX.w[0] & 0x0003ffffffffffffull);
520 __mul_64x64_to_128 (res, res.w[0], power10_table_128[18].w[0]);
521 res.w[1] |= ((CX.w[0]) & 0xfc00000000000000ull);
522 BID_RETURN (res);
523 }
524 // x is Infinity?
525 if (((x) & 0x7800000000000000ull) == 0x7800000000000000ull) {
526 // check if y is Inf.
527 if ((((y) & 0x7c00000000000000ull) == 0x7800000000000000ull))
528 // return NaN
529 {
530 #ifdef SET_STATUS_FLAGS
531 __set_status_flags (pfpsf, INVALID_EXCEPTION);
532 #endif
533 res.w[1] = 0x7c00000000000000ull;
534 res.w[0] = 0;
535 BID_RETURN (res);
536 }
537 if ((((y) & 0x7c00000000000000ull) != 0x7c00000000000000ull)) {
538 // otherwise return +/-Inf
539 res.w[1] =
540 (((x) ^ (y)) & 0x8000000000000000ull) | 0x7800000000000000ull;
541 res.w[0] = 0;
542 BID_RETURN (res);
543 }
544 }
545 // x is 0
546 if ((((y) & 0x7800000000000000ull) != 0x7800000000000000ull)) {
547 if(!CY.w[0]) {
548 #ifdef SET_STATUS_FLAGS
549 __set_status_flags (pfpsf, INVALID_EXCEPTION);
550 #endif
551 // x=y=0, return NaN
552 res.w[1] = 0x7c00000000000000ull;
553 res.w[0] = 0;
554 BID_RETURN (res);
555 }
556 // return 0
557 res.w[1] = ((x) ^ (y)) & 0x8000000000000000ull;
558 if (((y) & 0x6000000000000000ull) == 0x6000000000000000ull)
559 exponent_y = ((UINT32) ((y) >> 51)) & 0x3ff;
560 else
561 exponent_y = ((UINT32) ((y) >> 53)) & 0x3ff;
562 exponent_x = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS_128;
563 if (exponent_x > DECIMAL_MAX_EXPON_128)
564 exponent_x = DECIMAL_MAX_EXPON_128;
565 else if (exponent_x < 0)
566 exponent_x = 0;
567 res.w[1] |= (((UINT64) exponent_x) << 49);
568 res.w[0] = 0;
569 BID_RETURN (res);
570 }
571 }
572
573 CY.w[1] = 0;
574 if (!valid_y) {
575 // y is Inf. or NaN
576
577 // test if y is NaN
578 if ((y & NAN_MASK64) == NAN_MASK64) {
579 #ifdef SET_STATUS_FLAGS
580 if ((y & SNAN_MASK64) == SNAN_MASK64) // sNaN
581 __set_status_flags (pfpsf, INVALID_EXCEPTION);
582 #endif
583 res.w[0] = (CY.w[0] & 0x0003ffffffffffffull);
584 __mul_64x64_to_128 (res, res.w[0], power10_table_128[18].w[0]);
585 res.w[1] |= ((CY.w[0]) & 0xfc00000000000000ull);
586 BID_RETURN (res);
587 }
588 // y is Infinity?
589 if (((y) & 0x7800000000000000ull) == 0x7800000000000000ull) {
590 // return +/-0
591 res.w[1] = sign_x ^ sign_y;
592 res.w[0] = 0;
593 BID_RETURN (res);
594 }
595 // y is 0, return +/-Inf
596 res.w[1] =
597 (((x) ^ (y)) & 0x8000000000000000ull) | 0x7800000000000000ull;
598 res.w[0] = 0;
599 #ifdef SET_STATUS_FLAGS
600 __set_status_flags (pfpsf, ZERO_DIVIDE_EXCEPTION);
601 #endif
602 BID_RETURN (res);
603 }
604 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
605 (void) fegetexceptflag (&binaryflags, FE_ALL_FLAGS);
606 #endif
607 diff_expon = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS_128;
608
609 if (__unsigned_compare_gt_128 (CY, CX)) {
610 // CX < CY
611
612 // 2^64
613 f64.i = 0x5f800000;
614
615 // fx ~ CX, fy ~ CY
616 fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
617 fy.d = (float) CY.w[1] * f64.d + (float) CY.w[0];
618 // expon_cy - expon_cx
619 bin_index = (fy.i - fx.i) >> 23;
620
621 if (CX.w[1]) {
622 T = power10_index_binexp_128[bin_index].w[0];
623 __mul_64x128_short (CA, T, CX);
624 } else {
625 T128 = power10_index_binexp_128[bin_index];
626 __mul_64x128_short (CA, CX.w[0], T128);
627 }
628
629 ed2 = 33;
630 if (__unsigned_compare_gt_128 (CY, CA))
631 ed2++;
632
633 T128 = power10_table_128[ed2];
634 __mul_128x128_to_256 (CA4, CA, T128);
635
636 ed2 += estimate_decimal_digits[bin_index];
637 CQ.w[0] = CQ.w[1] = 0;
638 diff_expon = diff_expon - ed2;
639
640 } else {
641 // get CQ = CX/CY
642 __div_128_by_128 (&CQ, &CR, CX, CY);
643
644 if (!CR.w[1] && !CR.w[0]) {
645 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,
646 pfpsf);
647 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
648 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
649 #endif
650 BID_RETURN (res);
651 }
652 // get number of decimal digits in CQ
653 // 2^64
654 f64.i = 0x5f800000;
655 fx.d = (float) CQ.w[1] * f64.d + (float) CQ.w[0];
656 // binary expon. of CQ
657 bin_expon = (fx.i - 0x3f800000) >> 23;
658
659 digits_q = estimate_decimal_digits[bin_expon];
660 TP128.w[0] = power10_index_binexp_128[bin_expon].w[0];
661 TP128.w[1] = power10_index_binexp_128[bin_expon].w[1];
662 if (__unsigned_compare_ge_128 (CQ, TP128))
663 digits_q++;
664
665 ed2 = 34 - digits_q;
666 T128.w[0] = power10_table_128[ed2].w[0];
667 T128.w[1] = power10_table_128[ed2].w[1];
668 __mul_128x128_to_256 (CA4, CR, T128);
669 diff_expon = diff_expon - ed2;
670 __mul_128x128_low (CQ, CQ, T128);
671
672 }
673
674 __div_256_by_128 (&CQ, &CA4, CY);
675
676
677 #ifdef SET_STATUS_FLAGS
678 if (CA4.w[0] || CA4.w[1]) {
679 // set status flags
680 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
681 }
682 #ifndef LEAVE_TRAILING_ZEROS
683 else
684 #endif
685 #else
686 #ifndef LEAVE_TRAILING_ZEROS
687 if (!CA4.w[0] && !CA4.w[1])
688 #endif
689 #endif
690 #ifndef LEAVE_TRAILING_ZEROS
691 // check whether result is exact
692 {
693 // check whether CX, CY are short
694 if (!CX.w[1] && !CY.w[1] && (CX.w[0] <= 1024) && (CY.w[0] <= 1024)) {
695 i = (int) CY.w[0] - 1;
696 j = (int) CX.w[0] - 1;
697 // difference in powers of 2 factors for Y and X
698 nzeros = ed2 - factors[i][0] + factors[j][0];
699 // difference in powers of 5 factors
700 d5 = ed2 - factors[i][1] + factors[j][1];
701 if (d5 < nzeros)
702 nzeros = d5;
703 // get P*(2^M[extra_digits])/10^extra_digits
704 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
705 //__mul_128x128_to_256(P256, CQ, reciprocals10_128[nzeros]);Qh.w[1]=P256.w[3];Qh.w[0]=P256.w[2];
706
707 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
708 amount = recip_scale[nzeros];
709 __shr_128_long (CQ, Qh, amount);
710
711 diff_expon += nzeros;
712 } else {
713 // decompose Q as Qh*10^17 + Ql
714 //T128 = reciprocals10_128[17];
715 T128.w[0] = 0x44909befeb9fad49ull;
716 T128.w[1] = 0x000b877aa3236a4bull;
717 __mul_128x128_to_256 (P256, CQ, T128);
718 //amount = recip_scale[17];
719 Q_high = (P256.w[2] >> 44) | (P256.w[3] << (64 - 44));
720 Q_low = CQ.w[0] - Q_high * 100000000000000000ull;
721
722 if (!Q_low) {
723 diff_expon += 17;
724
725 tdigit[0] = Q_high & 0x3ffffff;
726 tdigit[1] = 0;
727 QX = Q_high >> 26;
728 QX32 = QX;
729 nzeros = 0;
730
731 for (j = 0; QX32; j++, QX32 >>= 7) {
732 k = (QX32 & 127);
733 tdigit[0] += convert_table[j][k][0];
734 tdigit[1] += convert_table[j][k][1];
735 if (tdigit[0] >= 100000000) {
736 tdigit[0] -= 100000000;
737 tdigit[1]++;
738 }
739 }
740
741
742 if (tdigit[1] >= 100000000) {
743 tdigit[1] -= 100000000;
744 if (tdigit[1] >= 100000000)
745 tdigit[1] -= 100000000;
746 }
747
748 digit = tdigit[0];
749 if (!digit && !tdigit[1])
750 nzeros += 16;
751 else {
752 if (!digit) {
753 nzeros += 8;
754 digit = tdigit[1];
755 }
756 // decompose digit
757 PD = (UINT64) digit *0x068DB8BBull;
758 digit_h = (UINT32) (PD >> 40);
759 digit_low = digit - digit_h * 10000;
760
761 if (!digit_low)
762 nzeros += 4;
763 else
764 digit_h = digit_low;
765
766 if (!(digit_h & 1))
767 nzeros +=
768 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
769 (digit_h & 7));
770 }
771
772 if (nzeros) {
773 __mul_64x64_to_128 (CQ, Q_high, reciprocals10_64[nzeros]);
774
775 // now get P/10^extra_digits: shift C64 right by M[extra_digits]-64
776 amount = short_recip_scale[nzeros];
777 CQ.w[0] = CQ.w[1] >> amount;
778 } else
779 CQ.w[0] = Q_high;
780 CQ.w[1] = 0;
781
782 diff_expon += nzeros;
783 } else {
784 tdigit[0] = Q_low & 0x3ffffff;
785 tdigit[1] = 0;
786 QX = Q_low >> 26;
787 QX32 = QX;
788 nzeros = 0;
789
790 for (j = 0; QX32; j++, QX32 >>= 7) {
791 k = (QX32 & 127);
792 tdigit[0] += convert_table[j][k][0];
793 tdigit[1] += convert_table[j][k][1];
794 if (tdigit[0] >= 100000000) {
795 tdigit[0] -= 100000000;
796 tdigit[1]++;
797 }
798 }
799
800 if (tdigit[1] >= 100000000) {
801 tdigit[1] -= 100000000;
802 if (tdigit[1] >= 100000000)
803 tdigit[1] -= 100000000;
804 }
805
806 digit = tdigit[0];
807 if (!digit && !tdigit[1])
808 nzeros += 16;
809 else {
810 if (!digit) {
811 nzeros += 8;
812 digit = tdigit[1];
813 }
814 // decompose digit
815 PD = (UINT64) digit *0x068DB8BBull;
816 digit_h = (UINT32) (PD >> 40);
817 digit_low = digit - digit_h * 10000;
818
819 if (!digit_low)
820 nzeros += 4;
821 else
822 digit_h = digit_low;
823
824 if (!(digit_h & 1))
825 nzeros +=
826 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
827 (digit_h & 7));
828 }
829
830 if (nzeros) {
831 // get P*(2^M[extra_digits])/10^extra_digits
832 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
833
834 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
835 amount = recip_scale[nzeros];
836 __shr_128 (CQ, Qh, amount);
837 }
838 diff_expon += nzeros;
839
840 }
841 }
842 get_BID128(&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,pfpsf);
843 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
844 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
845 #endif
846 BID_RETURN (res);
847 }
848 #endif
849
850 if (diff_expon >= 0) {
851 #ifdef IEEE_ROUND_NEAREST
852 // rounding
853 // 2*CA4 - CY
854 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
855 CA4r.w[0] = CA4.w[0] + CA4.w[0];
856 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
857 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
858
859 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
860 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
861
862 CQ.w[0] += carry64;
863 if (CQ.w[0] < carry64)
864 CQ.w[1]++;
865 #else
866 #ifdef IEEE_ROUND_NEAREST_TIES_AWAY
867 // rounding
868 // 2*CA4 - CY
869 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
870 CA4r.w[0] = CA4.w[0] + CA4.w[0];
871 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
872 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
873
874 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
875 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
876
877 CQ.w[0] += carry64;
878 if (CQ.w[0] < carry64)
879 CQ.w[1]++;
880 #else
881 rmode = rnd_mode;
882 if (sign_x ^ sign_y && (unsigned) (rmode - 1) < 2)
883 rmode = 3 - rmode;
884 switch (rmode) {
885 case ROUNDING_TO_NEAREST: // round to nearest code
886 // rounding
887 // 2*CA4 - CY
888 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
889 CA4r.w[0] = CA4.w[0] + CA4.w[0];
890 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
891 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
892 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
893 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
894 CQ.w[0] += carry64;
895 if (CQ.w[0] < carry64)
896 CQ.w[1]++;
897 break;
898 case ROUNDING_TIES_AWAY:
899 // rounding
900 // 2*CA4 - CY
901 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
902 CA4r.w[0] = CA4.w[0] + CA4.w[0];
903 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
904 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
905 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
906 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
907 CQ.w[0] += carry64;
908 if (CQ.w[0] < carry64)
909 CQ.w[1]++;
910 break;
911 case ROUNDING_DOWN:
912 case ROUNDING_TO_ZERO:
913 break;
914 default: // rounding up
915 CQ.w[0]++;
916 if (!CQ.w[0])
917 CQ.w[1]++;
918 break;
919 }
920 #endif
921 #endif
922
923 } else {
924 #ifdef SET_STATUS_FLAGS
925 if (CA4.w[0] || CA4.w[1]) {
926 // set status flags
927 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
928 }
929 #endif
930 handle_UF_128_rem (&res, sign_x ^ sign_y, diff_expon, CQ,
931 CA4.w[1] | CA4.w[0], &rnd_mode, pfpsf);
932 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
933 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
934 #endif
935 BID_RETURN (res);
936
937 }
938
939 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode, pfpsf);
940 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
941 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
942 #endif
943 BID_RETURN (res);
944 }
945
946
947 BID128_FUNCTION_ARGTYPE1_ARG128 (bid128dq_div, UINT64, x, y)
948 UINT256 CA4, CA4r, P256;
949 UINT128 CX, CY, T128, CQ, CR, CA, TP128, Qh, Ql, res;
950 UINT64 sign_x, sign_y, T, carry64, D, Q_high, Q_low, QX, valid_y,
951 PD;
952 int_float fx, fy, f64;
953 UINT32 QX32, tdigit[3], digit, digit_h, digit_low;
954 int exponent_x, exponent_y, bin_index, bin_expon, diff_expon, ed2,
955 digits_q, amount;
956 int nzeros, i, j, k, d5;
957 unsigned rmode;
958 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
959 fexcept_t binaryflags = 0;
960 #endif
961
962 valid_y = unpack_BID128_value (&sign_y, &exponent_y, &CY, y);
963
964 // unpack arguments, check for NaN or Infinity
965 CX.w[1] = 0;
966 if (!unpack_BID64 (&sign_x, &exponent_x, &CX.w[0], x)) {
967 #ifdef SET_STATUS_FLAGS
968 if ((y.w[1] & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
969 __set_status_flags (pfpsf, INVALID_EXCEPTION);
970 #endif
971
972 // test if x is NaN
973 if ((x & NAN_MASK64) == NAN_MASK64) {
974 #ifdef SET_STATUS_FLAGS
975 if ((x & SNAN_MASK64) == SNAN_MASK64) // sNaN
976 __set_status_flags (pfpsf, INVALID_EXCEPTION);
977 #endif
978 res.w[0] = (CX.w[0] & 0x0003ffffffffffffull);
979 __mul_64x64_to_128 (res, res.w[0], power10_table_128[18].w[0]);
980 res.w[1] |= ((CX.w[0]) & 0xfc00000000000000ull);
981 BID_RETURN (res);
982 }
983 // x is Infinity?
984 if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
985 // check if y is Inf.
986 if (((y.w[1] & 0x7c00000000000000ull) == 0x7800000000000000ull))
987 // return NaN
988 {
989 #ifdef SET_STATUS_FLAGS
990 __set_status_flags (pfpsf, INVALID_EXCEPTION);
991 #endif
992 res.w[1] = 0x7c00000000000000ull;
993 res.w[0] = 0;
994 BID_RETURN (res);
995 }
996 if (((y.w[1] & 0x7c00000000000000ull) != 0x7c00000000000000ull)) {
997 // otherwise return +/-Inf
998 res.w[1] =
999 ((x ^ y.w[1]) & 0x8000000000000000ull) | 0x7800000000000000ull;
1000 res.w[0] = 0;
1001 BID_RETURN (res);
1002 }
1003 }
1004 // x is 0
1005 if ((y.w[1] & INFINITY_MASK64) != INFINITY_MASK64) {
1006 if ((!CY.w[0]) && !(CY.w[1] & 0x0001ffffffffffffull)) {
1007 #ifdef SET_STATUS_FLAGS
1008 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1009 #endif
1010 // x=y=0, return NaN
1011 res.w[1] = 0x7c00000000000000ull;
1012 res.w[0] = 0;
1013 BID_RETURN (res);
1014 }
1015 // return 0
1016 res.w[1] = (x ^ y.w[1]) & 0x8000000000000000ull;
1017 exponent_x = exponent_x - exponent_y + (DECIMAL_EXPONENT_BIAS_128<<1) - DECIMAL_EXPONENT_BIAS;
1018 if (exponent_x > DECIMAL_MAX_EXPON_128)
1019 exponent_x = DECIMAL_MAX_EXPON_128;
1020 else if (exponent_x < 0)
1021 exponent_x = 0;
1022 res.w[1] |= (((UINT64) exponent_x) << 49);
1023 res.w[0] = 0;
1024 BID_RETURN (res);
1025 }
1026 }
1027 exponent_x += (DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS);
1028
1029 if (!valid_y) {
1030 // y is Inf. or NaN
1031
1032 // test if y is NaN
1033 if ((y.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
1034 #ifdef SET_STATUS_FLAGS
1035 if ((y.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) // sNaN
1036 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1037 #endif
1038 res.w[1] = CY.w[1] & QUIET_MASK64;
1039 res.w[0] = CY.w[0];
1040 BID_RETURN (res);
1041 }
1042 // y is Infinity?
1043 if ((y.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
1044 // return +/-0
1045 res.w[1] = sign_x ^ sign_y;
1046 res.w[0] = 0;
1047 BID_RETURN (res);
1048 }
1049 // y is 0, return +/-Inf
1050 res.w[1] =
1051 ((x ^ y.w[1]) & 0x8000000000000000ull) | 0x7800000000000000ull;
1052 res.w[0] = 0;
1053 #ifdef SET_STATUS_FLAGS
1054 __set_status_flags (pfpsf, ZERO_DIVIDE_EXCEPTION);
1055 #endif
1056 BID_RETURN (res);
1057 }
1058 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1059 (void) fegetexceptflag (&binaryflags, FE_ALL_FLAGS);
1060 #endif
1061 diff_expon = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS_128;
1062
1063 if (__unsigned_compare_gt_128 (CY, CX)) {
1064 // CX < CY
1065
1066 // 2^64
1067 f64.i = 0x5f800000;
1068
1069 // fx ~ CX, fy ~ CY
1070 fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
1071 fy.d = (float) CY.w[1] * f64.d + (float) CY.w[0];
1072 // expon_cy - expon_cx
1073 bin_index = (fy.i - fx.i) >> 23;
1074
1075 if (CX.w[1]) {
1076 T = power10_index_binexp_128[bin_index].w[0];
1077 __mul_64x128_short (CA, T, CX);
1078 } else {
1079 T128 = power10_index_binexp_128[bin_index];
1080 __mul_64x128_short (CA, CX.w[0], T128);
1081 }
1082
1083 ed2 = 33;
1084 if (__unsigned_compare_gt_128 (CY, CA))
1085 ed2++;
1086
1087 T128 = power10_table_128[ed2];
1088 __mul_128x128_to_256 (CA4, CA, T128);
1089
1090 ed2 += estimate_decimal_digits[bin_index];
1091 CQ.w[0] = CQ.w[1] = 0;
1092 diff_expon = diff_expon - ed2;
1093
1094 } else {
1095 // get CQ = CX/CY
1096 __div_128_by_128 (&CQ, &CR, CX, CY);
1097
1098 if (!CR.w[1] && !CR.w[0]) {
1099 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,
1100 pfpsf);
1101 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1102 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1103 #endif
1104 BID_RETURN (res);
1105 }
1106 // get number of decimal digits in CQ
1107 // 2^64
1108 f64.i = 0x5f800000;
1109 fx.d = (float) CQ.w[1] * f64.d + (float) CQ.w[0];
1110 // binary expon. of CQ
1111 bin_expon = (fx.i - 0x3f800000) >> 23;
1112
1113 digits_q = estimate_decimal_digits[bin_expon];
1114 TP128.w[0] = power10_index_binexp_128[bin_expon].w[0];
1115 TP128.w[1] = power10_index_binexp_128[bin_expon].w[1];
1116 if (__unsigned_compare_ge_128 (CQ, TP128))
1117 digits_q++;
1118
1119 ed2 = 34 - digits_q;
1120 T128.w[0] = power10_table_128[ed2].w[0];
1121 T128.w[1] = power10_table_128[ed2].w[1];
1122 __mul_128x128_to_256 (CA4, CR, T128);
1123 diff_expon = diff_expon - ed2;
1124 __mul_128x128_low (CQ, CQ, T128);
1125
1126 }
1127
1128 __div_256_by_128 (&CQ, &CA4, CY);
1129
1130 #ifdef SET_STATUS_FLAGS
1131 if (CA4.w[0] || CA4.w[1]) {
1132 // set status flags
1133 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
1134 }
1135 #ifndef LEAVE_TRAILING_ZEROS
1136 else
1137 #endif
1138 #else
1139 #ifndef LEAVE_TRAILING_ZEROS
1140 if (!CA4.w[0] && !CA4.w[1])
1141 #endif
1142 #endif
1143 #ifndef LEAVE_TRAILING_ZEROS
1144 // check whether result is exact
1145 {
1146 //printf("ed2=%d,nz=%d,a=%d,CQ="LX16","LX16", RH="LX16", RL="LX16"\n",ed2,nzeros,amount,CQ.w[1],CQ.w[0],reciprocals10_128[nzeros].w[1],reciprocals10_128[nzeros].w[0]);fflush(stdout);
1147 // check whether CX, CY are short
1148 if (!CX.w[1] && !CY.w[1] && (CX.w[0] <= 1024) && (CY.w[0] <= 1024)) {
1149 i = (int) CY.w[0] - 1;
1150 j = (int) CX.w[0] - 1;
1151 // difference in powers of 2 factors for Y and X
1152 nzeros = ed2 - factors[i][0] + factors[j][0];
1153 // difference in powers of 5 factors
1154 d5 = ed2 - factors[i][1] + factors[j][1];
1155 if (d5 < nzeros)
1156 nzeros = d5;
1157 // get P*(2^M[extra_digits])/10^extra_digits
1158 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
1159 //__mul_128x128_to_256(P256, CQ, reciprocals10_128[nzeros]);Qh.w[1]=P256.w[3];Qh.w[0]=P256.w[2];
1160
1161 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
1162 amount = recip_scale[nzeros];
1163 __shr_128_long (CQ, Qh, amount);
1164
1165 diff_expon += nzeros;
1166 } else {
1167 // decompose Q as Qh*10^17 + Ql
1168 //T128 = reciprocals10_128[17];
1169 T128.w[0] = 0x44909befeb9fad49ull;
1170 T128.w[1] = 0x000b877aa3236a4bull;
1171 __mul_128x128_to_256 (P256, CQ, T128);
1172 //amount = recip_scale[17];
1173 Q_high = (P256.w[2] >> 44) | (P256.w[3] << (64 - 44));
1174 Q_low = CQ.w[0] - Q_high * 100000000000000000ull;
1175
1176 if (!Q_low) {
1177 diff_expon += 17;
1178
1179 tdigit[0] = Q_high & 0x3ffffff;
1180 tdigit[1] = 0;
1181 QX = Q_high >> 26;
1182 QX32 = QX;
1183 nzeros = 0;
1184
1185 for (j = 0; QX32; j++, QX32 >>= 7) {
1186 k = (QX32 & 127);
1187 tdigit[0] += convert_table[j][k][0];
1188 tdigit[1] += convert_table[j][k][1];
1189 if (tdigit[0] >= 100000000) {
1190 tdigit[0] -= 100000000;
1191 tdigit[1]++;
1192 }
1193 }
1194
1195
1196 if (tdigit[1] >= 100000000) {
1197 tdigit[1] -= 100000000;
1198 if (tdigit[1] >= 100000000)
1199 tdigit[1] -= 100000000;
1200 }
1201
1202 digit = tdigit[0];
1203 if (!digit && !tdigit[1])
1204 nzeros += 16;
1205 else {
1206 if (!digit) {
1207 nzeros += 8;
1208 digit = tdigit[1];
1209 }
1210 // decompose digit
1211 PD = (UINT64) digit *0x068DB8BBull;
1212 digit_h = (UINT32) (PD >> 40);
1213 //printf("i=%d, nz=%d, digit=%d (%d, %016I64x %016I64x)\n",i,nzeros,digit_h,digit,PD,digit_h);fflush(stdout);
1214 digit_low = digit - digit_h * 10000;
1215
1216 if (!digit_low)
1217 nzeros += 4;
1218 else
1219 digit_h = digit_low;
1220
1221 if (!(digit_h & 1))
1222 nzeros +=
1223 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
1224 (digit_h & 7));
1225 }
1226
1227 if (nzeros) {
1228 __mul_64x64_to_128 (CQ, Q_high, reciprocals10_64[nzeros]);
1229
1230 // now get P/10^extra_digits: shift C64 right by M[extra_digits]-64
1231 amount = short_recip_scale[nzeros];
1232 CQ.w[0] = CQ.w[1] >> amount;
1233 } else
1234 CQ.w[0] = Q_high;
1235 CQ.w[1] = 0;
1236
1237 diff_expon += nzeros;
1238 } else {
1239 tdigit[0] = Q_low & 0x3ffffff;
1240 tdigit[1] = 0;
1241 QX = Q_low >> 26;
1242 QX32 = QX;
1243 nzeros = 0;
1244
1245 for (j = 0; QX32; j++, QX32 >>= 7) {
1246 k = (QX32 & 127);
1247 tdigit[0] += convert_table[j][k][0];
1248 tdigit[1] += convert_table[j][k][1];
1249 if (tdigit[0] >= 100000000) {
1250 tdigit[0] -= 100000000;
1251 tdigit[1]++;
1252 }
1253 }
1254
1255 if (tdigit[1] >= 100000000) {
1256 tdigit[1] -= 100000000;
1257 if (tdigit[1] >= 100000000)
1258 tdigit[1] -= 100000000;
1259 }
1260
1261 digit = tdigit[0];
1262 if (!digit && !tdigit[1])
1263 nzeros += 16;
1264 else {
1265 if (!digit) {
1266 nzeros += 8;
1267 digit = tdigit[1];
1268 }
1269 // decompose digit
1270 PD = (UINT64) digit *0x068DB8BBull;
1271 digit_h = (UINT32) (PD >> 40);
1272 //printf("i=%d, nz=%d, digit=%d (%d, %016I64x %016I64x)\n",i,nzeros,digit_h,digit,PD,digit_h);fflush(stdout);
1273 digit_low = digit - digit_h * 10000;
1274
1275 if (!digit_low)
1276 nzeros += 4;
1277 else
1278 digit_h = digit_low;
1279
1280 if (!(digit_h & 1))
1281 nzeros +=
1282 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
1283 (digit_h & 7));
1284 }
1285
1286 if (nzeros) {
1287 // get P*(2^M[extra_digits])/10^extra_digits
1288 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
1289
1290 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
1291 amount = recip_scale[nzeros];
1292 __shr_128 (CQ, Qh, amount);
1293 }
1294 diff_expon += nzeros;
1295
1296 }
1297 }
1298 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,
1299 pfpsf);
1300 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1301 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1302 #endif
1303 BID_RETURN (res);
1304 }
1305 #endif
1306
1307 if (diff_expon >= 0) {
1308 #ifdef IEEE_ROUND_NEAREST
1309 // rounding
1310 // 2*CA4 - CY
1311 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1312 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1313 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1314 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1315
1316 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
1317 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
1318
1319 CQ.w[0] += carry64;
1320 if (CQ.w[0] < carry64)
1321 CQ.w[1]++;
1322 #else
1323 #ifdef IEEE_ROUND_NEAREST_TIES_AWAY
1324 // rounding
1325 // 2*CA4 - CY
1326 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1327 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1328 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1329 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1330
1331 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
1332 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
1333
1334 CQ.w[0] += carry64;
1335 if (CQ.w[0] < carry64)
1336 CQ.w[1]++;
1337 #else
1338 rmode = rnd_mode;
1339 if (sign_x ^ sign_y && (unsigned) (rmode - 1) < 2)
1340 rmode = 3 - rmode;
1341 switch (rmode) {
1342 case ROUNDING_TO_NEAREST: // round to nearest code
1343 // rounding
1344 // 2*CA4 - CY
1345 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1346 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1347 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1348 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1349 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
1350 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
1351 CQ.w[0] += carry64;
1352 if (CQ.w[0] < carry64)
1353 CQ.w[1]++;
1354 break;
1355 case ROUNDING_TIES_AWAY:
1356 // rounding
1357 // 2*CA4 - CY
1358 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1359 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1360 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1361 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1362 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
1363 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
1364 CQ.w[0] += carry64;
1365 if (CQ.w[0] < carry64)
1366 CQ.w[1]++;
1367 break;
1368 case ROUNDING_DOWN:
1369 case ROUNDING_TO_ZERO:
1370 break;
1371 default: // rounding up
1372 CQ.w[0]++;
1373 if (!CQ.w[0])
1374 CQ.w[1]++;
1375 break;
1376 }
1377 #endif
1378 #endif
1379
1380 } else {
1381 #ifdef SET_STATUS_FLAGS
1382 if (CA4.w[0] || CA4.w[1]) {
1383 // set status flags
1384 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
1385 }
1386 #endif
1387 handle_UF_128_rem (&res, sign_x ^ sign_y, diff_expon, CQ,
1388 CA4.w[1] | CA4.w[0], &rnd_mode, pfpsf);
1389 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1390 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1391 #endif
1392 BID_RETURN (res);
1393 }
1394
1395 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode, pfpsf);
1396 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1397 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1398 #endif
1399 BID_RETURN (res);
1400
1401 }
1402
1403
1404 BID128_FUNCTION_ARG128_ARGTYPE2 (bid128qd_div, x, UINT64, y)
1405 UINT256 CA4, CA4r, P256;
1406 UINT128 CX, CY, T128, CQ, CR, CA, TP128, Qh, Ql, res;
1407 UINT64 sign_x, sign_y, T, carry64, D, Q_high, Q_low, QX, PD,
1408 valid_y;
1409 int_float fx, fy, f64;
1410 UINT32 QX32, tdigit[3], digit, digit_h, digit_low;
1411 int exponent_x, exponent_y, bin_index, bin_expon, diff_expon, ed2,
1412 digits_q, amount;
1413 int nzeros, i, j, k, d5, rmode;
1414 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1415 fexcept_t binaryflags = 0;
1416 #endif
1417
1418
1419 valid_y = unpack_BID64 (&sign_y, &exponent_y, &CY.w[0], y);
1420 // unpack arguments, check for NaN or Infinity
1421 if (!unpack_BID128_value (&sign_x, &exponent_x, &CX, x)) {
1422 // test if x is NaN
1423 if ((x.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
1424 #ifdef SET_STATUS_FLAGS
1425 if ((x.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull || // sNaN
1426 (y & 0x7e00000000000000ull) == 0x7e00000000000000ull)
1427 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1428 #endif
1429 res.w[1] = (CX.w[1]) & QUIET_MASK64;
1430 res.w[0] = CX.w[0];
1431 BID_RETURN (res);
1432 }
1433 // x is Infinity?
1434 if ((x.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
1435 // check if y is Inf.
1436 if (((y & 0x7c00000000000000ull) == 0x7800000000000000ull))
1437 // return NaN
1438 {
1439 #ifdef SET_STATUS_FLAGS
1440 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1441 #endif
1442 res.w[1] = 0x7c00000000000000ull;
1443 res.w[0] = 0;
1444 BID_RETURN (res);
1445 }
1446 // y is NaN?
1447 if (((y & 0x7c00000000000000ull) != 0x7c00000000000000ull))
1448 // return NaN
1449 {
1450 // return +/-Inf
1451 res.w[1] = ((x.w[1] ^ y) & 0x8000000000000000ull) |
1452 0x7800000000000000ull;
1453 res.w[0] = 0;
1454 BID_RETURN (res);
1455 }
1456 }
1457 // x is 0
1458 if ((y & 0x7800000000000000ull) < 0x7800000000000000ull) {
1459 if (!CY.w[0]) {
1460 #ifdef SET_STATUS_FLAGS
1461 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1462 #endif
1463 // x=y=0, return NaN
1464 res.w[1] = 0x7c00000000000000ull;
1465 res.w[0] = 0;
1466 BID_RETURN (res);
1467 }
1468 // return 0
1469 res.w[1] = (x.w[1] ^ y) & 0x8000000000000000ull;
1470 exponent_x = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS;
1471 if (exponent_x > DECIMAL_MAX_EXPON_128)
1472 exponent_x = DECIMAL_MAX_EXPON_128;
1473 else if (exponent_x < 0)
1474 exponent_x = 0;
1475 res.w[1] |= (((UINT64) exponent_x) << 49);
1476 res.w[0] = 0;
1477 BID_RETURN (res);
1478 }
1479 }
1480 CY.w[1] = 0;
1481 if (!valid_y) {
1482 // y is Inf. or NaN
1483
1484 // test if y is NaN
1485 if ((y & NAN_MASK64) == NAN_MASK64) {
1486 #ifdef SET_STATUS_FLAGS
1487 if ((y & SNAN_MASK64) == SNAN_MASK64) // sNaN
1488 __set_status_flags (pfpsf, INVALID_EXCEPTION);
1489 #endif
1490 res.w[0] = (CY.w[0] & 0x0003ffffffffffffull);
1491 __mul_64x64_to_128 (res, res.w[0], power10_table_128[18].w[0]);
1492 res.w[1] |= ((CY.w[0]) & 0xfc00000000000000ull);
1493 BID_RETURN (res);
1494 }
1495 // y is Infinity?
1496 if ((y & INFINITY_MASK64) == INFINITY_MASK64) {
1497 // return +/-0
1498 res.w[1] = ((x.w[1] ^ y) & 0x8000000000000000ull);
1499 res.w[0] = 0;
1500 BID_RETURN (res);
1501 }
1502 // y is 0
1503 #ifdef SET_STATUS_FLAGS
1504 __set_status_flags (pfpsf, ZERO_DIVIDE_EXCEPTION);
1505 #endif
1506 res.w[1] = (sign_x ^ sign_y) | INFINITY_MASK64;
1507 res.w[0] = 0;
1508 BID_RETURN (res);
1509 }
1510 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1511 (void) fegetexceptflag (&binaryflags, FE_ALL_FLAGS);
1512 #endif
1513 diff_expon = exponent_x - exponent_y + DECIMAL_EXPONENT_BIAS;
1514
1515 if (__unsigned_compare_gt_128 (CY, CX)) {
1516 // CX < CY
1517
1518 // 2^64
1519 f64.i = 0x5f800000;
1520
1521 // fx ~ CX, fy ~ CY
1522 fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
1523 fy.d = (float) CY.w[1] * f64.d + (float) CY.w[0];
1524 // expon_cy - expon_cx
1525 bin_index = (fy.i - fx.i) >> 23;
1526
1527 if (CX.w[1]) {
1528 T = power10_index_binexp_128[bin_index].w[0];
1529 __mul_64x128_short (CA, T, CX);
1530 } else {
1531 T128 = power10_index_binexp_128[bin_index];
1532 __mul_64x128_short (CA, CX.w[0], T128);
1533 }
1534
1535 ed2 = 33;
1536 if (__unsigned_compare_gt_128 (CY, CA))
1537 ed2++;
1538
1539 T128 = power10_table_128[ed2];
1540 __mul_128x128_to_256 (CA4, CA, T128);
1541
1542 ed2 += estimate_decimal_digits[bin_index];
1543 CQ.w[0] = CQ.w[1] = 0;
1544 diff_expon = diff_expon - ed2;
1545
1546 } else {
1547 // get CQ = CX/CY
1548 __div_128_by_128 (&CQ, &CR, CX, CY);
1549
1550 if (!CR.w[1] && !CR.w[0]) {
1551 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,
1552 pfpsf);
1553 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1554 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1555 #endif
1556 BID_RETURN (res);
1557 }
1558 // get number of decimal digits in CQ
1559 // 2^64
1560 f64.i = 0x5f800000;
1561 fx.d = (float) CQ.w[1] * f64.d + (float) CQ.w[0];
1562 // binary expon. of CQ
1563 bin_expon = (fx.i - 0x3f800000) >> 23;
1564
1565 digits_q = estimate_decimal_digits[bin_expon];
1566 TP128.w[0] = power10_index_binexp_128[bin_expon].w[0];
1567 TP128.w[1] = power10_index_binexp_128[bin_expon].w[1];
1568 if (__unsigned_compare_ge_128 (CQ, TP128))
1569 digits_q++;
1570
1571 ed2 = 34 - digits_q;
1572 T128.w[0] = power10_table_128[ed2].w[0];
1573 T128.w[1] = power10_table_128[ed2].w[1];
1574 __mul_128x128_to_256 (CA4, CR, T128);
1575 diff_expon = diff_expon - ed2;
1576 __mul_128x128_low (CQ, CQ, T128);
1577
1578 }
1579
1580 __div_256_by_128 (&CQ, &CA4, CY);
1581
1582
1583 #ifdef SET_STATUS_FLAGS
1584 if (CA4.w[0] || CA4.w[1]) {
1585 // set status flags
1586 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
1587 }
1588 #ifndef LEAVE_TRAILING_ZEROS
1589 else
1590 #endif
1591 #else
1592 #ifndef LEAVE_TRAILING_ZEROS
1593 if (!CA4.w[0] && !CA4.w[1])
1594 #endif
1595 #endif
1596 #ifndef LEAVE_TRAILING_ZEROS
1597 // check whether result is exact
1598 {
1599 // check whether CX, CY are short
1600 if (!CX.w[1] && !CY.w[1] && (CX.w[0] <= 1024) && (CY.w[0] <= 1024)) {
1601 i = (int) CY.w[0] - 1;
1602 j = (int) CX.w[0] - 1;
1603 // difference in powers of 2 factors for Y and X
1604 nzeros = ed2 - factors[i][0] + factors[j][0];
1605 // difference in powers of 5 factors
1606 d5 = ed2 - factors[i][1] + factors[j][1];
1607 if (d5 < nzeros)
1608 nzeros = d5;
1609 // get P*(2^M[extra_digits])/10^extra_digits
1610 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
1611 //__mul_128x128_to_256(P256, CQ, reciprocals10_128[nzeros]);Qh.w[1]=P256.w[3];Qh.w[0]=P256.w[2];
1612
1613 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
1614 amount = recip_scale[nzeros];
1615 __shr_128_long (CQ, Qh, amount);
1616
1617 diff_expon += nzeros;
1618 } else {
1619 // decompose Q as Qh*10^17 + Ql
1620 //T128 = reciprocals10_128[17];
1621 T128.w[0] = 0x44909befeb9fad49ull;
1622 T128.w[1] = 0x000b877aa3236a4bull;
1623 __mul_128x128_to_256 (P256, CQ, T128);
1624 //amount = recip_scale[17];
1625 Q_high = (P256.w[2] >> 44) | (P256.w[3] << (64 - 44));
1626 Q_low = CQ.w[0] - Q_high * 100000000000000000ull;
1627
1628 if (!Q_low) {
1629 diff_expon += 17;
1630
1631 tdigit[0] = Q_high & 0x3ffffff;
1632 tdigit[1] = 0;
1633 QX = Q_high >> 26;
1634 QX32 = QX;
1635 nzeros = 0;
1636
1637 for (j = 0; QX32; j++, QX32 >>= 7) {
1638 k = (QX32 & 127);
1639 tdigit[0] += convert_table[j][k][0];
1640 tdigit[1] += convert_table[j][k][1];
1641 if (tdigit[0] >= 100000000) {
1642 tdigit[0] -= 100000000;
1643 tdigit[1]++;
1644 }
1645 }
1646
1647
1648 if (tdigit[1] >= 100000000) {
1649 tdigit[1] -= 100000000;
1650 if (tdigit[1] >= 100000000)
1651 tdigit[1] -= 100000000;
1652 }
1653
1654 digit = tdigit[0];
1655 if (!digit && !tdigit[1])
1656 nzeros += 16;
1657 else {
1658 if (!digit) {
1659 nzeros += 8;
1660 digit = tdigit[1];
1661 }
1662 // decompose digit
1663 PD = (UINT64) digit *0x068DB8BBull;
1664 digit_h = (UINT32) (PD >> 40);
1665 digit_low = digit - digit_h * 10000;
1666
1667 if (!digit_low)
1668 nzeros += 4;
1669 else
1670 digit_h = digit_low;
1671
1672 if (!(digit_h & 1))
1673 nzeros +=
1674 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
1675 (digit_h & 7));
1676 }
1677
1678 if (nzeros) {
1679 __mul_64x64_to_128 (CQ, Q_high, reciprocals10_64[nzeros]);
1680
1681 // now get P/10^extra_digits: shift C64 right by M[extra_digits]-64
1682 amount = short_recip_scale[nzeros];
1683 CQ.w[0] = CQ.w[1] >> amount;
1684 } else
1685 CQ.w[0] = Q_high;
1686 CQ.w[1] = 0;
1687
1688 diff_expon += nzeros;
1689 } else {
1690 tdigit[0] = Q_low & 0x3ffffff;
1691 tdigit[1] = 0;
1692 QX = Q_low >> 26;
1693 QX32 = QX;
1694 nzeros = 0;
1695
1696 for (j = 0; QX32; j++, QX32 >>= 7) {
1697 k = (QX32 & 127);
1698 tdigit[0] += convert_table[j][k][0];
1699 tdigit[1] += convert_table[j][k][1];
1700 if (tdigit[0] >= 100000000) {
1701 tdigit[0] -= 100000000;
1702 tdigit[1]++;
1703 }
1704 }
1705
1706 if (tdigit[1] >= 100000000) {
1707 tdigit[1] -= 100000000;
1708 if (tdigit[1] >= 100000000)
1709 tdigit[1] -= 100000000;
1710 }
1711
1712 digit = tdigit[0];
1713 if (!digit && !tdigit[1])
1714 nzeros += 16;
1715 else {
1716 if (!digit) {
1717 nzeros += 8;
1718 digit = tdigit[1];
1719 }
1720 // decompose digit
1721 PD = (UINT64) digit *0x068DB8BBull;
1722 digit_h = (UINT32) (PD >> 40);
1723 digit_low = digit - digit_h * 10000;
1724
1725 if (!digit_low)
1726 nzeros += 4;
1727 else
1728 digit_h = digit_low;
1729
1730 if (!(digit_h & 1))
1731 nzeros +=
1732 3 & (UINT32) (packed_10000_zeros[digit_h >> 3] >>
1733 (digit_h & 7));
1734 }
1735
1736 if (nzeros) {
1737 // get P*(2^M[extra_digits])/10^extra_digits
1738 __mul_128x128_full (Qh, Ql, CQ, reciprocals10_128[nzeros]);
1739
1740 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
1741 amount = recip_scale[nzeros];
1742 __shr_128 (CQ, Qh, amount);
1743 }
1744 diff_expon += nzeros;
1745
1746 }
1747 }
1748 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode,pfpsf);
1749 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1750 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1751 #endif
1752 BID_RETURN (res);
1753 }
1754 #endif
1755
1756 if (diff_expon >= 0) {
1757 #ifdef IEEE_ROUND_NEAREST
1758 // rounding
1759 // 2*CA4 - CY
1760 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1761 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1762 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1763 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1764
1765 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
1766 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
1767
1768 CQ.w[0] += carry64;
1769 if (CQ.w[0] < carry64)
1770 CQ.w[1]++;
1771 #else
1772 #ifdef IEEE_ROUND_NEAREST_TIES_AWAY
1773 // rounding
1774 // 2*CA4 - CY
1775 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1776 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1777 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1778 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1779
1780 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
1781 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
1782
1783 CQ.w[0] += carry64;
1784 if (CQ.w[0] < carry64)
1785 CQ.w[1]++;
1786 #else
1787 rmode = rnd_mode;
1788 if (sign_x ^ sign_y && (unsigned) (rmode - 1) < 2)
1789 rmode = 3 - rmode;
1790 switch (rmode) {
1791 case ROUNDING_TO_NEAREST: // round to nearest code
1792 // rounding
1793 // 2*CA4 - CY
1794 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1795 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1796 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1797 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1798 D = (CA4r.w[1] | CA4r.w[0]) ? 1 : 0;
1799 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) & ((CQ.w[0]) | D);
1800 CQ.w[0] += carry64;
1801 if (CQ.w[0] < carry64)
1802 CQ.w[1]++;
1803 break;
1804 case ROUNDING_TIES_AWAY:
1805 // rounding
1806 // 2*CA4 - CY
1807 CA4r.w[1] = (CA4.w[1] + CA4.w[1]) | (CA4.w[0] >> 63);
1808 CA4r.w[0] = CA4.w[0] + CA4.w[0];
1809 __sub_borrow_out (CA4r.w[0], carry64, CA4r.w[0], CY.w[0]);
1810 CA4r.w[1] = CA4r.w[1] - CY.w[1] - carry64;
1811 D = (CA4r.w[1] | CA4r.w[0]) ? 0 : 1;
1812 carry64 = (1 + (((SINT64) CA4r.w[1]) >> 63)) | D;
1813 CQ.w[0] += carry64;
1814 if (CQ.w[0] < carry64)
1815 CQ.w[1]++;
1816 break;
1817 case ROUNDING_DOWN:
1818 case ROUNDING_TO_ZERO:
1819 break;
1820 default: // rounding up
1821 CQ.w[0]++;
1822 if (!CQ.w[0])
1823 CQ.w[1]++;
1824 break;
1825 }
1826 #endif
1827 #endif
1828
1829 } else {
1830 #ifdef SET_STATUS_FLAGS
1831 if (CA4.w[0] || CA4.w[1]) {
1832 // set status flags
1833 __set_status_flags (pfpsf, INEXACT_EXCEPTION);
1834 }
1835 #endif
1836 handle_UF_128_rem (&res, sign_x ^ sign_y, diff_expon, CQ,
1837 CA4.w[1] | CA4.w[0], &rnd_mode, pfpsf);
1838 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1839 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1840 #endif
1841 BID_RETURN (res);
1842
1843 }
1844
1845 get_BID128 (&res, sign_x ^ sign_y, diff_expon, CQ, &rnd_mode, pfpsf);
1846 #ifdef UNCHANGED_BINARY_STATUS_FLAGS
1847 (void) fesetexceptflag (&binaryflags, FE_ALL_FLAGS);
1848 #endif
1849 BID_RETURN (res);
1850
1851 }