Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 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
.  */
23
 
24
#define BID_128RES
25
#include "bid_internal.h"
26
 
27
/*****************************************************************************
28
 *  BID128 nextup
29
 ****************************************************************************/
30
 
31
#if DECIMAL_CALL_BY_REFERENCE
32
void
33
bid128_nextup (UINT128 * pres,
34
	       UINT128 *
35
	       px _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
36
  UINT128 x = *px;
37
#else
38
UINT128
39
bid128_nextup (UINT128 x _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
40
	       _EXC_INFO_PARAM) {
41
#endif
42
 
43
  UINT128 res;
44
  UINT64 x_sign;
45
  UINT64 x_exp;
46
  int exp;
47
  BID_UI64DOUBLE tmp1;
48
  int x_nr_bits;
49
  int q1, ind;
50
  UINT128 C1;			// C1.w[1], C1.w[0] represent x_signif_hi, x_signif_lo (UINT64)
51
 
52
  BID_SWAP128 (x);
53
  // unpack the argument
54
  x_sign = x.w[1] & MASK_SIGN;	// 0 for positive, MASK_SIGN for negative
55
  C1.w[1] = x.w[1] & MASK_COEFF;
56
  C1.w[0] = x.w[0];
57
 
58
  // check for NaN or Infinity
59
  if ((x.w[1] & MASK_SPECIAL) == MASK_SPECIAL) {
60
    // x is special
61
    if ((x.w[1] & MASK_NAN) == MASK_NAN) {	// x is NAN
62
      // if x = NaN, then res = Q (x)
63
      // check first for non-canonical NaN payload
64
      if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
65
	  (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull)
66
	   && (x.w[0] > 0x38c15b09ffffffffull))) {
67
	x.w[1] = x.w[1] & 0xffffc00000000000ull;
68
	x.w[0] = 0x0ull;
69
      }
70
      if ((x.w[1] & MASK_SNAN) == MASK_SNAN) {	// x is SNAN
71
	// set invalid flag
72
	*pfpsf |= INVALID_EXCEPTION;
73
	// return quiet (x)
74
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out also G[6]-G[16]
75
	res.w[0] = x.w[0];
76
      } else {	// x is QNaN
77
	// return x
78
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out G[6]-G[16]
79
	res.w[0] = x.w[0];
80
      }
81
    } else {	// x is not NaN, so it must be infinity
82
      if (!x_sign) {	// x is +inf
83
	res.w[1] = 0x7800000000000000ull;	// +inf
84
	res.w[0] = 0x0000000000000000ull;
85
      } else {	// x is -inf
86
	res.w[1] = 0xdfffed09bead87c0ull;	// -MAXFP = -999...99 * 10^emax
87
	res.w[0] = 0x378d8e63ffffffffull;
88
      }
89
    }
90
    BID_RETURN (res);
91
  }
92
  // check for non-canonical values (treated as zero)
93
  if ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) {	// G0_G1=11
94
    // non-canonical
95
    x_exp = (x.w[1] << 2) & MASK_EXP;	// biased and shifted left 49 bits
96
    C1.w[1] = 0;	// significand high
97
    C1.w[0] = 0;	// significand low
98
  } else {	// G0_G1 != 11
99
    x_exp = x.w[1] & MASK_EXP;	// biased and shifted left 49 bits
100
    if (C1.w[1] > 0x0001ed09bead87c0ull ||
101
	(C1.w[1] == 0x0001ed09bead87c0ull
102
	 && C1.w[0] > 0x378d8e63ffffffffull)) {
103
      // x is non-canonical if coefficient is larger than 10^34 -1
104
      C1.w[1] = 0;
105
      C1.w[0] = 0;
106
    } else {	// canonical
107
      ;
108
    }
109
  }
110
 
