1/* Decimal floating point support.
2 Copyright (C) 2005-2023 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
24#include "tree.h"
25#include "dfp.h"
26
27/* The order of the following headers is important for making sure
28 decNumber structure is large enough to hold decimal128 digits. */
29
30#include "decimal128.h"
31#include "decimal64.h"
32#include "decimal32.h"
33
34#ifndef WORDS_BIGENDIAN
35#define WORDS_BIGENDIAN 0
36#endif
37
38/* Initialize R (a real with the decimal flag set) from DN. Can
39 utilize status passed in via CONTEXT, if a previous operation had
40 interesting status. */
41
42static void
43decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context)
44{
45 memset (s: r, c: 0, n: sizeof (REAL_VALUE_TYPE));
46
47 r->cl = rvc_normal;
48 if (decNumberIsNaN (dn))
49 r->cl = rvc_nan;
50 if (decNumberIsInfinite (dn))
51 r->cl = rvc_inf;
52 if (context->status & DEC_Overflow)
53 r->cl = rvc_inf;
54 if (decNumberIsNegative (dn))
55 r->sign = 1;
56 r->decimal = 1;
57
58 if (r->cl != rvc_normal)
59 return;
60
61 decContextDefault (context, DEC_INIT_DECIMAL128);
62 context->traps = 0;
63
64 decimal128FromNumber ((decimal128 *) r->sig, dn, context);
65}
66
67/* Create decimal encoded R from string S. */
68
69void
70decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s)
71{
72 decNumber dn;
73 decContext set;
74 decContextDefault (&set, DEC_INIT_DECIMAL128);
75 set.traps = 0;
76
77 decNumberFromString (&dn, s, &set);
78
79 /* It would be more efficient to store directly in decNumber format,
80 but that is impractical from current data structure size.
81 Encoding as a decimal128 is much more compact. */
82 decimal_from_decnumber (r, dn: &dn, context: &set);
83}
84
85/* Initialize a decNumber from a REAL_VALUE_TYPE. */
86
87static void
88decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
89{
90 decContext set;
91 decContextDefault (&set, DEC_INIT_DECIMAL128);
92 set.traps = 0;
93
94 switch (r->cl)
95 {
96 case rvc_zero:
97 decNumberZero (dn);
98 break;
99 case rvc_inf:
100 decNumberFromString (dn, "Infinity", &set);
101 break;
102 case rvc_nan:
103 if (r->signalling)
104 decNumberFromString (dn, "snan", &set);
105 else
106 decNumberFromString (dn, "nan", &set);
107 break;
108 case rvc_normal:
109 if (!r->decimal)
110 {
111 /* dconst{1,2,m1,half} are used in various places in
112 the middle-end and optimizers, allow them here
113 as an exception by converting them to decimal. */
114 if (memcmp (s1: r, s2: &dconst1, n: sizeof (*r)) == 0)
115 {
116 decNumberFromString (dn, "1", &set);
117 break;
118 }
119 if (memcmp (s1: r, s2: &dconst2, n: sizeof (*r)) == 0)
120 {
121 decNumberFromString (dn, "2", &set);
122 break;
123 }
124 if (memcmp (s1: r, s2: &dconstm1, n: sizeof (*r)) == 0)
125 {
126 decNumberFromString (dn, "-1", &set);
127 break;
128 }
129 if (memcmp (s1: r, s2: &dconsthalf, n: sizeof (*r)) == 0)
130 {
131 decNumberFromString (dn, "0.5", &set);
132 break;
133 }
134 gcc_unreachable ();
135 }
136 decimal128ToNumber ((const decimal128 *) r->sig, dn);
137 break;
138 default:
139 gcc_unreachable ();
140 }
141
142 /* Fix up sign bit. */
143 if (r->sign != decNumberIsNegative (dn))
144 dn->bits ^= DECNEG;
145}
146
147/* Encode a real into an IEEE 754 decimal32 type. */
148
149void
150encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
151 long *buf, const REAL_VALUE_TYPE *r)
152{
153 decNumber dn;
154 decimal32 d32;
155 decContext set;
156 int32_t image;
157
158 decContextDefault (&set, DEC_INIT_DECIMAL128);
159 set.traps = 0;
160
161 decimal_to_decnumber (r, dn: &dn);
162 decimal32FromNumber (&d32, &dn, &set);
163
164 memcpy (dest: &image, src: d32.bytes, n: sizeof (int32_t));
165 buf[0] = image;
166}
167
168/* Decode an IEEE 754 decimal32 type into a real. */
169
170void
171decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
172 REAL_VALUE_TYPE *r, const long *buf)
173{
174 decNumber dn;
175 decimal32 d32;
176 decContext set;
177 int32_t image;
178
179 decContextDefault (&set, DEC_INIT_DECIMAL128);
180 set.traps = 0;
181
182 image = buf[0];
183 memcpy (dest: &d32.bytes, src: &image, n: sizeof (int32_t));
184
185 decimal32ToNumber (&d32, &dn);
186 decimal_from_decnumber (r, dn: &dn, context: &set);
187}
188
189/* Encode a real into an IEEE 754 decimal64 type. */
190
191void
192encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
193 long *buf, const REAL_VALUE_TYPE *r)
194{
195 decNumber dn;
196 decimal64 d64;
197 decContext set;
198 int32_t image;
199
200 decContextDefault (&set, DEC_INIT_DECIMAL128);
201 set.traps = 0;
202
203 decimal_to_decnumber (r, dn: &dn);
204 decimal64FromNumber (&d64, &dn, &set);
205
206 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
207 {
208 memcpy (dest: &image, src: &d64.bytes[0], n: sizeof (int32_t));
209 buf[0] = image;
210 memcpy (dest: &image, src: &d64.bytes[4], n: sizeof (int32_t));
211 buf[1] = image;
212 }
213 else
214 {
215 memcpy (dest: &image, src: &d64.bytes[4], n: sizeof (int32_t));
216 buf[0] = image;
217 memcpy (dest: &image, src: &d64.bytes[0], n: sizeof (int32_t));
218 buf[1] = image;
219 }
220}
221
222/* Decode an IEEE 754 decimal64 type into a real. */
223
224void
225decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
226 REAL_VALUE_TYPE *r, const long *buf)
227{
228 decNumber dn;
229 decimal64 d64;
230 decContext set;
231 int32_t image;
232
233 decContextDefault (&set, DEC_INIT_DECIMAL128);
234 set.traps = 0;
235
236 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
237 {
238 image = buf[0];
239 memcpy (dest: &d64.bytes[0], src: &image, n: sizeof (int32_t));
240 image = buf[1];
241 memcpy (dest: &d64.bytes[4], src: &image, n: sizeof (int32_t));
242 }
243 else
244 {
245 image = buf[1];
246 memcpy (dest: &d64.bytes[0], src: &image, n: sizeof (int32_t));
247 image = buf[0];
248 memcpy (dest: &d64.bytes[4], src: &image, n: sizeof (int32_t));
249 }
250
251 decimal64ToNumber (&d64, &dn);
252 decimal_from_decnumber (r, dn: &dn, context: &set);
253}
254
255/* Encode a real into an IEEE 754 decimal128 type. */
256
257void
258encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
259 long *buf, const REAL_VALUE_TYPE *r)
260{
261 decNumber dn;
262 decContext set;
263 decimal128 d128;
264 int32_t image;
265
266 decContextDefault (&set, DEC_INIT_DECIMAL128);
267 set.traps = 0;
268
269 decimal_to_decnumber (r, dn: &dn);
270 decimal128FromNumber (&d128, &dn, &set);
271
272 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
273 {
274 memcpy (dest: &image, src: &d128.bytes[0], n: sizeof (int32_t));
275 buf[0] = image;
276 memcpy (dest: &image, src: &d128.bytes[4], n: sizeof (int32_t));
277 buf[1] = image;
278 memcpy (dest: &image, src: &d128.bytes[8], n: sizeof (int32_t));
279 buf[2] = image;
280 memcpy (dest: &image, src: &d128.bytes[12], n: sizeof (int32_t));
281 buf[3] = image;
282 }
283 else
284 {
285 memcpy (dest: &image, src: &d128.bytes[12], n: sizeof (int32_t));
286 buf[0] = image;
287 memcpy (dest: &image, src: &d128.bytes[8], n: sizeof (int32_t));
288 buf[1] = image;
289 memcpy (dest: &image, src: &d128.bytes[4], n: sizeof (int32_t));
290 buf[2] = image;
291 memcpy (dest: &image, src: &d128.bytes[0], n: sizeof (int32_t));
292 buf[3] = image;
293 }
294}
295
296/* Decode an IEEE 754 decimal128 type into a real. */
297
298void
299decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
300 REAL_VALUE_TYPE *r, const long *buf)
301{
302 decNumber dn;
303 decimal128 d128;
304 decContext set;
305 int32_t image;
306
307 decContextDefault (&set, DEC_INIT_DECIMAL128);
308 set.traps = 0;
309
310 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
311 {
312 image = buf[0];
313 memcpy (dest: &d128.bytes[0], src: &image, n: sizeof (int32_t));
314 image = buf[1];
315 memcpy (dest: &d128.bytes[4], src: &image, n: sizeof (int32_t));
316 image = buf[2];
317 memcpy (dest: &d128.bytes[8], src: &image, n: sizeof (int32_t));
318 image = buf[3];
319 memcpy (dest: &d128.bytes[12], src: &image, n: sizeof (int32_t));
320 }
321 else
322 {
323 image = buf[3];
324 memcpy (dest: &d128.bytes[0], src: &image, n: sizeof (int32_t));
325 image = buf[2];
326 memcpy (dest: &d128.bytes[4], src: &image, n: sizeof (int32_t));
327 image = buf[1];
328 memcpy (dest: &d128.bytes[8], src: &image, n: sizeof (int32_t));
329 image = buf[0];
330 memcpy (dest: &d128.bytes[12], src: &image, n: sizeof (int32_t));
331 }
332
333 decimal128ToNumber (&d128, &dn);
334 decimal_from_decnumber (r, dn: &dn, context: &set);
335}
336
337/* Helper function to convert from a binary real internal
338 representation. */
339
340static void
341decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
342 const real_format *fmt)
343{
344 char string[256];
345 if (from->cl == rvc_normal)
346 {
347 const decimal128 *const d128 = (const decimal128 *) from->sig;
348 decimal128ToString (d128, string);
349 }
350 else
351 real_to_decimal (string, from, sizeof (string), 0, 1);
352 real_from_string3 (to, string, fmt);
353}
354
355
356/* Helper function to convert from a binary real internal
357 representation. */
358
359static void
360decimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from)
361{
362 char string[256];
363
364 /* We convert to string, then to decNumber then to decimal128. */
365 real_to_decimal (string, from, sizeof (string), 0, 1);
366 decimal_real_from_string (r: to, s: string);
367 /* When a canonical NaN is originally created, it is not marked as
368 decimal. Ensure the result of converting to another decimal type
369 (which passes through this function) is also marked as
370 canonical. */
371 if (from->cl == rvc_nan && from->canonical)
372 to->canonical = 1;
373}
374
375/* Helper function to real.cc:do_compare() to handle decimal internal
376 representation including when one of the operands is still in the
377 binary internal representation. */
378
379int
380decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
381 int nan_result)
382{
383 decContext set;
384 decNumber dn, dn2, dn3;
385 REAL_VALUE_TYPE a1, b1;
386
387 /* If either operand is non-decimal, create temporary versions. */
388 if (!a->decimal)
389 {
390 decimal_from_binary (to: &a1, from: a);
391 a = &a1;
392 }
393 if (!b->decimal)
394 {
395 decimal_from_binary (to: &b1, from: b);
396 b = &b1;
397 }
398
399 /* Convert into decNumber form for comparison operation. */
400 decContextDefault (&set, DEC_INIT_DECIMAL128);
401 set.traps = 0;
402 decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
403 decimal128ToNumber ((const decimal128 *) b->sig, &dn3);
404
405 /* Finally, do the comparison. */
406 decNumberCompare (&dn, &dn2, &dn3, &set);
407
408 /* Return the comparison result. */
409 if (decNumberIsNaN (&dn))
410 return nan_result;
411 else if (decNumberIsZero (&dn))
412 return 0;
413 else if (decNumberIsNegative (&dn))
414 return -1;
415 else
416 return 1;
417}
418
419/* Helper to round_for_format, handling decimal float types. */
420
421void
422decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
423{
424 decNumber dn;
425 decContext set;
426
427 /* Real encoding occurs later. */
428 if (r->cl != rvc_normal)
429 return;
430
431 decContextDefault (&set, DEC_INIT_DECIMAL128);
432 set.traps = 0;
433 decimal128ToNumber ((decimal128 *) r->sig, &dn);
434
435 if (fmt == &decimal_quad_format)
436 {
437 /* The internal format is already in this format. */
438 return;
439 }
440 else if (fmt == &decimal_single_format)
441 {
442 decimal32 d32;
443 decContextDefault (&set, DEC_INIT_DECIMAL32);
444 set.traps = 0;
445
446 decimal32FromNumber (&d32, &dn, &set);
447 decimal32ToNumber (&d32, &dn);
448 }
449 else if (fmt == &decimal_double_format)
450 {
451 decimal64 d64;
452 decContextDefault (&set, DEC_INIT_DECIMAL64);
453 set.traps = 0;
454
455 decimal64FromNumber (&d64, &dn, &set);
456 decimal64ToNumber (&d64, &dn);
457 }
458 else
459 gcc_unreachable ();
460
461 decimal_from_decnumber (r, dn: &dn, context: &set);
462}
463
464/* Extend or truncate to a new mode. Handles conversions between
465 binary and decimal types. */
466
467void
468decimal_real_convert (REAL_VALUE_TYPE *r, const real_format *fmt,
469 const REAL_VALUE_TYPE *a)
470{
471 if (a->decimal && fmt->b == 10)
472 return;
473 if (a->decimal)
474 decimal_to_binary (to: r, from: a, fmt);
475 else
476 decimal_from_binary (to: r, from: a);
477}
478
479/* Render R_ORIG as a decimal floating point constant. Emit DIGITS
480 significant digits in the result, bounded by BUF_SIZE. If DIGITS
481 is 0, choose the maximum for the representation. If
482 CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring
483 DIGITS or CROP_TRAILING_ZEROS. */
484
485void
486decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig,
487 size_t buf_size,
488 size_t digits ATTRIBUTE_UNUSED,
489 int crop_trailing_zeros ATTRIBUTE_UNUSED)
490{
491 const decimal128 *const d128 = (const decimal128*) r_orig->sig;
492
493 /* decimal128ToString requires space for at least 24 characters;
494 Require two more for suffix. */
495 gcc_assert (buf_size >= 24);
496 decimal128ToString (d128, str);
497}
498
499static bool
500decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
501 const REAL_VALUE_TYPE *op1, int subtract_p)
502{
503 decNumber dn;
504 decContext set;
505 decNumber dn2, dn3;
506
507 decimal_to_decnumber (r: op0, dn: &dn2);
508 decimal_to_decnumber (r: op1, dn: &dn3);
509
510 decContextDefault (&set, DEC_INIT_DECIMAL128);
511 set.traps = 0;
512
513 if (subtract_p)
514 decNumberSubtract (&dn, &dn2, &dn3, &set);
515 else
516 decNumberAdd (&dn, &dn2, &dn3, &set);
517
518 decimal_from_decnumber (r, dn: &dn, context: &set);
519
520 /* Return true, if inexact. */
521 return (set.status & DEC_Inexact);
522}
523
524/* Compute R = OP0 * OP1. */
525
526static bool
527decimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
528 const REAL_VALUE_TYPE *op1)
529{
530 decContext set;
531 decNumber dn, dn2, dn3;
532
533 decimal_to_decnumber (r: op0, dn: &dn2);
534 decimal_to_decnumber (r: op1, dn: &dn3);
535
536 decContextDefault (&set, DEC_INIT_DECIMAL128);
537 set.traps = 0;
538
539 decNumberMultiply (&dn, &dn2, &dn3, &set);
540 decimal_from_decnumber (r, dn: &dn, context: &set);
541
542 /* Return true, if inexact. */
543 return (set.status & DEC_Inexact);
544}
545
546/* Compute R = OP0 / OP1. */
547
548static bool
549decimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
550 const REAL_VALUE_TYPE *op1)
551{
552 decContext set;
553 decNumber dn, dn2, dn3;
554
555 decimal_to_decnumber (r: op0, dn: &dn2);
556 decimal_to_decnumber (r: op1, dn: &dn3);
557
558 decContextDefault (&set, DEC_INIT_DECIMAL128);
559 set.traps = 0;
560
561 decNumberDivide (&dn, &dn2, &dn3, &set);
562 decimal_from_decnumber (r, dn: &dn, context: &set);
563
564 /* Return true, if inexact. */
565 return (set.status & DEC_Inexact);
566}
567
568/* Set R to A truncated to an integral value toward zero (decimal
569 floating point). */
570
571void
572decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
573{
574 decNumber dn, dn2;
575 decContext set;
576
577 decContextDefault (&set, DEC_INIT_DECIMAL128);
578 set.traps = 0;
579 set.round = DEC_ROUND_DOWN;
580 decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
581
582 decNumberToIntegralValue (&dn, &dn2, &set);
583 decimal_from_decnumber (r, dn: &dn, context: &set);
584}
585
586/* Render decimal float value R as an integer. */
587
588HOST_WIDE_INT
589decimal_real_to_integer (const REAL_VALUE_TYPE *r)
590{
591 decContext set;
592 decNumber dn, dn2, dn3;
593 REAL_VALUE_TYPE to;
594 char string[256];
595
596 decContextDefault (&set, DEC_INIT_DECIMAL128);
597 set.traps = 0;
598 set.round = DEC_ROUND_DOWN;
599 decimal128ToNumber ((const decimal128 *) r->sig, &dn);
600
601 decNumberToIntegralValue (&dn2, &dn, &set);
602 decNumberZero (&dn3);
603 decNumberRescale (&dn, &dn2, &dn3, &set);
604
605 /* Convert to REAL_VALUE_TYPE and call appropriate conversion
606 function. */
607 decNumberToString (&dn, string);
608 real_from_string (&to, string);
609 return real_to_integer (&to);
610}
611
612/* Likewise, but returns a wide_int with PRECISION. *FAIL is set if the
613 value does not fit. */
614
615wide_int
616decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
617{
618 decContext set;
619 decNumber dn, dn2, dn3;
620 REAL_VALUE_TYPE to;
621 char string[256];
622
623 decContextDefault (&set, DEC_INIT_DECIMAL128);
624 set.traps = 0;
625 set.round = DEC_ROUND_DOWN;
626 decimal128ToNumber ((const decimal128 *) r->sig, &dn);
627
628 decNumberToIntegralValue (&dn2, &dn, &set);
629 decNumberZero (&dn3);
630 decNumberRescale (&dn, &dn2, &dn3, &set);
631
632 /* Convert to REAL_VALUE_TYPE and call appropriate conversion
633 function. */
634 decNumberToString (&dn, string);
635 real_from_string (&to, string);
636 return real_to_integer (&to, fail, precision);
637}
638
639/* Perform the decimal floating point operation described by CODE.
640 For a unary operation, OP1 will be NULL. This function returns
641 true if the result may be inexact due to loss of precision. */
642
643bool
644decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code,
645 const REAL_VALUE_TYPE *op0,
646 const REAL_VALUE_TYPE *op1)
647{
648 REAL_VALUE_TYPE a, b;
649
650 /* If either operand is non-decimal, create temporaries. */
651 if (!op0->decimal)
652 {
653 decimal_from_binary (to: &a, from: op0);
654 op0 = &a;
655 }
656 if (op1 && !op1->decimal)
657 {
658 decimal_from_binary (to: &b, from: op1);
659 op1 = &b;
660 }
661
662 switch (code)
663 {
664 case PLUS_EXPR:
665 return decimal_do_add (r, op0, op1, subtract_p: 0);
666
667 case MINUS_EXPR:
668 return decimal_do_add (r, op0, op1, subtract_p: 1);
669
670 case MULT_EXPR:
671 return decimal_do_multiply (r, op0, op1);
672
673 case RDIV_EXPR:
674 return decimal_do_divide (r, op0, op1);
675
676 case MIN_EXPR:
677 if (op1->cl == rvc_nan)
678 *r = *op1;
679 else if (real_compare (UNLT_EXPR, op0, op1))
680 *r = *op0;
681 else
682 *r = *op1;
683 return false;
684
685 case MAX_EXPR:
686 if (op1->cl == rvc_nan)
687 *r = *op1;
688 else if (real_compare (LT_EXPR, op0, op1))
689 *r = *op1;
690 else
691 *r = *op0;
692 return false;
693
694 case NEGATE_EXPR:
695 {
696 *r = *op0;
697 /* Flip sign bit. */
698 decimal128FlipSign ((decimal128 *) r->sig);
699 /* Keep sign field in sync. */
700 r->sign ^= 1;
701 }
702 return false;
703
704 case ABS_EXPR:
705 {
706 *r = *op0;
707 /* Clear sign bit. */
708 decimal128ClearSign ((decimal128 *) r->sig);
709 /* Keep sign field in sync. */
710 r->sign = 0;
711 }
712 return false;
713
714 case FIX_TRUNC_EXPR:
715 decimal_do_fix_trunc (r, a: op0);
716 return false;
717
718 default:
719 gcc_unreachable ();
720 }
721}
722
723/* Fills R with the largest finite value representable in mode MODE.
724 If SIGN is nonzero, R is set to the most negative finite value. */
725
726void
727decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode)
728{
729 const char *max;
730
731 switch (mode)
732 {
733 case E_SDmode:
734 max = "9.999999E96";
735 break;
736 case E_DDmode:
737 max = "9.999999999999999E384";
738 break;
739 case E_TDmode:
740 max = "9.999999999999999999999999999999999E6144";
741 break;
742 default:
743 gcc_unreachable ();
744 }
745
746 decimal_real_from_string (r, s: max);
747 if (sign)
748 decimal128SetSign ((decimal128 *) r->sig, 1);
749
750 r->sign = sign;
751}
752

source code of gcc/dfp.cc