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);