diff --git a/src/Numerics/Trigonometry.cs b/src/Numerics/Trigonometry.cs index fc75847d..73c6c5c6 100644 --- a/src/Numerics/Trigonometry.cs +++ b/src/Numerics/Trigonometry.cs @@ -713,7 +713,13 @@ namespace MathNet.Numerics /// The hyperbolic angle, i.e. the area of its hyperbolic sector. public static double Asinh(double value) { - return Math.Log(value + Math.Sqrt((value * value) + 1), Math.E); + // asinh(x) = Sign(x) * ln(|x| + sqrt(x*x + 1)) + // if |x| > huge, asinh(x) ~= Sign(x) * ln(2|x|) + + if (Math.Abs(value) >= 268435456.0) // 2^28, taken from freeBSD + return Math.Sign(value) * (Math.Log(Math.Abs(value)) + Math.Log(2.0)); + + return Math.Sign(value) * Math.Log(Math.Abs(value) + Math.Sqrt((value * value) + 1)); } /// @@ -733,6 +739,12 @@ namespace MathNet.Numerics /// The hyperbolic angle, i.e. the area of its hyperbolic sector. public static double Acosh(double value) { + // acosh(x) = ln(x + sqrt(x*x - 1)) + // if |x| >= 2^28, acosh(x) ~ ln(x) + ln(2) + + if (Math.Abs(value) >= 268435456.0) // 2^28, taken from freeBSD + return Math.Log(value) + Math.Log(2.0); + return Math.Log(value + (Math.Sqrt(value - 1) * Math.Sqrt(value + 1)), Math.E); } diff --git a/src/UnitTests/TrigonometryTest.cs b/src/UnitTests/TrigonometryTest.cs index c55e0d27..f853d401 100644 --- a/src/UnitTests/TrigonometryTest.cs +++ b/src/UnitTests/TrigonometryTest.cs @@ -338,6 +338,7 @@ namespace MathNet.Numerics.UnitTests /// Expected value. [TestCase(1.0, 0.0)] [TestCase(8388608, 16.635532333438682)] + [TestCase(1.7976931348623157E+308, 710.47586007394394203711)] public void CanComputeInverseHyperbolicCosine(double value, double expected) { var actual = Trig.Acosh(value); @@ -383,6 +384,8 @@ namespace MathNet.Numerics.UnitTests [TestCase(-8388608, -16.63553233343869)] [TestCase(1.19209289550780998537e-7, 1.1920928955078072e-7)] [TestCase(-1.19209289550780998537e-7, -1.1920928955078072e-7)] + [TestCase(1.7976931348623157E+308, 710.47586007394394203711)] + [TestCase(-1.7976931348623157E+308, -710.47586007394394203711)] public void CanComputeInverseHyperbolicSine(double value, double expected) { var actual = Trig.Asinh(value);