Closed
Description
Hi @jzmaddock , I followed your advice to use float_distance when measuring ULP error. I have implemented this check. For nearly all functions it was enough to set tolerance of 8 ULP with two notable excepions: real part of tan
and imag part of tanh
functions. See the pipeline warnings (scroll up the output to around line 360):
- for float128
- for mpfr
- and for cpp_bin_float there are w few more errors.
Here is a short snippet to reproduce these errors:
#include <boost/core/demangle.hpp>
#include <boost/math/complex.hpp>
#include <boost/math/special_functions.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/mpfr.hpp>
#include <iostream>
template <typename T, typename Ref> void test()
{
bool first = true;
for (T x = -10.; x < 10.; x += 0.25)
for (T y = -10.; y < 10.; y += 0.25) {
std::complex<T> z(x, y);
std::complex<Ref> r(static_cast<Ref>(x), static_cast<Ref>(y));
using boost::multiprecision::tan;
using boost::multiprecision::tanh;
auto z_tan = tan(z).real();
auto r_tan = tan(r).real();
auto z_tanh = tanh(z).imag();
auto r_tanh = tanh(r).imag();
if (first) {
std::cout << boost::core::demangle(typeid(decltype(z_tan)).name()) << "\n";
std::cout << boost::core::demangle(typeid(decltype(r_tan)).name()) << "\n";
first = false;
}
auto dist_tan = boost::math::float_distance(static_cast<T>(r_tan), z_tan);
auto dist_tanh = boost::math::float_distance(static_cast<T>(r_tanh), z_tanh);
if (dist_tan > 290000000)
std::cout << "tan error, args=" << z << " ULP dist=" << dist_tan << "\n";
if (dist_tanh > 290000000)
std::cout << "tanh error, args=" << z << " ULP dist=" << dist_tanh << "\n";
}
std::cout << "\n";
}
int main()
{
test<boost::multiprecision::float128, boost::multiprecision::mpfr_float_50>();
test<boost::multiprecision::mpfr_float_50, boost::multiprecision::mpfr_float_100>();
test<boost::multiprecision::mpfr_float_100, boost::multiprecision::mpfr_float_500>();
}
Here I print only ULP errors larger than 290000000, otherwise it's a real flood. And all other functions pass with ULP error < 8 (except for cpp_bin_float - there I've set the limit to 200 with some exceptions for tgamma and lgamma).
Looks like I have stumbled upon a pretty large bug :).
This sample program produces following output:
boost::multiprecision::number<boost::multiprecision::backends::float128_backend, (boost::multiprecision::expression_template_option)0>
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<50u, (boost::multiprecision::mpfr_allocation_type)1>, (boost::multiprecision::expression_template_option)1>
tanh error, args=(-10,-2.75) ULP dist=3.21107e+08
tanh error, args=(-10,3.25) ULP dist=3.36694e+08
tanh error, args=(-10,6.5) ULP dist=3.85652e+08
tanh error, args=(-9.75,-0.25) ULP dist=3.41471e+08
tan error, args=(-2.75,-10) ULP dist=3.21107e+08
tan error, args=(-0.25,-9.75) ULP dist=3.41471e+08
tan error, args=(-0.25,9.75) ULP dist=3.41471e+08
tan error, args=(3.25,-10) ULP dist=3.36694e+08
tan error, args=(6.5,-10) ULP dist=3.85652e+08
tanh error, args=(9.75,-0.25) ULP dist=3.41471e+08
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<50u, (boost::multiprecision::mpfr_allocation_type)1>, (boost::multiprecision::expression_template_option)1>
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<100u, (boost::multiprecision::mpfr_allocation_type)1>, (boost::multiprecision::expression_template_option)1>
tanh error, args=(-10,-7.75) ULP dist=2.90069e+08
tan error, args=(-7.75,-10) ULP dist=2.90069e+08
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<100u, (boost::multiprecision::mpfr_allocation_type)1>, (boost::multiprecision::expression_template_option)1>
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u, (boost::multiprecision::mpfr_allocation_type)1>, (boost::multiprecision::expression_template_option)1>
tanh error, args=(-9.75,-6.25) ULP dist=4.31581e+08
tanh error, args=(-9.75,-5.75) ULP dist=3.09252e+08
tanh error, args=(-9.75,4) ULP dist=3.86202e+08
tan error, args=(-6.25,-9.75) ULP dist=4.31581e+08
tan error, args=(-6.25,9.75) ULP dist=4.31581e+08
tan error, args=(-5.75,-9.75) ULP dist=3.09252e+08
tan error, args=(-5.75,9.75) ULP dist=3.09252e+08
tan error, args=(4,-9.75) ULP dist=3.86202e+08
tan error, args=(4,9.75) ULP dist=3.86202e+08
tanh error, args=(9.75,-6.25) ULP dist=4.31581e+08
tanh error, args=(9.75,-5.75) ULP dist=3.09252e+08
tanh error, args=(9.75,4) ULP dist=3.86202e+08
Metadata
Metadata
Assignees
Labels
No labels