public static long rescale(long value, int fromScale, int toScale) { if (toScale < fromScale) { throw new IllegalArgumentException("target scale must be larger than source scale"); } return value * longTenToNth(toScale - fromScale); }
public static boolean overflows(long value, int precision) { if (precision > MAX_SHORT_PRECISION) { throw new IllegalArgumentException("expected precision to be less than " + MAX_SHORT_PRECISION); } return abs(value) >= longTenToNth(precision); }
@UsedByGeneratedCode public static long divideShortShortShort(long dividend, long divisor, int rescaleFactor) { if (divisor == 0) { throw new PrestoException(DIVISION_BY_ZERO, "Division by zero"); } if (dividend == 0) { return 0; } int resultSignum = signum(dividend) * signum(divisor); long unsignedDividend = abs(dividend); long unsignedDivisor = abs(divisor); long rescaledUnsignedDividend = unsignedDividend * longTenToNth(rescaleFactor); long quotient = rescaledUnsignedDividend / unsignedDivisor; long remainder = rescaledUnsignedDividend - (quotient * unsignedDivisor); if (Long.compareUnsigned(remainder * 2, unsignedDivisor) >= 0) { quotient++; } return resultSignum * quotient; }
private static List<Object> calculateShortRescaleParameters(SpecializeContext context) { long aRescale = longTenToNth(rescaleFactor(context.getLiteral("a_scale"), context.getLiteral("b_scale"))); long bRescale = longTenToNth(rescaleFactor(context.getLiteral("b_scale"), context.getLiteral("a_scale"))); return ImmutableList.of(aRescale, bRescale); }
@LiteralParameters({"p", "s", "rp"}) @SqlType("decimal(rp,0)") @Constraint(variable = "rp", expression = "p - s + min(s, 1)") public static long ceilingShort(@LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num) { long rescaleFactor = Decimals.longTenToNth((int) numScale); long increment = (num % rescaleFactor > 0) ? 1 : 0; return num / rescaleFactor + increment; }
@LiteralParameters({"p", "s", "rp"}) @SqlType("decimal(rp,0)") @Constraint(variable = "rp", expression = "p - s + min(s, 1)") public static long floorShort(@LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num) { long rescaleFactor = Decimals.longTenToNth((int) numScale); long increment = (num % rescaleFactor) < 0 ? -1 : 0; return num / rescaleFactor + increment; }
@LiteralParameters({"p", "s", "rp"}) @SqlType("decimal(rp,0)") @Constraint(variable = "rp", expression = "max(1, p - s)") public static long truncateShort(@LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num) { if (num == 0) { return 0; } if (numScale == 0) { return num; } long rescaleFactor = Decimals.longTenToNth((int) numScale); return num / rescaleFactor; }
@LiteralParameters({"p", "s"}) @SqlType("decimal(p, s)") public static long truncateShort( @LiteralParameter("p") long numPrecision, @LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num, @SqlType(StandardTypes.INTEGER) long roundScale) { if (num == 0 || numPrecision - numScale + roundScale <= 0) { return 0; } if (roundScale >= numScale) { return num; } long rescaleFactor = longTenToNth((int) (numScale - roundScale)); long remainder = num % rescaleFactor; return num - remainder; }
@LiteralParameters({"p", "s", "rp", "rs"}) @SqlType("decimal(rp, rs)") @Constraint(variable = "rp", expression = "min(38, p - s + min(1, s))") @Constraint(variable = "rs", expression = "0") public static long roundShort(@LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num) { if (num == 0) { return 0; } if (numScale == 0) { return num; } if (num < 0) { return -roundShort(numScale, -num); } long rescaleFactor = Decimals.longTenToNth((int) numScale); long remainder = num % rescaleFactor; long remainderBoundary = rescaleFactor / 2; int roundUp = remainder >= remainderBoundary ? 1 : 0; return num / rescaleFactor + roundUp; }
private static void scaleDownRoundUp(Slice decimal, int scaleFactor, Slice result) { // optimized path for smaller values long low = getLong(decimal, 0); long high = getLong(decimal, 1); if (scaleFactor <= MAX_POWER_OF_TEN_LONG && high == 0 && low >= 0) { long divisor = longTenToNth(scaleFactor); long newLow = low / divisor; if (low % divisor >= (divisor >> 1)) { newLow++; } pack(result, newLow, 0, isNegative(decimal)); return; } // Scales down for 10**rescaleFactor. // Because divide by int has limited divisor, we choose code path with the least amount of divisions if ((scaleFactor - 1) / MAX_POWER_OF_FIVE_INT < (scaleFactor - 1) / MAX_POWER_OF_TEN_INT) { // scale down for 10**rescale is equivalent to scaling down with 5**rescaleFactor first, then with 2**rescaleFactor scaleDownFive(decimal, scaleFactor, result); shiftRightRoundUp(result, scaleFactor, result); } else { scaleDownTenRoundUp(decimal, scaleFactor, result); } }
private static void scaleDownTruncate(Slice decimal, int scaleFactor, Slice result) { // optimized path for smaller values long low = getLong(decimal, 0); long high = getLong(decimal, 1); if (scaleFactor <= MAX_POWER_OF_TEN_LONG && high == 0 && low >= 0) { long divisor = longTenToNth(scaleFactor); long newLow = low / divisor; pack(result, newLow, 0, isNegative(decimal)); return; } // Scales down for 10**rescaleFactor. // Because divide by int has limited divisor, we choose code path with the least amount of divisions if ((scaleFactor - 1) / MAX_POWER_OF_FIVE_INT < (scaleFactor - 1) / MAX_POWER_OF_TEN_INT) { // scale down for 10**rescale is equivalent to scaling down with 5**rescaleFactor first, then with 2**rescaleFactor scaleDownFive(decimal, scaleFactor, result); shiftRightTruncate(result, scaleFactor, result); } else { scaleDownTenTruncate(decimal, scaleFactor, result); } }
@LiteralParameters({"p", "s", "rp"}) @SqlType("decimal(rp, s)") @Constraint(variable = "rp", expression = "min(38, p + 1)") public static long roundNShort( @LiteralParameter("p") long numPrecision, @LiteralParameter("s") long numScale, @SqlType("decimal(p, s)") long num, @SqlType(StandardTypes.INTEGER) long decimals) { if (num == 0 || numPrecision - numScale + decimals <= 0) { return 0; } if (decimals >= numScale) { return num; } if (num < 0) { return -roundNShort(numPrecision, numScale, -num, decimals); } long rescaleFactor = longTenToNth((int) (numScale - decimals)); long remainder = num % rescaleFactor; int roundUp = (remainder >= rescaleFactor / 2) ? 1 : 0; return (num / rescaleFactor + roundUp) * rescaleFactor; }
private static SqlScalarFunction castFunctionFromDecimalTo(TypeSignature to, String... methodNames) { Signature signature = Signature.builder() .kind(SCALAR) .operatorType(CAST) .argumentTypes(parseTypeSignature("decimal(precision,scale)", ImmutableSet.of("precision", "scale"))) .returnType(to) .build(); return SqlScalarFunction.builder(DecimalCasts.class) .signature(signature) .deterministic(true) .choice(choice -> choice .implementation(methodsGroup -> methodsGroup .methods(methodNames) .withExtraParameters((context) -> { long precision = context.getLiteral("precision"); long scale = context.getLiteral("scale"); Number tenToScale; if (isShortDecimal(context.getParameterTypes().get(0))) { tenToScale = longTenToNth(intScale(scale)); } else { tenToScale = bigIntegerTenToNth(intScale(scale)); } return ImmutableList.of(precision, scale, tenToScale); }))) .build(); }
private static SqlScalarFunction castFunctionToDecimalFromBuilder(TypeSignature from, boolean nullableResult, String... methodNames) { Signature signature = Signature.builder() .kind(SCALAR) .operatorType(CAST) .argumentTypes(from) .returnType(parseTypeSignature("decimal(precision,scale)", ImmutableSet.of("precision", "scale"))) .build(); return SqlScalarFunction.builder(DecimalCasts.class) .signature(signature) .deterministic(true) .choice(choice -> choice .nullableResult(nullableResult) .implementation(methodsGroup -> methodsGroup .methods(methodNames) .withExtraParameters((context) -> { DecimalType resultType = (DecimalType) context.getReturnType(); Number tenToScale; if (isShortDecimal(resultType)) { tenToScale = longTenToNth(resultType.getScale()); } else { tenToScale = bigIntegerTenToNth(resultType.getScale()); } return ImmutableList.of(resultType.getPrecision(), resultType.getScale(), tenToScale); }))).build(); }
public static long rescale(long value, int fromScale, int toScale) { if (toScale < fromScale) { throw new IllegalArgumentException("target scale must be larger than source scale"); } return value * longTenToNth(toScale - fromScale); }
public static boolean overflows(long value, int precision) { if (precision > MAX_SHORT_PRECISION) { throw new IllegalArgumentException("expected precision to be less than " + MAX_SHORT_PRECISION); } return abs(value) >= longTenToNth(precision); }
private static void scaleDownTruncate(Slice decimal, int scaleFactor, Slice result) { // optimized path for smaller values long low = getLong(decimal, 0); long high = getLong(decimal, 1); if (scaleFactor <= MAX_POWER_OF_TEN_LONG && high == 0 && low >= 0) { long divisor = longTenToNth(scaleFactor); long newLow = low / divisor; pack(result, newLow, 0, isNegative(decimal)); return; } // Scales down for 10**rescaleFactor. // Because divide by int has limited divisor, we choose code path with the least amount of divisions if ((scaleFactor - 1) / MAX_POWER_OF_FIVE_INT < (scaleFactor - 1) / MAX_POWER_OF_TEN_INT) { // scale down for 10**rescale is equivalent to scaling down with 5**rescaleFactor first, then with 2**rescaleFactor scaleDownFive(decimal, scaleFactor, result); shiftRightTruncate(result, scaleFactor, result); } else { scaleDownTenTruncate(decimal, scaleFactor, result); } }
private static void scaleDownRoundUp(Slice decimal, int scaleFactor, Slice result) { // optimized path for smaller values long low = getLong(decimal, 0); long high = getLong(decimal, 1); if (scaleFactor <= MAX_POWER_OF_TEN_LONG && high == 0 && low >= 0) { long divisor = longTenToNth(scaleFactor); long newLow = low / divisor; if (low % divisor >= (divisor >> 1)) { newLow++; } pack(result, newLow, 0, isNegative(decimal)); return; } // Scales down for 10**rescaleFactor. // Because divide by int has limited divisor, we choose code path with the least amount of divisions if ((scaleFactor - 1) / MAX_POWER_OF_FIVE_INT < (scaleFactor - 1) / MAX_POWER_OF_TEN_INT) { // scale down for 10**rescale is equivalent to scaling down with 5**rescaleFactor first, then with 2**rescaleFactor scaleDownFive(decimal, scaleFactor, result); shiftRightRoundUp(result, scaleFactor, result); } else { scaleDownTenRoundUp(decimal, scaleFactor, result); } }