* gcc-interface/decl.c (gnat_to_gnu_field): Do not set the alignment
[official-gcc.git] / libgcc / config / libbid / bid64_rem.c
blob4ca3864cf2cfd3f72ff190b0845a4cda29e6554b
1 /* Copyright (C) 2007-2017 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
8 version.
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.
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 /*****************************************************************************
25 * BID64 remainder
26 *****************************************************************************
28 * Algorithm description:
30 * if(exponent_x < exponent_y)
31 * scale coefficient_y so exponents are aligned
32 * perform coefficient divide (64-bit integer divide), unless
33 * coefficient_y is longer than 64 bits (clearly larger
34 * than coefficient_x)
35 * else // exponent_x > exponent_y
36 * use a loop to scale coefficient_x to 18_digits, divide by
37 * coefficient_y (64-bit integer divide), calculate remainder
38 * as new_coefficient_x and repeat until final remainder is obtained
39 * (when new_exponent_x < exponent_y)
41 ****************************************************************************/
43 #include "bid_internal.h"
45 #define MAX_FORMAT_DIGITS 16
46 #define DECIMAL_EXPONENT_BIAS 398
47 #define MASK_BINARY_EXPONENT 0x7ff0000000000000ull
48 #define BINARY_EXPONENT_BIAS 0x3ff
49 #define UPPER_EXPON_LIMIT 51
51 #if DECIMAL_CALL_BY_REFERENCE
53 void
54 bid64_rem (UINT64 * pres, UINT64 * px,
55 UINT64 *
56 py _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
57 UINT64 x, y;
58 #else
60 UINT64
61 bid64_rem (UINT64 x,
62 UINT64 y _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
63 #endif
64 UINT128 CY;
65 UINT64 sign_x, sign_y, coefficient_x, coefficient_y, res;
66 UINT64 Q, R, R2, T, valid_y, valid_x;
67 int_float tempx;
68 int exponent_x, exponent_y, bin_expon, e_scale;
69 int digits_x, diff_expon;
71 #if DECIMAL_CALL_BY_REFERENCE
72 x = *px;
73 y = *py;
74 #endif
76 valid_y = unpack_BID64 (&sign_y, &exponent_y, &coefficient_y, y);
77 valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x);
79 // unpack arguments, check for NaN or Infinity
80 if (!valid_x) {
81 // x is Inf. or NaN or 0
82 #ifdef SET_STATUS_FLAGS
83 if ((y & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
84 __set_status_flags (pfpsf, INVALID_EXCEPTION);
85 #endif
87 // test if x is NaN
88 if ((x & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
89 #ifdef SET_STATUS_FLAGS
90 if (((x & SNAN_MASK64) == SNAN_MASK64))
91 __set_status_flags (pfpsf, INVALID_EXCEPTION);
92 #endif
93 res = coefficient_x & QUIET_MASK64;;
94 BID_RETURN (res);
96 // x is Infinity?
97 if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
98 if (((y & NAN_MASK64) != NAN_MASK64)) {
99 #ifdef SET_STATUS_FLAGS
100 __set_status_flags (pfpsf, INVALID_EXCEPTION);
101 #endif
102 // return NaN
103 res = 0x7c00000000000000ull;
104 BID_RETURN (res);
107 // x is 0
108 // return x if y != 0
109 if (((y & 0x7800000000000000ull) < 0x7800000000000000ull) &&
110 coefficient_y) {
111 if ((y & 0x6000000000000000ull) == 0x6000000000000000ull)
112 exponent_y = (y >> 51) & 0x3ff;
113 else
114 exponent_y = (y >> 53) & 0x3ff;
116 if (exponent_y < exponent_x)
117 exponent_x = exponent_y;
119 x = exponent_x;
120 x <<= 53;
122 res = x | sign_x;
123 BID_RETURN (res);
127 if (!valid_y) {
128 // y is Inf. or NaN
130 // test if y is NaN
131 if ((y & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
132 #ifdef SET_STATUS_FLAGS
133 if (((y & SNAN_MASK64) == SNAN_MASK64))
134 __set_status_flags (pfpsf, INVALID_EXCEPTION);
135 #endif
136 res = coefficient_y & QUIET_MASK64;;
137 BID_RETURN (res);
139 // y is Infinity?
140 if ((y & 0x7800000000000000ull) == 0x7800000000000000ull) {
141 res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x);
142 BID_RETURN (res);
144 // y is 0, return NaN
146 #ifdef SET_STATUS_FLAGS
147 __set_status_flags (pfpsf, INVALID_EXCEPTION);
148 #endif
149 res = 0x7c00000000000000ull;
150 BID_RETURN (res);
155 diff_expon = exponent_x - exponent_y;
156 if (diff_expon <= 0) {
157 diff_expon = -diff_expon;
159 if (diff_expon > 16) {
160 // |x|<|y| in this case
161 res = x;
162 BID_RETURN (res);
164 // set exponent of y to exponent_x, scale coefficient_y
165 T = power10_table_128[diff_expon].w[0];
166 __mul_64x64_to_128 (CY, coefficient_y, T);
168 if (CY.w[1] || CY.w[0] > (coefficient_x << 1)) {
169 res = x;
170 BID_RETURN (res);
173 Q = coefficient_x / CY.w[0];
174 R = coefficient_x - Q * CY.w[0];
176 R2 = R + R;
177 if (R2 > CY.w[0] || (R2 == CY.w[0] && (Q & 1))) {
178 R = CY.w[0] - R;
179 sign_x ^= 0x8000000000000000ull;
182 res = very_fast_get_BID64 (sign_x, exponent_x, R);
183 BID_RETURN (res);
187 while (diff_expon > 0) {
188 // get number of digits in coeff_x
189 tempx.d = (float) coefficient_x;
190 bin_expon = ((tempx.i >> 23) & 0xff) - 0x7f;
191 digits_x = estimate_decimal_digits[bin_expon];
192 // will not use this test, dividend will have 18 or 19 digits
193 //if(coefficient_x >= power10_table_128[digits_x].w[0])
194 // digits_x++;
196 e_scale = 18 - digits_x;
197 if (diff_expon >= e_scale) {
198 diff_expon -= e_scale;
199 } else {
200 e_scale = diff_expon;
201 diff_expon = 0;
204 // scale dividend to 18 or 19 digits
205 coefficient_x *= power10_table_128[e_scale].w[0];
207 // quotient
208 Q = coefficient_x / coefficient_y;
209 // remainder
210 coefficient_x -= Q * coefficient_y;
212 // check for remainder == 0
213 if (!coefficient_x) {
214 res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, 0);
215 BID_RETURN (res);
219 R2 = coefficient_x + coefficient_x;
220 if (R2 > coefficient_y || (R2 == coefficient_y && (Q & 1))) {
221 coefficient_x = coefficient_y - coefficient_x;
222 sign_x ^= 0x8000000000000000ull;
225 res = very_fast_get_BID64 (sign_x, exponent_y, coefficient_x);
226 BID_RETURN (res);