111
  if ((C1.w[1] == 0x0ull) && (C1.w[0] == 0x0ull)) {
112
    // x is +/-0
113
    res.w[1] = 0x0000000000000000ull;	// +1 * 10^emin
114
    res.w[0] = 0x0000000000000001ull;
115
  } else {	// x is not special and is not zero
116
    if (x.w[1] == 0x5fffed09bead87c0ull
117
	&& x.w[0] == 0x378d8e63ffffffffull) {
118
      // x = +MAXFP = 999...99 * 10^emax
119
      res.w[1] = 0x7800000000000000ull;	// +inf
120
      res.w[0] = 0x0000000000000000ull;
121
    } else if (x.w[1] == 0x8000000000000000ull
122
	       && x.w[0] == 0x0000000000000001ull) {
123
      // x = -MINFP = 1...99 * 10^emin
124
      res.w[1] = 0x8000000000000000ull;	// -0
125
      res.w[0] = 0x0000000000000000ull;
126
    } else {	// -MAXFP <= x <= -MINFP - 1 ulp OR MINFP <= x <= MAXFP - 1 ulp
127
      // can add/subtract 1 ulp to the significand
128
 
129
      // Note: we could check here if x >= 10^34 to speed up the case q1 = 34
130
      // q1 = nr. of decimal digits in x
131
      // determine first the nr. of bits in x
132
      if (C1.w[1] == 0) {
133
	if (C1.w[0] >= 0x0020000000000000ull) {	// x >= 2^53
134
	  // split the 64-bit value in two 32-bit halves to avoid rnd errors
135
	  if (C1.w[0] >= 0x0000000100000000ull) {	// x >= 2^32
136
	    tmp1.d = (double) (C1.w[0] >> 32);	// exact conversion
137
	    x_nr_bits =
138
	      33 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) -
139
		    0x3ff);
140
	  } else {	// x < 2^32
141
	    tmp1.d = (double) (C1.w[0]);	// exact conversion
142
	    x_nr_bits =
143
	      1 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) -
144
		   0x3ff);
145
	  }
146
	} else {	// if x < 2^53
147
	  tmp1.d = (double) C1.w[0];	// exact conversion
148
	  x_nr_bits =
149
	    1 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) - 0x3ff);
150
	}
151
      } else {	// C1.w[1] != 0 => nr. bits = 64 + nr_bits (C1.w[1])
152
	tmp1.d = (double) C1.w[1];	// exact conversion
153
	x_nr_bits =
154
	  65 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) - 0x3ff);
155
      }
156
      q1 = nr_digits[x_nr_bits - 1].digits;
157
      if (q1 == 0) {
158
	q1 = nr_digits[x_nr_bits - 1].digits1;
159
	if (C1.w[1] > nr_digits[x_nr_bits - 1].threshold_hi
160
	    || (C1.w[1] == nr_digits[x_nr_bits - 1].threshold_hi
161
		&& C1.w[0] >= nr_digits[x_nr_bits - 1].threshold_lo))
162
	  q1++;
163
      }
164
      // if q1 < P34 then pad the significand with zeros
165
      if (q1 < P34) {
166
	exp = (x_exp >> 49) - 6176;
167
	if (exp + 6176 > P34 - q1) {
168
	  ind = P34 - q1;	// 1 <= ind <= P34 - 1
169
	  // pad with P34 - q1 zeros, until exponent = emin
170
	  // C1 = C1 * 10^ind
171
	  if (q1 <= 19) {	// 64-bit C1
172
	    if (ind <= 19) {	// 64-bit 10^ind and 64-bit C1
173
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
174
	    } else {	// 128-bit 10^ind and 64-bit C1
175
	      __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
176
	    }
177
	  } else {	// C1 is (most likely) 128-bit
178
	    if (ind <= 14) {	// 64-bit 10^ind and 128-bit C1 (most likely)
179
	      __mul_128x64_to_128 (C1, ten2k64[ind], C1);
180
	    } else if (ind <= 19) {	// 64-bit 10^ind and 64-bit C1 (q1 <= 19)
181
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
182
	    } else {	// 128-bit 10^ind and 64-bit C1 (C1 must be 64-bit)
183
	      __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
184
	    }
185
	  }
186
	  x_exp = x_exp - ((UINT64) ind << 49);
187
	} else {	// pad with zeros until the exponent reaches emin
188
	  ind = exp + 6176;
189
	  // C1 = C1 * 10^ind
190
	  if (ind <= 19) {	// 1 <= P34 - q1 <= 19 <=> 15 <= q1 <= 33
191
	    if (q1 <= 19) {	// 64-bit C1, 64-bit 10^ind
192
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
193
	    } else {	// 20 <= q1 <= 33 => 128-bit C1, 64-bit 10^ind
194
	      __mul_128x64_to_128 (C1, ten2k64[ind], C1);
195
	    }
196
	  } else {	// if 20 <= P34 - q1 <= 33 <=> 1 <= q1 <= 14 =>
197
	    // 64-bit C1, 128-bit 10^ind
198
	    __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
199
	  }
200
	  x_exp = EXP_MIN;
201
	}
202
      }
