-
Notifications
You must be signed in to change notification settings - Fork 7
Description
I did not have a lot of time to investigate, so here is brief recap of what I figured out for now.
template<typename T>
void test_asin()
{
using nl = std::numeric_limits<T>;
std::print("{}\n", boost::typeindex::type_id<T>().pretty_name());
auto tiny0 = nl::epsilon()*999/1000;
auto tiny1 = nl::epsilon();
auto tiny2 = nl::epsilon()*1000/999;
assert(tiny0!=tiny1);
assert(tiny1!=tiny2);
std::println("{:.36e} -> {:.36e}", tiny0, asin(tiny0));
std::println("{:.36e} -> {:.36e}", tiny1, asin(tiny1));
std::println("{:.36e} -> {:.36e}", tiny2, asin(tiny2));
}
prints
float
1.190900817960027779918164014816284180e-07 -> 1.190900817960027779918164014816284180e-07
1.192092895507812500000000000000000000e-07 -> 1.192092895507812500000000000000000000e-07
1.193286180978248012252151966094970703e-07 -> 1.193286180978248012252151966094970703e-07
double
2.218225603201062765794263809792929471e-16 -> 2.218225603201062765794263809792929471e-16
2.220446049250313080847263336181640625e-16 -> 2.220446049250313080847263336181640625e-16
2.222668717968281558635048558466794015e-16 -> 2.222668717968281558635048558466794015e-16
long double
1.083117970313018929550875856533283850e-19 -> 1.083117970313018929550875856533283850e-19
1.084202172485504434007452800869941711e-19 -> 1.084202172485504434007452800869941711e-19
1.085287459945449883881930776840203615e-19 -> 1.085287459945449883881930776840203615e-19
boost::decimal::decimal32_t
9.990000000000000000000000000000000000e-07 -> 9.990000000000000000000000000000000000e-07
1.000000000000000000000000000000000000e-06 -> 1.000000000000000000000000000000000000e-06
1.001001000000000000000000000000000000e-06 -> 1.001075000000000000000000000000000000e-06
boost::decimal::decimal64_t
9.990000000000000000000000000000000000e-16 -> 9.990000000000000000000000000000000000e-16
1.000000000000000000000000000000000000e-15 -> 1.000000000000000000000000000000000000e-15
1.001001001001001000000000000000000000e-15 -> 1.001609728980325000000000000000000000e-15
boost::decimal::decimal128_t
9.990000000000000000000000000000000000e-34 -> 9.990000000000000000000000000000000000e-34
1.000000000000000000000000000000000000e-33 -> 1.000000000000000000000000000000000000e-33
1.001001001001001001001001001001001000e-33 -> 1.109451248382801572892973052948674000e-33
I think that depending on precision you guarantee you could claim all results are fine, but I do not know what you guarantee so I opened an issue.
Issues I can see:
https://www.wolframalpha.com/input?i=asin%281.001001001001001000000000000000000000e-15+%29
https://www.wolframalpha.com/input?i=asin%281.001001001001001001001001001001001000e-33+%29
In other words tiny2 for decimal64 and decimal128 seems to have very large error.
Beside that function does not seem "smooth". What I mean by this is that code jumps from identity(tiny0, tiny1) to values that are quite higher from identity for small increment over epsilon since different code branch is used to compute tiny0, tiny1 versus branch for tiny2.