Skip to content

Commit

Permalink
Add support for TRUNCATE function for DOUBLE and REAL
Browse files Browse the repository at this point in the history
  • Loading branch information
fgwang7w authored and Rongrong Zhong committed Oct 13, 2020
1 parent 4631b6d commit f2965f6
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
10 changes: 10 additions & 0 deletions presto-docs/src/main/sphinx/functions/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ Mathematical Functions

Returns ``x`` rounded to integer by dropping digits after decimal point.

.. function:: truncate(x, n) -> double

Returns ``x`` truncated to ``n`` decimal places.
``n`` can be negative to truncate ``n`` digits left of the decimal point.

Example:
``truncate(REAL '12.333', -1)`` -> result is 10.0
``truncate(REAL '12.333', 0)`` -> result is 12.0
``truncate(REAL '12.333', 1)`` -> result is 12.3

.. function:: width_bucket(x, bound1, bound2, n) -> bigint

Returns the bin number of ``x`` in an equi-width histogram with the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.commons.math3.distribution.BetaDistribution;
import org.apache.commons.math3.special.Erf;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.ThreadLocalRandom;

Expand Down Expand Up @@ -327,6 +328,49 @@ public static long truncate(@SqlType(StandardTypes.REAL) long num)
return floatToRawIntBits((float) (Math.signum(numInFloat) * Math.floor(Math.abs(numInFloat))));
}

@Description("truncate to double by dropping digits after decimal point")
@ScalarFunction
@SqlType(StandardTypes.DOUBLE)
public static double truncate(@SqlType(StandardTypes.DOUBLE) double num, @SqlType(StandardTypes.INTEGER) long decimals)
{
if (Double.isNaN(num) || Double.isInfinite(num)) {
// compatible with truncate(DOUBLE)
return num;
}
if (decimals == 0) {
if (num >= 0) {
return Math.floor(num);
}
else {
return Math.ceil(num);
}
}

return BigDecimal.valueOf(num).setScale((int) decimals, BigDecimal.ROUND_DOWN).doubleValue();
}

@Description("truncate to float by dropping digits after decimal point")
@ScalarFunction
@SqlType(StandardTypes.REAL)
public static long truncate(@SqlType(StandardTypes.REAL) long num, @SqlType(StandardTypes.INTEGER) long decimals)
{
float numBitsToFloats = intBitsToFloat((int) num);
if (Float.isNaN(numBitsToFloats) || Float.isInfinite(numBitsToFloats)) {
// compatible with truncate(REAL)
return num;
}
if (decimals == 0) {
if (numBitsToFloats >= 0) {
return floatToRawIntBits((float) Math.floor(numBitsToFloats));
}
else {
return floatToRawIntBits((float) Math.ceil(numBitsToFloats));
}
}

return floatToRawIntBits(new BigDecimal(Float.toString(numBitsToFloats)).setScale((int) decimals, BigDecimal.ROUND_DOWN).floatValue());
}

@Description("cosine")
@ScalarFunction
@SqlType(StandardTypes.DOUBLE)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.operator.scalar;

import org.testng.annotations.Test;

import static com.facebook.presto.common.type.DoubleType.DOUBLE;
import static com.facebook.presto.common.type.RealType.REAL;

public class TestTruncateWithPrecision
extends AbstractTestFunctions
{
@Test
public void testTruncate()
{
// TRUNCATE DOUBLE -> DOUBLE
assertFunction("truncate(nan(),-1)", DOUBLE, Double.NaN);
assertFunction("truncate(infinity(),1)", DOUBLE, Double.POSITIVE_INFINITY);
assertFunction("truncate(-infinity(),1)", DOUBLE, Double.NEGATIVE_INFINITY);
assertFunction("truncate(DOUBLE '17.1', -1)", DOUBLE, 10.0);
assertFunction("truncate(DOUBLE '1234.56', 1)", DOUBLE, 1234.5);
assertFunction("truncate(DOUBLE '1234.56', 0)", DOUBLE, 1234.0);
assertFunction("truncate(DOUBLE '-1234.56', 0)", DOUBLE, -1234.0);
assertFunction("truncate(DOUBLE '-1234.56', -500)", DOUBLE, 0.0);
assertFunction("truncate(DOUBLE '1234.567', 2)", DOUBLE, 1234.56);
assertFunction("truncate(DOUBLE '1234.567', 2)", DOUBLE, 1234.56);
assertFunction("truncate(DOUBLE '" + Double.MAX_VALUE + "', -408)", DOUBLE, 0.0);
assertFunction("truncate(DOUBLE '" + -Double.MAX_VALUE / 10 + "', 408)", DOUBLE, -Double.MAX_VALUE / 10);
assertFunction("truncate(DOUBLE '" + (double) Long.MAX_VALUE + "', -15)", DOUBLE, 9.223E18);

// TRUNCATE REAL -> REAL

assertFunction("truncate(REAL '12.333', 0)", REAL, 12.0f);
assertFunction("truncate(REAL '-12.333', 0)", REAL, -12.0f);
assertFunction("truncate(REAL '12.123456789011234567892', 10)", REAL, 12.12345695499999f);
assertFunction("truncate(REAL '12.333', -1)", REAL, 10.0f);
assertFunction("truncate(REAL '12.333', -500)", REAL, 0.0f);
assertFunction("truncate(REAL '3.40287e37', -35)", REAL, 3.4E37f);
assertFunction("truncate(REAL '3.40287e37', -488)", REAL, 0.0f);
assertFunction("truncate(REAL '" + (float) Long.MAX_VALUE + "', -15)", REAL, 9.223E18f);
}
}

0 comments on commit f2965f6

Please sign in to comment.