203
      if (!x_sign) {	// x > 0
204
	// add 1 ulp (add 1 to the significand)
205
	C1.w[0]++;
206
	if (C1.w[0] == 0)
207
	  C1.w[1]++;
208
	if (C1.w[1] == 0x0001ed09bead87c0ull && C1.w[0] == 0x378d8e6400000000ull) {	// if  C1 = 10^34
209
	  C1.w[1] = 0x0000314dc6448d93ull;	// C1 = 10^33
210
	  C1.w[0] = 0x38c15b0a00000000ull;
211
	  x_exp = x_exp + EXP_P1;
212
	}
213
      } else {	// x < 0
214
	// subtract 1 ulp (subtract 1 from the significand)
215
	C1.w[0]--;
216
	if (C1.w[0] == 0xffffffffffffffffull)
217
	  C1.w[1]--;
218
	if (x_exp != 0 && C1.w[1] == 0x0000314dc6448d93ull && C1.w[0] == 0x38c15b09ffffffffull) {	// if  C1 = 10^33 - 1
219
	  C1.w[1] = 0x0001ed09bead87c0ull;	// C1 = 10^34 - 1
220
	  C1.w[0] = 0x378d8e63ffffffffull;
221
	  x_exp = x_exp - EXP_P1;
222
	}
223
      }
224
      // assemble the result
225
      res.w[1] = x_sign | x_exp | C1.w[1];
226
      res.w[0] = C1.w[0];
227
    }	// end -MAXFP <= x <= -MINFP - 1 ulp OR MINFP <= x <= MAXFP - 1 ulp
228
  }	// end x is not special and is not zero
229
  BID_RETURN (res);
230
}
231
 
232
/*****************************************************************************
233
 *  BID128 nextdown
234
 ****************************************************************************/
235
 
236
#if DECIMAL_CALL_BY_REFERENCE
237
void
238
bid128_nextdown (UINT128 * pres,
239
		 UINT128 *
240
		 px _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
241
  UINT128 x = *px;
242
#else
243
UINT128
244
bid128_nextdown (UINT128 x _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
245
		 _EXC_INFO_PARAM) {
246
#endif
247
 
248
  UINT128 res;
249
  UINT64 x_sign;
250
  UINT64 x_exp;
251
  int exp;
252
  BID_UI64DOUBLE tmp1;
253
  int x_nr_bits;
254
  int q1, ind;
255
  UINT128 C1;			// C1.w[1], C1.w[0] represent x_signif_hi, x_signif_lo (UINT64)
256
 
257
  BID_SWAP128 (x);
258
  // unpack the argument
259
  x_sign = x.w[1] & MASK_SIGN;	// 0 for positive, MASK_SIGN for negative
260
  C1.w[1] = x.w[1] & MASK_COEFF;
261
  C1.w[0] = x.w[0];
262
 
263
  // check for NaN or Infinity
264
  if ((x.w[1] & MASK_SPECIAL) == MASK_SPECIAL) {
265
    // x is special
266
    if ((x.w[1] & MASK_NAN) == MASK_NAN) {	// x is NAN
267
      // if x = NaN, then res = Q (x)
268
      // check first for non-canonical NaN payload
269
      if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
270
	  (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull)
271
	   && (x.w[0] > 0x38c15b09ffffffffull))) {
272
	x.w[1] = x.w[1] & 0xffffc00000000000ull;
273
	x.w[0] = 0x0ull;
274
      }
275
      if ((x.w[1] & MASK_SNAN) == MASK_SNAN) {	// x is SNAN
276
	// set invalid flag
277
	*pfpsf |= INVALID_EXCEPTION;
278
	// return quiet (x)
279
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out also G[6]-G[16]
280
	res.w[0] = x.w[0];
281
      } else {	// x is QNaN
282
	// return x
283
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out G[6]-G[16]
284
	res.w[0] = x.w[0];
285
      }
286
    } else {	// x is not NaN, so it must be infinity
287
      if (!x_sign) {	// x is +inf
288
	res.w[1] = 0x5fffed09bead87c0ull;	// +MAXFP = +999...99 * 10^emax
289
	res.w[0] = 0x378d8e63ffffffffull;
290
      } else {	// x is -inf
291
	res.w[1] = 0xf800000000000000ull;	// -inf
292
	res.w[0] = 0x0000000000000000ull;
293
      }
294
    }
295
    BID_RETURN (res);
296
  }
