2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-24 18:12:09 +00:00
Files
math/test/test_pow1p.cpp
2024-08-26 09:57:02 -04:00

123 lines
3.7 KiB
C++

// (C) Copyright Matt Borland 2024.
// (C) Copyrigh Fancidev 2024.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/math/special_functions/pow1p.hpp>
#include <boost/math/concepts/real_concept.hpp>
#include <exception>
#include <random>
#if __has_include(<stdfloat>) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
# include <stdfloat>
#endif
#include "math_unit_test.hpp"
template <typename T>
void test()
{
using std::pow;
// First we hit all the special cases
// pow(x, +/-0)
CHECK_EQUAL(boost::math::pow1p(T(1), T(0)), T(1));
// pow(0, y)
#ifndef BOOST_MATH_NO_EXCEPTIONS
CHECK_THROW(boost::math::pow1p(T(-1), T(-1)), std::domain_error);
#endif
CHECK_EQUAL(boost::math::pow1p(T(-1), T(1)), T(0));
// pow(-1, inf)
CHECK_EQUAL(boost::math::pow1p(T(-2), boost::math::numeric_limits<T>::infinity()), T(1));
// pow(1, y)
CHECK_EQUAL(boost::math::pow1p(T(0), T(2)), T(1));
// pow(x, +/-inf)
BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<T>::has_infinity)
{
CHECK_EQUAL(boost::math::pow1p(T(5), -boost::math::numeric_limits<T>::infinity()), T(0));
CHECK_EQUAL(boost::math::pow1p(T(5), boost::math::numeric_limits<T>::infinity()), boost::math::numeric_limits<T>::infinity());
// pow(+/-inf, y)
CHECK_EQUAL(boost::math::pow1p(boost::math::numeric_limits<T>::infinity(), T(2)), boost::math::numeric_limits<T>::infinity());
CHECK_EQUAL(boost::math::pow1p(-boost::math::numeric_limits<T>::infinity(), T(2)), boost::math::numeric_limits<T>::infinity());
}
// NANs for x and y
BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<T>::has_quiet_NaN)
{
CHECK_EQUAL(boost::math::isnan(boost::math::pow1p(boost::math::numeric_limits<T>::quiet_NaN(), T(1))), true);
CHECK_EQUAL(boost::math::isnan(boost::math::pow1p(T(1), boost::math::numeric_limits<T>::quiet_NaN())), true);
}
// pow(x, +/-1)
CHECK_ULP_CLOSE(boost::math::pow1p(T(2), T(1)), pow(T(3), T(1)), 10);
CHECK_ULP_CLOSE(boost::math::pow1p(T(2), T(-1)), pow(T(3), T(-1)), 10);
// (1+x) < 0
CHECK_ULP_CLOSE(boost::math::pow1p(T(-3), T(2)), pow(T(-2), T(2)), 10);
// x < 0
std::mt19937_64 rng;
std::uniform_real_distribution<double> dist (-1, 0);
std::uniform_real_distribution<double> dist_y (0, 10);
constexpr int N = 1024;
for (int i = 0; i < N; ++i)
{
const auto x = static_cast<T>(dist(rng));
const auto y = static_cast<T>(dist_y(rng));
CHECK_ULP_CLOSE(boost::math::pow1p(x, y), pow(x + 1, y), 100);
}
// 0 < x < 1
std::uniform_real_distribution<double> dist_x_1(0, 1);
for (int i = 0; i < N; ++i)
{
const auto x = static_cast<T>(dist_x_1(rng));
const auto y = static_cast<T>(dist_y(rng));
CHECK_ULP_CLOSE(boost::math::pow1p(x, y), pow(x + 1, y), 100);
}
// Else
std::uniform_real_distribution<double> dist_other_x(1, 1000);
for (int i = 0; i < N; ++i)
{
const auto x = static_cast<T>(dist_other_x(rng));
const auto y = static_cast<T>(dist_y(rng));
CHECK_ULP_CLOSE(boost::math::pow1p(x, y), pow(x + 1, y), 100);
}
}
int main()
{
#ifdef __STDCPP_FLOAT32_T__
test<std::float32_t>();
#else
test<float>();
#endif
#ifdef __STDCPP_FLOAT64_T__
test<std::float64_t>();
#else
test<double>();
#endif
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
test<long double>();
#endif
#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
test<boost::math::concepts::real_concept>();
#endif
return boost::math::test::report_errors();
}