diff --git a/presto-docs/src/main/sphinx/functions/math.rst b/presto-docs/src/main/sphinx/functions/math.rst index a26a312fd8db8..b3623502e502e 100644 --- a/presto-docs/src/main/sphinx/functions/math.rst +++ b/presto-docs/src/main/sphinx/functions/math.rst @@ -266,9 +266,14 @@ Probability Functions: cdf Compute the Poisson cdf with given lambda (mean) parameter: P(N <= value; lambda). The lambda parameter must be a positive real number (of type DOUBLE) and value must be a non-negative integer. +.. function:: t_cdf(df, value) -> double + + Compute the Student's t cdf with given degrees of freedom: P(N < value; df). + The degrees of freedom must be a positive real number and value must be a real value. + .. function:: weibull_cdf(a, b, value) -> double - Compute the Weibull cdf with given parameters a, b: P(N <= value). The ``a`` + Compute the Weibull cdf with given parameters a, b: P(N <= value). The ``a`` and ``b`` parameters must be positive doubles and ``value`` must also be a double. @@ -332,6 +337,12 @@ Probability Functions: inverse_cdf The lambda parameter must be a positive real number (of type DOUBLE). The probability p must lie on the interval [0, 1). +.. function:: inverse_t_cdf(df, p) -> double + + Compute the inverse of the Student's t cdf with given degrees of freedom for the cumulative + probability (p): P(N < n). The degrees of freedom must be a positive real value. + The probability p must lie on the interval [0, 1]. + .. function:: inverse_weibull_cdf(a, b, p) -> double Compute the inverse of the Weibull cdf with given parameters ``a``, ``b`` for the probability ``p``. diff --git a/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/MathFunctions.java b/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/MathFunctions.java index 1bdd52292b2f7..9d6048f484b83 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/MathFunctions.java +++ b/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/MathFunctions.java @@ -39,6 +39,7 @@ import org.apache.commons.math3.distribution.GammaDistribution; import org.apache.commons.math3.distribution.LaplaceDistribution; import org.apache.commons.math3.distribution.PoissonDistribution; +import org.apache.commons.math3.distribution.TDistribution; import org.apache.commons.math3.distribution.WeibullDistribution; import org.apache.commons.math3.special.Erf; @@ -981,6 +982,31 @@ public static double poissonCdf( return distribution.cumulativeProbability((int) value); } + @Description("inverse of Student's t cdf given degrees of freedom and probability") + @ScalarFunction + @SqlType(StandardTypes.DOUBLE) + public static double inverseTCdf( + @SqlType(StandardTypes.DOUBLE) double df, + @SqlType(StandardTypes.DOUBLE) double p) + { + checkCondition(df > 0, INVALID_FUNCTION_ARGUMENT, "df must be greater than 0"); + checkCondition(p >= 0.0 && p <= 1.0, INVALID_FUNCTION_ARGUMENT, "p must be in the interval [0, 1]"); + TDistribution distribution = new TDistribution(null, df, TDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY); + return distribution.inverseCumulativeProbability(p); + } + + @Description("Student's t cdf given degrees of freedom and value") + @ScalarFunction + @SqlType(StandardTypes.DOUBLE) + public static double tCdf( + @SqlType(StandardTypes.DOUBLE) double df, + @SqlType(StandardTypes.DOUBLE) double value) + { + checkCondition(df > 0, INVALID_FUNCTION_ARGUMENT, "df must be greater than 0"); + TDistribution distribution = new TDistribution(null, df, TDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY); + return distribution.cumulativeProbability(value); + } + @Description("Inverse of Weibull cdf given a, b parameters and probability") @ScalarFunction @SqlType(StandardTypes.DOUBLE) diff --git a/presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestMathFunctions.java b/presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestMathFunctions.java index fc0802b280756..1e2902fa42607 100644 --- a/presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestMathFunctions.java +++ b/presto-main-base/src/test/java/com/facebook/presto/operator/scalar/TestMathFunctions.java @@ -1809,6 +1809,31 @@ public void testPoissonCdf() assertInvalidFunction("poisson_cdf(3, -10)", "poissonCdf Function: value must be a non-negative integer"); } + @Test + public void testInverseTCdf() + { + assertFunction("inverse_t_cdf(1000, 0.5)", DOUBLE, 0.0); + assertFunction("inverse_t_cdf(1000, 0.0)", DOUBLE, Double.NEGATIVE_INFINITY); + assertFunction("inverse_t_cdf(1000, 1.0)", DOUBLE, Double.POSITIVE_INFINITY); + + assertInvalidFunction("inverse_t_cdf(0, 0.5)", "df must be greater than 0"); + assertInvalidFunction("inverse_t_cdf(-1, 0.5)", "df must be greater than 0"); + assertInvalidFunction("inverse_t_cdf(3, -0.1)", "p must be in the interval [0, 1]"); + assertInvalidFunction("inverse_t_cdf(3, 1.1)", "p must be in the interval [0, 1]"); + } + + @Test + public void testTCdf() + throws Exception + { + assertFunction("t_cdf(1000, 0.0)", DOUBLE, 0.5); + assertFunction("t_cdf(1000, infinity())", DOUBLE, 1.0); + assertFunction("t_cdf(1000, -infinity())", DOUBLE, 0.0); + + assertInvalidFunction("t_cdf(0, 0.5)", "df must be greater than 0"); + assertInvalidFunction("t_cdf(-1, 0.5)", "df must be greater than 0"); + } + @Test public void testInverseWeibullCdf() {