297
  // check for non-canonical values (treated as zero)
298
  if ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) {	// G0_G1=11
299
    // non-canonical
300
    x_exp = (x.w[1] << 2) & MASK_EXP;	// biased and shifted left 49 bits
301
    C1.w[1] = 0;	// significand high
302
    C1.w[0] = 0;	// significand low
303
  } else {	// G0_G1 != 11
304
    x_exp = x.w[1] & MASK_EXP;	// biased and shifted left 49 bits
305
    if (C1.w[1] > 0x0001ed09bead87c0ull ||
306
	(C1.w[1] == 0x0001ed09bead87c0ull
307
	 && C1.w[0] > 0x378d8e63ffffffffull)) {
308
      // x is non-canonical if coefficient is larger than 10^34 -1
309
      C1.w[1] = 0;
310
      C1.w[0] = 0;
311
    } else {	// canonical
312
      ;
313
    }
314
  }
315
 
316
  if ((C1.w[1] == 0x0ull) && (C1.w[0] == 0x0ull)) {
317
    // x is +/-0
318
    res.w[1] = 0x8000000000000000ull;	// -1 * 10^emin
319
    res.w[0] = 0x0000000000000001ull;
320
  } else {	// x is not special and is not zero
321
    if (x.w[1] == 0xdfffed09bead87c0ull
322
	&& x.w[0] == 0x378d8e63ffffffffull) {
323
      // x = -MAXFP = -999...99 * 10^emax
324
      res.w[1] = 0xf800000000000000ull;	// -inf
325
      res.w[0] = 0x0000000000000000ull;
326
    } else if (x.w[1] == 0x0ull && x.w[0] == 0x0000000000000001ull) {	// +MINFP
327
      res.w[1] = 0x0000000000000000ull;	// +0
328
      res.w[0] = 0x0000000000000000ull;
329
    } else {	// -MAXFP <= x <= -MINFP - 1 ulp OR MINFP <= x <= MAXFP - 1 ulp
330
      // can add/subtract 1 ulp to the significand
331
 
332
      // Note: we could check here if x >= 10^34 to speed up the case q1 = 34
333
      // q1 = nr. of decimal digits in x
334
      // determine first the nr. of bits in x
335
      if (C1.w[1] == 0) {
336
	if (C1.w[0] >= 0x0020000000000000ull) {	// x >= 2^53
337
	  // split the 64-bit value in two 32-bit halves to avoid rnd errors
338
	  if (C1.w[0] >= 0x0000000100000000ull) {	// x >= 2^32
339
	    tmp1.d = (double) (C1.w[0] >> 32);	// exact conversion
340
	    x_nr_bits =
341
	      33 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) -
342
		    0x3ff);
343
	  } else {	// x < 2^32
344
	    tmp1.d = (double) (C1.w[0]);	// exact conversion
345
	    x_nr_bits =
346
	      1 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) -
347
		   0x3ff);
348
	  }
349
	} else {	// if x < 2^53
350
	  tmp1.d = (double) C1.w[0];	// exact conversion
351
	  x_nr_bits =
352
	    1 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) - 0x3ff);
353
	}
354
      } else {	// C1.w[1] != 0 => nr. bits = 64 + nr_bits (C1.w[1])
355
	tmp1.d = (double) C1.w[1];	// exact conversion
356
	x_nr_bits =
357
	  65 + ((((unsigned int) (tmp1.ui64 >> 52)) & 0x7ff) - 0x3ff);
358
      }
359
      q1 = nr_digits[x_nr_bits - 1].digits;
360
      if (q1 == 0) {
361
	q1 = nr_digits[x_nr_bits - 1].digits1;
362
	if (C1.w[1] > nr_digits[x_nr_bits - 1].threshold_hi
363
	    || (C1.w[1] == nr_digits[x_nr_bits - 1].threshold_hi
364
		&& C1.w[0] >= nr_digits[x_nr_bits - 1].threshold_lo))
365
	  q1++;
366
      }
367
      // if q1 < P then pad the significand with zeros
