mtommila / apfloat

Apfloat is a high performance arbitrary precision arithmetic library.
MIT License
54 stars 11 forks source link

`UnderflowException` should be thrown instead of an OverflowException? #38

Open axkr opened 5 months ago

axkr commented 5 months ago

An UnderflowException should be thrown instead of a OverflowException?

Example:

N(Erfc(100000000000000000000000000000000035/2*1/Sqrt(2)),30)
mtommila commented 5 months ago

There's no UnderflowException class, usually underflow just results in zero (i.e. when the exponent is too small to be represented as a long), such as in exp(-10e20).

Please note that all of the special functions like erfc are calculated using more or less complicated algorithms, and with extreme input values, an overflow may happen at any intermediate step, and does not necessarily mean that the value of the function is "infinite" but simply that it couldn't be computed with the existing algorithm.

This case with erf or erfc with extremely large input values is a bit more complicated though. For large input values they use the incomplete gamma function, which does have severe shortcomings with very large input values (shortcomings that Mathematica does not have but then again Mathematica easily produces wildly incorrect values for the incomplete gamma functions whereas I aimed for producing correct results even if it means sacrificing execution time). However for extreme cases where either |z| ≫ |a| or |a| ≫ |z| there exist asymptotic formulas, which are currently not used, but could be used.

mtommila commented 5 months ago

I committed a fix so that the above at least doesn't throw OverflowException. However there's still no UnderflowException, so it now underflows and returns zero. Or at least this line of code in particular does:

new FixedPrecisionApcomplexHelper(30).erfc(new Apcomplex("3.53553390593273762200422181052e34"))

Also not all possible similar use cases are fixed. It's probably easy to get a LossOfPrecisionException, for example with ApcomplexMath.erfc(new Apcomplex("3.53553390593273762200422181052e34")).

mtommila commented 5 months ago

Committed another change that returns an underflow (i.e. zero) from exp() before checking for complete loss of precision. With that, also e.g. ApcomplexMath.erfc(new Apcomplex("3.53553390593273762200422181052e34")) just returns zero (because of the underflow).