mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
PR 681: Add ndtri function, the inverse of the normal distribution function.
This commit is contained in:
@@ -1069,6 +1069,66 @@ void test_gpu_erfc(const Scalar stddev)
|
||||
gpuFree(d_out);
|
||||
}
|
||||
#endif
|
||||
template <typename Scalar>
|
||||
void test_gpu_ndtri()
|
||||
{
|
||||
Tensor<Scalar, 1> in_x(8);
|
||||
Tensor<Scalar, 1> out(8);
|
||||
Tensor<Scalar, 1> expected_out(8);
|
||||
out.setZero();
|
||||
|
||||
in_x(0) = Scalar(1);
|
||||
in_x(1) = Scalar(0.);
|
||||
in_x(2) = Scalar(0.5);
|
||||
in_x(3) = Scalar(0.2);
|
||||
in_x(4) = Scalar(0.8);
|
||||
in_x(5) = Scalar(0.9);
|
||||
in_x(6) = Scalar(0.1);
|
||||
in_x(7) = Scalar(0.99);
|
||||
in_x(8) = Scalar(0.01);
|
||||
|
||||
expected_out(0) = std::numeric_limits<Scalar>::infinity();
|
||||
expected_out(1) = -std::numeric_limits<Scalar>::infinity();
|
||||
expected_out(2) = Scalar(0.0);
|
||||
expected_out(3) = Scalar(-0.8416212335729142);
|
||||
expected_out(4) = Scalar(0.8416212335729142);j
|
||||
expected_out(5) = Scalar(1.2815515655446004);
|
||||
expected_out(6) = Scalar(-1.2815515655446004);
|
||||
expected_out(7) = Scalar(2.3263478740408408);
|
||||
expected_out(8) = Scalar(-2.3263478740408408);
|
||||
|
||||
std::size_t bytes = in_x.size() * sizeof(Scalar);
|
||||
|
||||
Scalar* d_in_x;
|
||||
Scalar* d_out;
|
||||
gpuMalloc((void**)(&d_in_x), bytes);
|
||||
gpuMalloc((void**)(&d_out), bytes);
|
||||
|
||||
gpuMemcpy(d_in_x, in_x.data(), bytes, gpuMemcpyHostToDevice);
|
||||
|
||||
Eigen::GpuStreamDevice stream;
|
||||
Eigen::GpuDevice gpu_device(&stream);
|
||||
|
||||
Eigen::TensorMap<Eigen::Tensor<Scalar, 1> > gpu_in_x(d_in_x, 6);
|
||||
Eigen::TensorMap<Eigen::Tensor<Scalar, 1> > gpu_out(d_out, 6);
|
||||
|
||||
gpu_out.device(gpu_device) = gpu_in_x.ndtri();
|
||||
|
||||
assert(gpuMemcpyAsync(out.data(), d_out, bytes, gpuMemcpyDeviceToHost, gpu_device.stream()) == gpuSuccess);
|
||||
assert(gpuStreamSynchronize(gpu_device.stream()) == gpuSuccess);
|
||||
|
||||
VERIFY_IS_EQUAL(out(0), expected_out(0));
|
||||
VERIFY((std::isnan)(out(3)));
|
||||
|
||||
for (int i = 1; i < 6; ++i) {
|
||||
if (i != 3) {
|
||||
VERIFY_IS_APPROX(out(i), expected_out(i));
|
||||
}
|
||||
}
|
||||
|
||||
gpuFree(d_in_x);
|
||||
gpuFree(d_out);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void test_gpu_betainc()
|
||||
@@ -1538,6 +1598,10 @@ EIGEN_DECLARE_TEST(cxx11_tensor_gpu)
|
||||
|
||||
#if !defined(EIGEN_USE_HIP)
|
||||
// disable these tests on HIP for now.
|
||||
|
||||
CALL_SUBTEST_5(test_gpu_ndtri<float>());
|
||||
CALL_SUBTEST_5(test_gpu_ndtri<double>());
|
||||
|
||||
CALL_SUBTEST_5(test_gpu_digamma<float>());
|
||||
CALL_SUBTEST_5(test_gpu_digamma<double>());
|
||||
|
||||
|
||||
@@ -133,6 +133,26 @@ template<typename ArrayType> void array_special_functions()
|
||||
}
|
||||
#endif // EIGEN_HAS_C99_MATH
|
||||
|
||||
// Check the ndtri function against scipy.special.ndtri
|
||||
{
|
||||
ArrayType x(7), res(7), ref(7);
|
||||
x << 0.5, 0.2, 0.8, 0.9, 0.1, 0.99, 0.01;
|
||||
ref << 0., -0.8416212335729142, 0.8416212335729142, 1.2815515655446004, -1.2815515655446004, 2.3263478740408408, -2.3263478740408408;
|
||||
CALL_SUBTEST( verify_component_wise(ref, ref); );
|
||||
CALL_SUBTEST( res = x.ndtri(); verify_component_wise(res, ref); );
|
||||
CALL_SUBTEST( res = ndtri(x); verify_component_wise(res, ref); );
|
||||
|
||||
// ndtri(normal_cdf(x)) ~= x
|
||||
CALL_SUBTEST(
|
||||
ArrayType m1 = ArrayType::Random(32);
|
||||
using std::sqrt;
|
||||
|
||||
ArrayType cdf_val = (m1 / sqrt(2.)).erf();
|
||||
cdf_val = (cdf_val + 1.) / 2.;
|
||||
verify_component_wise(cdf_val.ndtri(), m1););
|
||||
|
||||
}
|
||||
|
||||
// Check the zeta function against scipy.special.zeta
|
||||
{
|
||||
ArrayType x(7), q(7), res(7), ref(7);
|
||||
|
||||
Reference in New Issue
Block a user