Skip to content

Commit

Permalink
add inverse_cauchy_cdf
Browse files Browse the repository at this point in the history
  • Loading branch information
wills-feng committed Apr 22, 2024
1 parent f51e34d commit 852bdf4
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
4 changes: 4 additions & 0 deletions velox/docs/functions/presto/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ Probability Functions: inverse_cdf
probability (p): P(N < n). The a, b parameters must be positive real values (all of type DOUBLE).
The probability p must lie on the interval [0, 1].

.. function:: inverse_cauchy_cdf(median, scale, p) → double#

Compute the inverse of the Cauchy cdf with given parameters median and scale (gamma) for the probability p.
The scale parameter must be a positive double. The probability p must be a double on the interval [0, 1].

====================================
Statistical Functions
Expand Down
31 changes: 31 additions & 0 deletions velox/functions/prestosql/Probability.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
#pragma once

#include <boost/math/distributions.hpp>
#include <boost/math/distributions/cauchy.hpp>
#include <boost/math/distributions/laplace.hpp>
#include <boost/math/distributions/weibull.hpp>
#include "boost/math/distributions/beta.hpp"
Expand Down Expand Up @@ -249,5 +251,34 @@ struct WeibullCDFFunction {
}
};

template <typename T>
struct InverseCauchyCDFFunction {
VELOX_DEFINE_FUNCTION_TYPES(T);
FOLLY_ALWAYS_INLINE void
call(double& result, double median, double scale, double p) {
static constexpr double kInf = std::numeric_limits<double>::infinity();
static constexpr double kDoubleMax = std::numeric_limits<double>::max();
static constexpr double kNan = std::numeric_limits<double>::quiet_NaN();

VELOX_USER_CHECK(p >= 0 && p <= 1, "p must be in the interval [0, 1]");
VELOX_USER_CHECK_GT(scale, 0, "scale must be greater than 0");

if (p == 1.0) {
result = kInf;
} else if (scale == kInf) {
result = median;
} else if (std::isnan(median)) {
result = kNan;
} else if (median == kInf || median == kDoubleMax) {
result = kInf;
} else if (median == -kInf || median == -kDoubleMax) {
result = 0.0;
} else {
boost::math::cauchy_distribution<> cauchyDist(median, scale);
result = boost::math::quantile(cauchyDist, p);
}
}
};

} // namespace
} // namespace facebook::velox::functions
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ void registerSimpleFunctions(const std::string& prefix) {
Map<Varchar, double>>({prefix + "cosine_similarity"});
registerFunction<WeibullCDFFunction, double, double, double, double>(
{prefix + "weibull_cdf"});
registerFunction<InverseCauchyCDFFunction, double, double, double, double>(
{prefix + "inverse_cauchy_cdf"});
}

} // namespace
Expand Down
24 changes: 24 additions & 0 deletions velox/functions/prestosql/tests/ProbabilityTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,5 +453,29 @@ TEST_F(ProbabilityTest, weibullCDF) {
weibullCDF(kDoubleMin, kNan, kDoubleMax), "b must be greater than 0");
}

TEST_F(ProbabilityTest, inverseCauchyCDF) {
const auto cauchyInvCDF = [&](std::optional<double> median,
std::optional<double> scale,
std::optional<double> p) {
return evaluateOnce<double>(
"inverse_cauchy_cdf(c0, c1, c2)", median, scale, p);
};

EXPECT_EQ(cauchyInvCDF(0.0, 1.0, 0.5), 0.0);
EXPECT_EQ(cauchyInvCDF(2.5, 1.0, 0.64758361765043326), 3.0);
EXPECT_EQ(cauchyInvCDF(5.0, 2.0, 1.0), kInf);
EXPECT_EQ(cauchyInvCDF(5.0, kInf, 0.5), 5.0);
EXPECT_EQ(cauchyInvCDF(kInf, 2.0, 0.5), kInf);
EXPECT_EQ(cauchyInvCDF(kDoubleMax, 2.0, 0.5), kInf);
EXPECT_EQ(cauchyInvCDF(-kInf, 1.0, 0.5), 0);
EXPECT_EQ(cauchyInvCDF(-kDoubleMax, 1.0, 0.5), 0);
VELOX_ASSERT_THROW(
cauchyInvCDF(1.0, 1.0, kNan), "p must be in the interval [0, 1]");
VELOX_ASSERT_THROW(
cauchyInvCDF(1.0, 1.0, 9), "p must be in the interval [0, 1]");
VELOX_ASSERT_THROW(cauchyInvCDF(0, -1, 0.5), "scale must be greater than 0");
EXPECT_THAT(cauchyInvCDF(kNan, 1.0, 0.5), IsNan());
}

} // namespace
} // namespace facebook::velox

0 comments on commit 852bdf4

Please sign in to comment.