Converts a double to the smallest DECIMAL type that represents it losslessly. Populates exactly one of the three sinks. Returns the full column type int (ColumnType#getDecimalType(int, int)) on success, or 0 for NaN / Infinity / value doesn't fit in any DECIMAL type. @param value the doub
(
double value,
Decimal64 sink64,
Decimal128 sink128,
Decimal256 sink256
)
| 674 | * @return the column type int, or 0 on failure |
| 675 | */ |
| 676 | public static int doubleToDecimal( |
| 677 | double value, |
| 678 | Decimal64 sink64, |
| 679 | Decimal128 sink128, |
| 680 | Decimal256 sink256 |
| 681 | ) { |
| 682 | final long doubleBits = Double.doubleToRawLongBits(value); |
| 683 | boolean negative = (doubleBits & SIGN_BIT_MASK) != 0L; |
| 684 | long ieeeMantissa = doubleBits & SIGNIF_BIT_MASK; |
| 685 | int ieeeExponent = (int) ((doubleBits & EXP_BIT_MASK) >> EXP_SHIFT); |
| 686 | |
| 687 | if (ieeeExponent == 2047) { |
| 688 | return 0; // NaN or Infinity |
| 689 | } |
| 690 | |
| 691 | if (ieeeExponent == 0 && ieeeMantissa == 0L) { |
| 692 | sink64.ofZero(); |
| 693 | return ColumnType.getDecimalType(1, 0); |
| 694 | } |
| 695 | |
| 696 | int[] e10 = tlE10.get(); |
| 697 | long output = RyuDouble.d2d(ieeeMantissa, ieeeExponent, e10); |
| 698 | int olength = RyuDouble.decimalLength17(output); |
| 699 | int decExp = e10[0] + olength; |
| 700 | |
| 701 | int naturalScale = Math.max(0, -e10[0]); |
| 702 | int integerDigits = Math.max(0, decExp); |
| 703 | int precision = Math.max(1, integerDigits + naturalScale); |
| 704 | |
| 705 | Decimal target; |
| 706 | if (precision <= Decimal64.MAX_PRECISION && naturalScale <= Decimal64.MAX_SCALE) { |
| 707 | target = sink64; |
| 708 | } else if (precision <= Decimal128.MAX_PRECISION && naturalScale <= Decimal128.MAX_SCALE) { |
| 709 | target = sink128; |
| 710 | } else if (precision <= Decimals.MAX_PRECISION && naturalScale <= Decimal256.MAX_SCALE) { |
| 711 | target = sink256; |
| 712 | } else { |
| 713 | return 0; |
| 714 | } |
| 715 | |
| 716 | target.ofDigitsAndPower(output, e10[0]); |
| 717 | if (negative) { |
| 718 | target.negate(); |
| 719 | } |
| 720 | |
| 721 | return ColumnType.getDecimalType(precision, naturalScale); |
| 722 | } |
| 723 | |
| 724 | /** |
| 725 | * Converts a double directly to a Decimal with the specified target precision and scale, |