blob: 036b416ad49ba373e50414c3a33b1728a54194cf [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include "packetmath_test_shared.h"
void check_trig_reduction() {
// MPFR 4.2.1, 256-bit precision, rounded to binary64. Include both sides of the medium/large reduction cutoffs.
const double cases[][4] = {
{1.5707963267948963, 1, 2.8327694488239898e-16, 3530114321217157.5},
{1.5707963267948966, 1, 6.123233995736766e-17, 16331239353195370},
{1.5707963267948968, 1, -1.6081226496766366e-16, -6218431163823738},
{3.1415926535897927, 5.6655388976479796e-16, -1, -5.6655388976479796e-16},
{3.1415926535897931, 1.2246467991473532e-16, -1, -1.2246467991473532e-16},
{3.1415926535897936, -3.2162452993532732e-16, -1, 3.2162452993532732e-16},
{14.137166941154067, 1, 2.3274478990165594e-15, 429655160239049.94},
{14.137166941154069, 1, 5.5109105961630896e-16, 1814582150355041},
{14.137166941154071, 1, -1.2252657797839415e-15, -816149456305174.88},
{0.29999999999999999, 0.29552020666133955, 0.95533648912560598, 0.30933624960962325},
{4.7123889803846897, -1, -1.8369701987210297e-16, 5443746451065123},
{14.999999999999998, 0.65028784015711827, -0.75968791285882009, -0.85599340090852183},
{15, 0.65028784015711683, -0.75968791285882131, -0.85599340090851872},
{15.000000000000002, 0.65028784015711549, -0.75968791285882242, -0.85599340090851572},
{20, 0.91294525072762767, 0.40808206181339196, 2.2371609442247422},
{100, -0.50636564110975879, 0.86231887228768389, -0.58721391515692911},
{123.456, -0.80393736857282394, -0.5947139710921574, 1.3518050821917635},
{1000, 0.82687954053200252, 0.56237907629070294, 1.4703241557027185},
{12345.678900000001, -0.70344192126325633, 0.71075274421521484, -0.98971397154430851},
{123456.789, -0.99866408234322457, 0.051672532718701383, -19.326787943215852},
{1000000, -0.34999350217129294, 0.93675212753314474, -0.37362445398759903},
{10000000, 0.4205477931907825, -0.90727038618173961, -0.46353082785018906},
{100000000, 0.93163902710972601, -0.36338508935569053, -2.5637789067283774},
{1000000000, 0.54584344944869956, 0.83788718136390239, 0.65145220214514132},
{10000000000, -0.48750602508751067, 0.87311962267685606, -0.55834963781124181},
{100000000000, 0.92869366049659197, 0.37084779216471114, 2.5042448144982212},
{1000000000000, -0.61123870237688949, 0.79144630185289022, -0.77230596813187613},
{6907362400000, 0.5754525274479354, 0.81783518428457402, 0.70362896889955862},
{10000000000000, -0.28888529481752512, 0.95736371690083999, -0.30175082856983471},
{99999999999999.984, -0.19410480015836853, -0.9809807982603328, 0.1978680933435121},
{100000000000000, -0.20940830749645231, -0.97782828796853249, 0.21415652428250395},
{100000000000000.02, -0.22466069079959752, -0.97443705492425092, 0.23055433869667633},
{1000000000000000, 0.85827279317023586, -0.51319373778697031, -1.672414782127583},
// Medium-path inputs within 6e-19 to 9e-7 of k*pi/2, for k from 29 to 6e13.
{45.553093477052002, 1, -6.1898063658835771e-19, -1.6155594228467482e+18},
{364.42474781641602, 4.9518450927068616e-18, 1, 4.9518450927068616e-18},
{857879.41830474522, -1, -1.2354480663331819e-14, 80942293508783.953},
{956274858.90980339, -1, 2.2360885370100136e-11, -44720948363.571968},
{93293944418765.062, 9.1063643066365511e-07, 0.99999999999958533, 9.1063643066403267e-07},
};
const Index count = sizeof(cases) / sizeof(cases[0]);
ArrayXd x(2 * count), sin_ref(2 * count), cos_ref(2 * count), tan_ref(2 * count);
for (Index i = 0; i < count; ++i) {
x[2 * i] = cases[i][0];
x[2 * i + 1] = -cases[i][0];
sin_ref[2 * i] = cases[i][1];
sin_ref[2 * i + 1] = -cases[i][1];
cos_ref[2 * i] = cos_ref[2 * i + 1] = cases[i][2];
tan_ref[2 * i] = cases[i][3];
tan_ref[2 * i + 1] = -cases[i][3];
}
for (Index offset = 0; offset < 2; ++offset) {
for (Index size = 1; size <= x.size() - offset; ++size) {
const ArrayXd sine = x.segment(offset, size).sin();
const ArrayXd cosine = x.segment(offset, size).cos();
const ArrayXd tangent = x.segment(offset, size).tan();
VERIFY(test::areWithinUlps(sin_ref.data() + offset, sine.data(), static_cast<int>(size), 4));
VERIFY(test::areWithinUlps(cos_ref.data() + offset, cosine.data(), static_cast<int>(size), 4));
VERIFY(test::areWithinUlps(tan_ref.data() + offset, tangent.data(), static_cast<int>(size), 4));
}
}
}
template <typename Packet>
void check_error_free_transformations() {
const double low = std::ldexp(1.0, -54);
Packet hi, lo;
internal::twosum(internal::pset1<Packet>(low), internal::pset1<Packet>(1.0), hi, lo);
VERIFY_IS_EQUAL(internal::pfirst(hi), 1.0);
VERIFY_IS_EQUAL(internal::pfirst(lo), low);
const Packet x = internal::pset1<Packet>(1.0 + std::ldexp(1.0, -30));
internal::twoprod<Packet, true>(x, x, hi, lo);
VERIFY_IS_EQUAL(internal::pfirst(hi), 1.0 + std::ldexp(1.0, -29));
VERIFY_IS_EQUAL(internal::pfirst(lo), std::ldexp(1.0, -60));
}
EIGEN_DECLARE_TEST(trig_reduction_fastmath) {
CALL_SUBTEST(check_trig_reduction());
CALL_SUBTEST(check_error_free_transformations<double>());
CALL_SUBTEST(check_error_free_transformations<internal::packet_traits<double>::type>());
}