368
      if (q1 < P34) {
369
	exp = (x_exp >> 49) - 6176;
370
	if (exp + 6176 > P34 - q1) {
371
	  ind = P34 - q1;	// 1 <= ind <= P34 - 1
372
	  // pad with P34 - q1 zeros, until exponent = emin
373
	  // C1 = C1 * 10^ind
374
	  if (q1 <= 19) {	// 64-bit C1
375
	    if (ind <= 19) {	// 64-bit 10^ind and 64-bit C1
376
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
377
	    } else {	// 128-bit 10^ind and 64-bit C1
378
	      __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
379
	    }
380
	  } else {	// C1 is (most likely) 128-bit
381
	    if (ind <= 14) {	// 64-bit 10^ind and 128-bit C1 (most likely)
382
	      __mul_128x64_to_128 (C1, ten2k64[ind], C1);
383
	    } else if (ind <= 19) {	// 64-bit 10^ind and 64-bit C1 (q1 <= 19)
384
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
385
	    } else {	// 128-bit 10^ind and 64-bit C1 (C1 must be 64-bit)
386
	      __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
387
	    }
388
	  }
389
	  x_exp = x_exp - ((UINT64) ind << 49);
390
	} else {	// pad with zeros until the exponent reaches emin
391
	  ind = exp + 6176;
392
	  // C1 = C1 * 10^ind
393
	  if (ind <= 19) {	// 1 <= P34 - q1 <= 19 <=> 15 <= q1 <= 33
394
	    if (q1 <= 19) {	// 64-bit C1, 64-bit 10^ind
395
	      __mul_64x64_to_128MACH (C1, C1.w[0], ten2k64[ind]);
396
	    } else {	// 20 <= q1 <= 33 => 128-bit C1, 64-bit 10^ind
397
	      __mul_128x64_to_128 (C1, ten2k64[ind], C1);
398
	    }
399
	  } else {	// if 20 <= P34 - q1 <= 33 <=> 1 <= q1 <= 14 =>
400
	    // 64-bit C1, 128-bit 10^ind
401
	    __mul_128x64_to_128 (C1, C1.w[0], ten2k128[ind - 20]);
402
	  }
403
	  x_exp = EXP_MIN;
404
	}
405
      }
406
      if (x_sign) {	// x < 0
407
	// add 1 ulp (add 1 to the significand)
408
	C1.w[0]++;
409
	if (C1.w[0] == 0)
410
	  C1.w[1]++;
411
	if (C1.w[1] == 0x0001ed09bead87c0ull && C1.w[0] == 0x378d8e6400000000ull) {	// if  C1 = 10^34
412
	  C1.w[1] = 0x0000314dc6448d93ull;	// C1 = 10^33
413
	  C1.w[0] = 0x38c15b0a00000000ull;
414
	  x_exp = x_exp + EXP_P1;
415
	}
416
      } else {	// x > 0
417
	// subtract 1 ulp (subtract 1 from the significand)
418
	C1.w[0]--;
419
	if (C1.w[0] == 0xffffffffffffffffull)
420
	  C1.w[1]--;
421
	if (x_exp != 0 && C1.w[1] == 0x0000314dc6448d93ull && C1.w[0] == 0x38c15b09ffffffffull) {	// if  C1 = 10^33 - 1
422
	  C1.w[1] = 0x0001ed09bead87c0ull;	// C1 = 10^34 - 1
423
	  C1.w[0] = 0x378d8e63ffffffffull;
424
	  x_exp = x_exp - EXP_P1;
425
	}
426
      }
427
      // assemble the result
428
      res.w[1] = x_sign | x_exp | C1.w[1];
429
      res.w[0] = C1.w[0];
430
    }	// end -MAXFP <= x <= -MINFP - 1 ulp OR MINFP <= x <= MAXFP - 1 ulp
431
  }	// end x is not special and is not zero
432
  BID_RETURN (res);
433
}
434
 
435
/*****************************************************************************
436
 *  BID128 nextafter
437
 ****************************************************************************/
438
 
439
#if DECIMAL_CALL_BY_REFERENCE
440
void
441
bid128_nextafter (UINT128 * pres, UINT128 * px,
442
		  UINT128 *
443
		  py _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM)
