blob: 45a9f7e399ec5464ac0f85949346408958581230 [file] [log] [blame]
// Distributed under 3-clause BSD license with permission from the author,
// see https://lists.debian.org/debian-legal/2004/12/msg00295.html
//
// Cephes Math Library Release 2.8: June, 2000
//
// Copyright 1984, 1995, 2000 by Stephen L. Moshier
//
// This software is derived from the Cephes Math Library and is
// incorporated herein by permission of the author.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// Note: The file inverse_gaussian_cdf.cc is a rewrite of the implementation
// of the ndtri function in the cephes library. It is not a copy; modification
// was permitted by the author under the above license. The original file can be
// found here: https://netlib.org/cephes/doubldoc.html#ndtri
#include "third_party/cephes/inverse_gaussian_cdf.h"
#include <cstdlib>
#include <limits>
#include "gtest/gtest.h"
namespace differential_privacy::third_party::cephes {
namespace {
TEST(InverseCdfStandardGaussianTest, InputZeroReturnsNagativeInfinity) {
EXPECT_EQ(InverseCdfStandardGaussian(0.0),
-std::numeric_limits<double>::infinity());
}
TEST(InverseCdfStandardGaussianTest, InputOneReturnsInfinity) {
EXPECT_EQ(InverseCdfStandardGaussian(1.0),
std::numeric_limits<double>::infinity());
}
TEST(InverseCdfStandardGaussianTest, VerifiesThatMedianOfGaussianIsZero) {
EXPECT_NEAR(InverseCdfStandardGaussian(0.5), 0, 1E-15);
}
struct InputOutput {
double input;
double expected_output;
};
using InverseCdfStandardGaussianIoTest = ::testing::TestWithParam<InputOutput>;
TEST_P(InverseCdfStandardGaussianIoTest, RelativeAccuracy) {
const InputOutput& test_case = GetParam();
double output = InverseCdfStandardGaussian(test_case.input);
double relative_accuracy = std::abs((output - test_case.expected_output) /
test_case.expected_output);
EXPECT_NEAR(0.0, relative_accuracy, 1e-15);
}
// Listing a number of correct input/output pairs.
// The values were generated by the following python code:
//
// from scipy.stats import norm
// from numpy.random import uniform
//
// numbers_per_order = 2
//
// # p close to 1, st. 1-p is of order 10**(-i)
// # Due to rounding errors, this has limitations
// for i in range(1,14):
// for j in range(numbers_per_order):
// rand = uniform(1-10**(-i), 1)
// print("{%.18e, %.18f}," % (rand, norm.ppf(rand)))
//
// # p close to 0, st. p is of order 10**(-i)
// for i in [0, 1, 2, 4, 8, 15, 16, 17, 32, 64, 128, 256, 300]:
// for j in range(numbers_per_order):
// rand = uniform(0.1, 1) * 10**(-i)
// print("{%.18e, %.18f}," % (rand, norm.ppf(rand)))
INSTANTIATE_TEST_SUITE_P(
RelativeAccuracyTest, InverseCdfStandardGaussianIoTest,
testing::ValuesIn<InputOutput>({
{9.590875421333870943e-01, 1.740194245526870631},
{9.204728130878864212e-01, 1.408259059429154192},
{9.987822916403579221e-01, 3.031252275870897073},
{9.925605599510384236e-01, 2.435313800480054969},
{9.990447702229799942e-01, 3.103810031034545780},
{9.996763629885648816e-01, 3.410990265746212557},
{9.999886033679458164e-01, 4.235609454156513465},
{9.999760495761819135e-01, 4.065639908388418711},
{9.999918285209185020e-01, 4.309763019113548310},
{9.999949297010878313e-01, 4.414153527077065320},
{9.999995741498048929e-01, 4.923131819830989464},
{9.999997043019083209e-01, 4.994005806628707411},
{9.999999930150607064e-01, 5.673757581075118850},
{9.999999627780953304e-01, 5.380101608071190533},
{9.999999977551378150e-01, 5.865059216395640540},
{9.999999987822485448e-01, 5.965724924667977547},
{9.999999996778887734e-01, 6.179212230118906746},
{9.999999995927016938e-01, 6.142056907043477842},
{9.999999999050942501e-01, 6.369365733005997399},
{9.999999999612441126e-01, 6.505351784059330456},
{9.999999999965828446e-01, 6.861077421111833274},
{9.999999999911421966e-01, 6.723709001398219698},
{9.999999999990811794e-01, 7.046280136673924055},
{9.999999999995440314e-01, 7.143183551114592689},
{9.999999999999484857e-01, 7.436960043545139065},
{9.999999999999442668e-01, 7.426550452501929911},
{7.078202134622706421e-01, 0.547027887498922949},
{3.389657500740557161e-01, -0.415287432523317290},
{5.957715702260371615e-02, -1.558333067730558463},
{7.814884269185563836e-02, -1.417633872953655949},
{7.031239497917323583e-03, -2.455663440450241986},
{1.539105641403513232e-03, -2.959817704299271046},
{4.308036802518321198e-05, -3.926584208482659655},
{4.792417534760087735e-05, -3.900868137755500342},
{4.463560376039031862e-09, -5.749947420065786297},
{4.134037552039715277e-09, -5.762900076062255295},
{4.483536530421512750e-16, -8.040229004994209561},
{3.339983254697393151e-16, -8.076230307018560595},
{6.215336569124182823e-17, -8.278911061075142186},
{9.601065568608536918e-17, -8.226962019547366722},
{6.991559520245878977e-18, -8.535267778973684827},
{7.798272601053520958e-18, -8.522633695927112285},
{9.753826112572825312e-33, -11.858220714899207593},
{7.239945717749332110e-33, -11.883153923605899394},
{3.081878658827924595e-65, -17.016810944246216764},
{5.854299805089005594e-65, -16.979192464465175050},
{8.217571054262086351e-129, -24.117363860470103276},
{5.940660698416777152e-129, -24.130790266655189669},
{7.104594771285924014e-257, -34.215527373144254852},
{5.222691495369919695e-257, -34.224512368673167373},
{9.255861729918001973e-301, -37.049182013454569073},
{5.918562407887116857e-301, -37.061240736056291212},
}));
} // namespace
} // namespace differential_privacy::third_party::cephes