@@ -264,6 +264,7 @@ static decNumber * decTrim(decNumber *, decContext *, Flag, Int *);
264
264
static Int decUnitAddSub (const Unit * , Int , const Unit * , Int , Int ,
265
265
Unit * , Int );
266
266
static Int decUnitCompare (const Unit * , Int , const Unit * , Int , Int );
267
+ static bool mulUInt128ByPowOf10 (uLong * , uLong * , uInt );
267
268
268
269
#if !DECSUBSET
269
270
/* decFinish == decFinalize when no subset arithmetic needed */
@@ -542,6 +543,68 @@ int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set)
542
543
return 0 ;
543
544
} /* decNumberIntegralToInt64 */
544
545
546
+ /* ------------------------------------------------------------------ */
547
+ /* decNumberIntegralToInt128 -- conversion to int128 */
548
+ /* */
549
+ /* dn is the decNumber to convert. dn is assumed to have been */
550
+ /* rounded to a floating point integer value. */
551
+ /* set is the context for reporting errors */
552
+ /* returns the converted decNumber via plow and phigh */
553
+ /* */
554
+ /* Invalid is set if the decNumber is a NaN, Infinite or is out of */
555
+ /* range for a signed 128 bit integer. */
556
+ /* ------------------------------------------------------------------ */
557
+
558
+ void decNumberIntegralToInt128 (const decNumber * dn , decContext * set ,
559
+ uint64_t * plow , uint64_t * phigh )
560
+ {
561
+ int d ; /* work */
562
+ const Unit * up ; /* .. */
563
+ uint64_t lo = 0 , hi = 0 ;
564
+
565
+ if (decNumberIsSpecial (dn ) || (dn -> exponent < 0 ) ||
566
+ (dn -> digits + dn -> exponent > 39 )) {
567
+ goto Invalid ;
568
+ }
569
+
570
+ up = dn -> lsu ; /* -> lsu */
571
+
572
+ for (d = (dn -> digits - 1 ) / DECDPUN ; d >= 0 ; d -- ) {
573
+ if (mulu128 (& lo , & hi , DECDPUNMAX + 1 )) {
574
+ /* overflow */
575
+ goto Invalid ;
576
+ }
577
+ if (uadd64_overflow (lo , up [d ], & lo )) {
578
+ if (uadd64_overflow (hi , 1 , & hi )) {
579
+ /* overflow */
580
+ goto Invalid ;
581
+ }
582
+ }
583
+ }
584
+
585
+ if (mulUInt128ByPowOf10 (& lo , & hi , dn -> exponent )) {
586
+ /* overflow */
587
+ goto Invalid ;
588
+ }
589
+
590
+ if (decNumberIsNegative (dn )) {
591
+ if (lo == 0 ) {
592
+ * phigh = - hi ;
593
+ * plow = 0 ;
594
+ } else {
595
+ * phigh = ~hi ;
596
+ * plow = - lo ;
597
+ }
598
+ } else {
599
+ * plow = lo ;
600
+ * phigh = hi ;
601
+ }
602
+
603
+ return ;
604
+
605
+ Invalid :
606
+ decContextSetStatus (set , DEC_Invalid_operation );
607
+ } /* decNumberIntegralToInt128 */
545
608
546
609
/* ------------------------------------------------------------------ */
547
610
/* to-scientific-string -- conversion to numeric string */
@@ -7885,6 +7948,38 @@ static Int decGetDigits(Unit *uar, Int len) {
7885
7948
return digits ;
7886
7949
} /* decGetDigits */
7887
7950
7951
+ /* ------------------------------------------------------------------ */
7952
+ /* mulUInt128ByPowOf10 -- multiply a 128-bit unsigned integer by a */
7953
+ /* power of 10. */
7954
+ /* */
7955
+ /* The 128-bit factor composed of plow and phigh is multiplied */
7956
+ /* by 10^exp. */
7957
+ /* */
7958
+ /* plow pointer to the low 64 bits of the first factor */
7959
+ /* phigh pointer to the high 64 bits of the first factor */
7960
+ /* exp the exponent of the power of 10 of the second factor */
7961
+ /* */
7962
+ /* If the result fits in 128 bits, returns false and the */
7963
+ /* multiplication result through plow and phigh. */
7964
+ /* Otherwise, returns true. */
7965
+ /* ------------------------------------------------------------------ */
7966
+ static bool mulUInt128ByPowOf10 (uLong * plow , uLong * phigh , uInt pow10 )
7967
+ {
7968
+ while (pow10 >= ARRAY_SIZE (powers )) {
7969
+ if (mulu128 (plow , phigh , powers [ARRAY_SIZE (powers ) - 1 ])) {
7970
+ /* Overflow */
7971
+ return true;
7972
+ }
7973
+ pow10 -= ARRAY_SIZE (powers ) - 1 ;
7974
+ }
7975
+
7976
+ if (pow10 > 0 ) {
7977
+ return mulu128 (plow , phigh , powers [pow10 ]);
7978
+ } else {
7979
+ return false;
7980
+ }
7981
+ }
7982
+
7888
7983
#if DECTRACE | DECCHECK
7889
7984
/* ------------------------------------------------------------------ */
7890
7985
/* decNumberShow -- display a number [debug aid] */
0 commit comments