444
{
445
  UINT128 x = *px;
446
  UINT128 y = *py;
447
  UINT128 xnswp = *px;
448
  UINT128 ynswp = *py;
449
#else
450
UINT128
451
bid128_nextafter (UINT128 x,
452
		  UINT128 y _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
453
		  _EXC_INFO_PARAM) {
454
  UINT128 xnswp = x;
455
  UINT128 ynswp = y;
456
#endif
457
 
458
  UINT128 res;
459
  UINT128 tmp1, tmp2, tmp3;
460
  FPSC tmp_fpsf = 0;		// dummy fpsf for calls to comparison functions
461
  int res1, res2;
462
  UINT64 x_exp;
463
 
464
 
465
  BID_SWAP128 (x);
466
  BID_SWAP128 (y);
467
  // check for NaNs
468
  if (((x.w[1] & MASK_SPECIAL) == MASK_SPECIAL)
469
      || ((y.w[1] & MASK_SPECIAL) == MASK_SPECIAL)) {
470
    // x is special or y is special
471
    if ((x.w[1] & MASK_NAN) == MASK_NAN) {	// x is NAN
472
      // if x = NaN, then res = Q (x)
473
      // check first for non-canonical NaN payload
474
      if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
475
	  (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull)
476
	   && (x.w[0] > 0x38c15b09ffffffffull))) {
477
	x.w[1] = x.w[1] & 0xffffc00000000000ull;
478
	x.w[0] = 0x0ull;
479
      }
480
      if ((x.w[1] & MASK_SNAN) == MASK_SNAN) {	// x is SNAN
481
	// set invalid flag
482
	*pfpsf |= INVALID_EXCEPTION;
483
	// return quiet (x)
484
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out also G[6]-G[16]
485
	res.w[0] = x.w[0];
486
      } else {	// x is QNaN
487
	// return x
488
	res.w[1] = x.w[1] & 0xfc003fffffffffffull;	// clear out G[6]-G[16]
489
	res.w[0] = x.w[0];
490
	if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {	// y is SNAN
491
	  // set invalid flag
492
	  *pfpsf |= INVALID_EXCEPTION;
493
	}
494
      }
495
      BID_RETURN (res)
496
    } else if ((y.w[1] & MASK_NAN) == MASK_NAN) {	// y is NAN
497
      // if x = NaN, then res = Q (x)
498
      // check first for non-canonical NaN payload
499
      if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
500
	  (((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull)
501
	   && (y.w[0] > 0x38c15b09ffffffffull))) {
502
	y.w[1] = y.w[1] & 0xffffc00000000000ull;
503
	y.w[0] = 0x0ull;
504
      }
505
      if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {	// y is SNAN
506
	// set invalid flag
507
	*pfpsf |= INVALID_EXCEPTION;
508
	// return quiet (x)
509
	res.w[1] = y.w[1] & 0xfc003fffffffffffull;	// clear out also G[6]-G[16]
510
	res.w[0] = y.w[0];
511
      } else {	// x is QNaN
512
	// return x
513
	res.w[1] = y.w[1] & 0xfc003fffffffffffull;	// clear out G[6]-G[16]
514
	res.w[0] = y.w[0];
515
      }
516
      BID_RETURN (res)
517
    } else {	// at least one is infinity
518
      if ((x.w[1] & MASK_ANY_INF) == MASK_INF) {	// x = inf
519
	x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF);
520
	x.w[0] = 0x0ull;
521
      }
522
      if ((y.w[1] & MASK_ANY_INF) == MASK_INF) {	// y = inf
523
	y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF);
524
	y.w[0] = 0x0ull;
525
      }
526
    }
527
  }
528
  // neither x nor y is NaN
529
 
530
  // if not infinity, check for non-canonical values x (treated as zero)
531
  if ((x.w[1] & MASK_ANY_INF) != MASK_INF) {	// x != inf
532
    if ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) {	// G0_G1=11
533
      // non-canonical
534
      x_exp = (x.w[1] << 2) & MASK_EXP;	// biased and shifted left 49 bits
535
      x.w[1] = (x.w[1] & MASK_SIGN) | x_exp;
536
      x.w[0] = 0x0ull;
537
    } else {	// G0_G1 != 11
538
      x_exp = x.w[1] & MASK_EXP;	// biased and shifted left 49 bits
539
      if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
540
	  ((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
541
	   && x.w[0] > 0x378d8e63ffffffffull)) {
542
	// x is non-canonical if coefficient is larger than 10^34 -1
543
	x.w[1] = (x.w[1] & MASK_SIGN) | x_exp;
544
	x.w[0] = 0x0ull;
545
      } else {	// canonical
546
	;
547
      }
548
    }
549
  }
550
  // no need to check for non-canonical y
551
 
552
  // neither x nor y is NaN
553
  tmp_fpsf = *pfpsf;	// save fpsf
554
#if DECIMAL_CALL_BY_REFERENCE
555
  bid128_quiet_equal (&res1, &xnswp,
556
		      &ynswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
557
		      _EXC_INFO_ARG);
558
  bid128_quiet_greater (&res2, &xnswp,
559
			&ynswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
560
			_EXC_INFO_ARG);
561
#else
562
  res1 =
563
    bid128_quiet_equal (xnswp,
564
			ynswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
565
			_EXC_INFO_ARG);
566
  res2 =
567
    bid128_quiet_greater (xnswp,
568
			  ynswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
569
			  _EXC_INFO_ARG);
570
#endif
571
  *pfpsf = tmp_fpsf;	// restore fpsf
572
 
573
  if (res1) {	// x = y
574
    // return x with the sign of y
575
    res.w[1] =
576
      (x.w[1] & 0x7fffffffffffffffull) | (y.
577
					  w[1] & 0x8000000000000000ull);
578
    res.w[0] = x.w[0];
579
  } else if (res2) {	// x > y
580
#if DECIMAL_CALL_BY_REFERENCE
581
    bid128_nextdown (&res,
582
		     &xnswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
583
		     _EXC_INFO_ARG);
584
#else
585
    res =
586
      bid128_nextdown (xnswp _EXC_FLAGS_ARG _EXC_MASKS_ARG
587
		       _EXC_INFO_ARG);
588
#endif
589
    BID_SWAP128 (res);
590
  } else {	// x < y
591
#if DECIMAL_CALL_BY_REFERENCE
592
    bid128_nextup (&res,
593
		   &xnswp _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
594
#else
595
    res =
596
      bid128_nextup (xnswp _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
597
#endif
598
    BID_SWAP128 (res);
599
  }
600
  // if the operand x is finite but the result is infinite, signal
601
  // overflow and inexact
602
  if (((x.w[1] & MASK_SPECIAL) != MASK_SPECIAL)
603
      && ((res.w[1] & MASK_SPECIAL) == MASK_SPECIAL)) {
604
    // set the inexact flag
605
    *pfpsf |= INEXACT_EXCEPTION;
606
    // set the overflow flag
607
    *pfpsf |= OVERFLOW_EXCEPTION;
608
  }
609
  // if the result is in (-10^emin, 10^emin), and is different from the
610
  // operand x, signal underflow and inexact
611
  tmp1.w[HIGH_128W] = 0x0000314dc6448d93ull;
612
  tmp1.w[LOW_128W] = 0x38c15b0a00000000ull;	// +100...0[34] * 10^emin
613
  tmp2.w[HIGH_128W] = res.w[1] & 0x7fffffffffffffffull;
614
  tmp2.w[LOW_128W] = res.w[0];
615
  tmp3.w[HIGH_128W] = res.w[1];
616
  tmp3.w[LOW_128W] = res.w[0];
617
  tmp_fpsf = *pfpsf;	// save fpsf
618
#if DECIMAL_CALL_BY_REFERENCE
619
  bid128_quiet_greater (&res1, &tmp1,
620
			&tmp2 _EXC_FLAGS_ARG _EXC_MASKS_ARG
621
			_EXC_INFO_ARG);
622
  bid128_quiet_not_equal (&res2, &xnswp,
623
			  &tmp3 _EXC_FLAGS_ARG _EXC_MASKS_ARG
624
			  _EXC_INFO_ARG);
625
#else
626
  res1 =
627
    bid128_quiet_greater (tmp1,
628
			  tmp2 _EXC_FLAGS_ARG _EXC_MASKS_ARG
629
			  _EXC_INFO_ARG);
630
  res2 =
631
    bid128_quiet_not_equal (xnswp,
632
			    tmp3 _EXC_FLAGS_ARG _EXC_MASKS_ARG
633
			    _EXC_INFO_ARG);
634
#endif
635
  *pfpsf = tmp_fpsf;	// restore fpsf
636
  if (res1 && res2) {
637
    // set the inexact flag
638
    *pfpsf |= INEXACT_EXCEPTION;
639
    // set the underflow flag
640
    *pfpsf |= UNDERFLOW_EXCEPTION;
641
  }
642
  BID_RETURN (res);
643
}