mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Introduce inverse hyperbolic functions
#KT-4900 Improve accuracy of JS polyfills of hyperbolic functions and expm1/log1p
This commit is contained in:
@@ -62,6 +62,12 @@ public external object Math {
|
||||
internal fun cosh(value: Double): Double
|
||||
@PublishedApi
|
||||
internal fun tanh(value: Double): Double
|
||||
@PublishedApi
|
||||
internal fun asinh(value: Double): Double
|
||||
@PublishedApi
|
||||
internal fun acosh(value: Double): Double
|
||||
@PublishedApi
|
||||
internal fun atanh(value: Double): Double
|
||||
|
||||
@PublishedApi
|
||||
internal fun hypot(x: Double, y: Double): Double
|
||||
|
||||
@@ -152,6 +152,52 @@ public inline fun cosh(a: Double): Double = nativeMath.cosh(a)
|
||||
@InlineOnly
|
||||
public inline fun tanh(a: Double): Double = nativeMath.tanh(a)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun asinh(a: Double): Double = nativeMath.asinh(a)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun acosh(a: Double): Double = nativeMath.acosh(a)
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun atanh(a: Double): Double = nativeMath.atanh(a)
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
@@ -592,6 +638,52 @@ public inline fun cosh(a: Float): Float = nativeMath.cosh(a.toDouble()).toFloat(
|
||||
@InlineOnly
|
||||
public inline fun tanh(a: Float): Float = nativeMath.tanh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun asinh(a: Float): Float = nativeMath.asinh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun acosh(a: Float): Float = nativeMath.acosh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun atanh(a: Float): Float = nativeMath.atanh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
|
||||
@@ -52,24 +52,171 @@ if (typeof Math.trunc === "undefined") {
|
||||
return Math.ceil(x);
|
||||
};
|
||||
}
|
||||
if (typeof Math.sinh === "undefined") {
|
||||
Math.sinh = function(x) {
|
||||
var y = Math.exp(x);
|
||||
return (y - 1 / y) / 2;
|
||||
};
|
||||
}
|
||||
if (typeof Math.cosh === "undefined") {
|
||||
Math.cosh = function(x) {
|
||||
var y = Math.exp(x);
|
||||
return (y + 1 / y) / 2;
|
||||
};
|
||||
}
|
||||
if (typeof Math.tanh === "undefined") {
|
||||
Math.tanh = function(x){
|
||||
var a = Math.exp(+x), b = Math.exp(-x);
|
||||
return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (a + b);
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
var epsilon = 2.220446049250313E-16;
|
||||
var taylor_2_bound = Math.sqrt(epsilon);
|
||||
var taylor_n_bound = Math.sqrt(taylor_2_bound);
|
||||
var upper_taylor_2_bound = 1/taylor_2_bound;
|
||||
var upper_taylor_n_bound = 1/taylor_n_bound;
|
||||
|
||||
if (typeof Math.sinh === "undefined") {
|
||||
Math.sinh = function(x) {
|
||||
if (Math.abs(x) < taylor_n_bound) {
|
||||
var result = x;
|
||||
if (Math.abs(x) > taylor_2_bound) {
|
||||
result += (x * x * x) / 6;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
var y = Math.exp(x);
|
||||
var y1 = 1 / y;
|
||||
if (!isFinite(y)) return Math.exp(x - Math.LN2);
|
||||
if (!isFinite(y1)) return -Math.exp(-x - Math.LN2);
|
||||
return (y - y1) / 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
if (typeof Math.cosh === "undefined") {
|
||||
Math.cosh = function(x) {
|
||||
var y = Math.exp(x);
|
||||
var y1 = 1 / y;
|
||||
if (!isFinite(y) || !isFinite(y1)) return Math.exp(Math.abs(x) - Math.LN2);
|
||||
return (y + y1) / 2;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof Math.tanh === "undefined") {
|
||||
Math.tanh = function(x){
|
||||
if (Math.abs(x) < taylor_n_bound) {
|
||||
var result = x;
|
||||
if (Math.abs(x) > taylor_2_bound) {
|
||||
result -= (x * x * x) / 3;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
var a = Math.exp(+x), b = Math.exp(-x);
|
||||
return a === Infinity ? 1 : b === Infinity ? -1 : (a - b) / (a + b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Inverse hyperbolic function implementations derived from boost special math functions,
|
||||
// Copyright Eric Ford & Hubert Holin 2001.
|
||||
|
||||
if (typeof Math.asinh === "undefined") {
|
||||
var asinh = function(x) {
|
||||
if (x >= +taylor_n_bound)
|
||||
{
|
||||
if (x > upper_taylor_n_bound)
|
||||
{
|
||||
if (x > upper_taylor_2_bound)
|
||||
{
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 0
|
||||
return Math.log(x) + Math.LN2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 1
|
||||
return Math.log(x * 2 + (1 / (x * 2)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.log(x + Math.sqrt(x * x + 1));
|
||||
}
|
||||
}
|
||||
else if (x <= -taylor_n_bound)
|
||||
{
|
||||
return -asinh(-x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
var result = x;
|
||||
if (Math.abs(x) >= taylor_2_bound)
|
||||
{
|
||||
var x3 = x * x * x;
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result -= x3 / 6;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
Math.asinh = asinh;
|
||||
}
|
||||
if (typeof Math.acosh === "undefined") {
|
||||
Math.acosh = function(x) {
|
||||
if (x < 1)
|
||||
{
|
||||
return NaN;
|
||||
}
|
||||
else if (x - 1 >= taylor_n_bound)
|
||||
{
|
||||
if (x > upper_taylor_2_bound)
|
||||
{
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 0
|
||||
return Math.log(x) + Math.LN2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.log(x + Math.sqrt(x * x - 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var y = Math.sqrt(x - 1);
|
||||
// approximation by taylor series in y at 0 up to order 2
|
||||
var result = y;
|
||||
if (y >= taylor_2_bound)
|
||||
{
|
||||
var y3 = y * y * y;
|
||||
// approximation by taylor series in y at 0 up to order 4
|
||||
result -= y3 / 12;
|
||||
}
|
||||
|
||||
return Math.sqrt(2) * result;
|
||||
}
|
||||
};
|
||||
}
|
||||
if (typeof Math.atanh === "undefined") {
|
||||
Math.atanh = function(x) {
|
||||
if (Math.abs(x) < taylor_n_bound) {
|
||||
var result = x;
|
||||
if (Math.abs(x) > taylor_2_bound) {
|
||||
result += (x * x * x) / 3;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return Math.log((1 + x) / (1 - x)) / 2;
|
||||
};
|
||||
}
|
||||
if (typeof Math.log1p === "undefined") {
|
||||
Math.log1p = function(x) {
|
||||
if (Math.abs(x) < taylor_n_bound) {
|
||||
var x2 = x * x;
|
||||
var x3 = x2 * x;
|
||||
var x4 = x3 * x;
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
return (-x4 / 4 + x3 / 3 - x2 / 2 + x);
|
||||
}
|
||||
return Math.log(x + 1);
|
||||
};
|
||||
}
|
||||
if (typeof Math.expm1 === "undefined") {
|
||||
Math.expm1 = function(x) {
|
||||
if (Math.abs(x) < taylor_n_bound) {
|
||||
var x2 = x * x;
|
||||
var x3 = x2 * x;
|
||||
var x4 = x3 * x;
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
return (x4 / 24 + x3 / 6 + x2 / 2 + x);
|
||||
}
|
||||
return Math.exp(x) - 1;
|
||||
};
|
||||
}
|
||||
})();
|
||||
if (typeof Math.hypot === "undefined") {
|
||||
Math.hypot = function() {
|
||||
var y = 0;
|
||||
@@ -94,16 +241,7 @@ if (typeof Math.log2 === "undefined") {
|
||||
return Math.log(x) * Math.LOG2E;
|
||||
};
|
||||
}
|
||||
if (typeof Math.log1p === "undefined") {
|
||||
Math.log1p = function(x) {
|
||||
return Math.log(x + 1);
|
||||
};
|
||||
}
|
||||
if (typeof Math.expm1 === "undefined") {
|
||||
Math.expm1 = function(x) {
|
||||
return Math.exp(x) - 1;
|
||||
};
|
||||
}
|
||||
|
||||
// For HtmlUnit and PhantomJs
|
||||
if (typeof ArrayBuffer.isView === "undefined") {
|
||||
ArrayBuffer.isView = function(a) {
|
||||
|
||||
@@ -140,6 +140,49 @@ public expect fun cosh(a: Double): Double
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun tanh(a: Double): Double
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun asinh(a: Double): Double
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun acosh(a: Double): Double
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun atanh(a: Double): Double
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
@@ -527,6 +570,49 @@ public expect fun cosh(a: Float): Float
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun tanh(a: Float): Float
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun asinh(a: Float): Float
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun acosh(a: Float): Float
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun atanh(a: Float): Float
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
|
||||
@@ -32,6 +32,12 @@ public const val E: Double = nativeMath.E
|
||||
/** Natural logarithm of 2.0, used to compute [log2] function */
|
||||
private val LN2: Double = ln(2.0)
|
||||
|
||||
private val epsilon: Double = nativeMath.ulp(1.0)
|
||||
private val taylor_2_bound = nativeMath.sqrt(epsilon)
|
||||
private val taylor_n_bound = nativeMath.sqrt(taylor_2_bound)
|
||||
private val upper_taylor_2_bound = 1 / taylor_2_bound
|
||||
private val upper_taylor_n_bound = 1 / taylor_n_bound
|
||||
|
||||
// ================ Double Math ========================================
|
||||
|
||||
/** Computes the sine of the angle [a] given in radians.
|
||||
@@ -155,6 +161,109 @@ public inline fun cosh(a: Double): Double = nativeMath.cosh(a)
|
||||
@InlineOnly
|
||||
public inline fun tanh(a: Double): Double = nativeMath.tanh(a)
|
||||
|
||||
|
||||
// Inverse hyperbolic function implementations derived from boost special math functions,
|
||||
// Copyright Eric Ford & Hubert Holin 2001.
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public fun asinh(a: Double): Double =
|
||||
when {
|
||||
a >= +taylor_n_bound ->
|
||||
if (a > upper_taylor_n_bound) {
|
||||
if (a > upper_taylor_2_bound) {
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 0
|
||||
nativeMath.log(a) + LN2
|
||||
} else {
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 1
|
||||
nativeMath.log(a * 2 + (1 / (a * 2)))
|
||||
}
|
||||
} else {
|
||||
nativeMath.log(a + nativeMath.sqrt(a * a + 1))
|
||||
}
|
||||
a <= -taylor_n_bound -> -asinh(-a)
|
||||
else -> {
|
||||
// approximation by taylor series in x at 0 up to order 2
|
||||
var result = a;
|
||||
if (nativeMath.abs(a) >= taylor_2_bound) {
|
||||
// approximation by taylor series in x at 0 up to order 4
|
||||
result -= (a * a * a) / 6
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public fun acosh(a: Double): Double =
|
||||
when {
|
||||
a < 1 -> Double.NaN
|
||||
|
||||
a > upper_taylor_2_bound ->
|
||||
// approximation by laurent series in 1/x at 0+ order from -1 to 0
|
||||
nativeMath.log(a) + LN2
|
||||
|
||||
a - 1 >= taylor_n_bound ->
|
||||
nativeMath.log(a + nativeMath.sqrt(a * a - 1))
|
||||
|
||||
else -> {
|
||||
val y = nativeMath.sqrt(a - 1)
|
||||
// approximation by taylor series in y at 0 up to order 2
|
||||
var result = y
|
||||
if (y >= taylor_2_bound) {
|
||||
// approximation by taylor series in y at 0 up to order 4
|
||||
result -= (y * y * y) / 12
|
||||
}
|
||||
|
||||
nativeMath.sqrt(2.0) * result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
public fun atanh(x: Double): Double {
|
||||
if (nativeMath.abs(x) < taylor_n_bound) {
|
||||
var result = x
|
||||
if (nativeMath.abs(x) > taylor_2_bound) {
|
||||
result += (x * x * x) / 3
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nativeMath.log((1 + x) / (1 - x)) / 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
@@ -640,6 +749,52 @@ public inline fun cosh(a: Float): Float = nativeMath.cosh(a.toDouble()).toFloat(
|
||||
@InlineOnly
|
||||
public inline fun tanh(a: Float): Float = nativeMath.tanh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic sine of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `sinh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `asinh(NaN)` is `NaN`
|
||||
* - `asinh(+Inf)` is `+Inf`
|
||||
* - `asinh(-Inf)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun asinh(a: Float): Float = asinh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic cosine of the value [a].
|
||||
*
|
||||
* The returned value is positive `x` such that `cosh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `acosh(NaN)` is `NaN`
|
||||
* - `acosh(x)` is `NaN` when `x < 1`
|
||||
* - `acosh(+Inf)` is `+Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun acosh(a: Float): Float = acosh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes the inverse hyperbolic tangent of the value [a].
|
||||
*
|
||||
* The returned value is `x` such that `tanh(x) == a`.
|
||||
*
|
||||
* Special cases:
|
||||
*
|
||||
* - `tanh(NaN)` is `NaN`
|
||||
* - `tanh(x)` is `NaN` when `x > 1` or `x < -1`
|
||||
* - `tanh(1.0)` is `+Inf`
|
||||
* - `tanh(-1.0)` is `-Inf`
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@InlineOnly
|
||||
public inline fun atanh(a: Float): Float = atanh(a.toDouble()).toFloat()
|
||||
|
||||
/**
|
||||
* Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow.
|
||||
*
|
||||
|
||||
@@ -79,17 +79,60 @@ class DoubleMathTest {
|
||||
@Test fun hyperbolic() {
|
||||
assertEquals(Double.POSITIVE_INFINITY, sinh(Double.POSITIVE_INFINITY))
|
||||
assertEquals(Double.NEGATIVE_INFINITY, sinh(Double.NEGATIVE_INFINITY))
|
||||
assertTrue(sinh(Double.MIN_VALUE) != 0.0)
|
||||
assertTrue(sinh(710.0).isFinite())
|
||||
assertTrue(sinh(-710.0).isFinite())
|
||||
assertTrue(sinh(Double.NaN).isNaN())
|
||||
|
||||
assertEquals(Double.POSITIVE_INFINITY, cosh(Double.POSITIVE_INFINITY))
|
||||
assertEquals(Double.POSITIVE_INFINITY, cosh(Double.NEGATIVE_INFINITY))
|
||||
assertTrue(cosh(710.0).isFinite())
|
||||
assertTrue(cosh(-710.0).isFinite())
|
||||
assertTrue(cosh(Double.NaN).isNaN())
|
||||
|
||||
assertAlmostEquals(1.0, tanh(Double.POSITIVE_INFINITY))
|
||||
assertAlmostEquals(-1.0, tanh(Double.NEGATIVE_INFINITY))
|
||||
assertTrue(tanh(Double.MIN_VALUE) != 0.0)
|
||||
assertTrue(tanh(Double.NaN).isNaN())
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicSin() {
|
||||
for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0, Double.MIN_VALUE, -Double.MIN_VALUE, 0.00001)) {
|
||||
assertEquals(exact, asinh(sinh(exact)))
|
||||
}
|
||||
for (approx in listOf(Double.MIN_VALUE, 0.1, 1.0, 100.0, 710.0)) {
|
||||
assertAlmostEquals(approx, asinh(sinh(approx)))
|
||||
assertAlmostEquals(-approx, asinh(sinh(-approx)))
|
||||
}
|
||||
assertTrue(asinh(Double.NaN).isNaN())
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicCos() {
|
||||
for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0)) {
|
||||
assertEquals(abs(exact), acosh(cosh(exact)))
|
||||
}
|
||||
for (approx in listOf(Double.MIN_VALUE, 0.00001, 1.0, 100.0, 710.0)) {
|
||||
assertAlmostEquals(approx, acosh(cosh(approx)))
|
||||
assertAlmostEquals(approx, acosh(cosh(-approx)))
|
||||
}
|
||||
for (invalid in listOf(-1.0, 0.0, 0.99999, Double.NaN)) {
|
||||
assertTrue(acosh(invalid).isNaN())
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicTan() {
|
||||
for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0, Double.MIN_VALUE, -Double.MIN_VALUE)) {
|
||||
assertEquals(exact, atanh(tanh(exact)))
|
||||
}
|
||||
for (approx in listOf(0.00001)) {
|
||||
assertAlmostEquals(approx, atanh(tanh(approx)))
|
||||
}
|
||||
|
||||
for (invalid in listOf(-1.00001, 1.00001, Double.NaN, Double.MAX_VALUE, -Double.MAX_VALUE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)) {
|
||||
assertTrue(atanh(invalid).isNaN())
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun powers() {
|
||||
assertEquals(5.0, hypot(3.0, 4.0))
|
||||
assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, Double.NaN))
|
||||
@@ -117,6 +160,8 @@ class DoubleMathTest {
|
||||
assertEquals(Double.POSITIVE_INFINITY, exp(Double.POSITIVE_INFINITY))
|
||||
|
||||
assertEquals(0.0, expm1(0.0))
|
||||
assertEquals(Double.MIN_VALUE, expm1(Double.MIN_VALUE))
|
||||
assertEquals(0.00010000500016667084, expm1(1e-4))
|
||||
assertEquals(-1.0, expm1(Double.NEGATIVE_INFINITY))
|
||||
assertEquals(Double.POSITIVE_INFINITY, expm1(Double.POSITIVE_INFINITY))
|
||||
}
|
||||
@@ -151,6 +196,8 @@ class DoubleMathTest {
|
||||
assertTrue(ln1p(Double.NaN).isNaN())
|
||||
assertTrue(ln1p(-1.1).isNaN())
|
||||
assertEquals(0.0, ln1p(0.0))
|
||||
assertEquals(9.999995000003334e-7, ln1p(1e-6))
|
||||
assertEquals(Double.MIN_VALUE, ln1p(Double.MIN_VALUE))
|
||||
assertEquals(Double.NEGATIVE_INFINITY, ln1p(-1.0))
|
||||
}
|
||||
|
||||
@@ -323,17 +370,61 @@ class FloatMathTest {
|
||||
@Test fun hyperbolic() {
|
||||
assertEquals(Float.POSITIVE_INFINITY, sinh(Float.POSITIVE_INFINITY))
|
||||
assertEquals(Float.NEGATIVE_INFINITY, sinh(Float.NEGATIVE_INFINITY))
|
||||
assertTrue(sinh(Float.MIN_VALUE) != 0.0F)
|
||||
assertTrue(sinh(89.0F).isFinite())
|
||||
assertTrue(sinh(-89.0F).isFinite())
|
||||
assertTrue(sinh(Float.NaN).isNaN())
|
||||
|
||||
assertEquals(Float.POSITIVE_INFINITY, cosh(Float.POSITIVE_INFINITY))
|
||||
assertEquals(Float.POSITIVE_INFINITY, cosh(Float.NEGATIVE_INFINITY))
|
||||
assertTrue(cosh(89.0F).isFinite())
|
||||
assertTrue(cosh(-89.0F).isFinite())
|
||||
assertTrue(cosh(Float.NaN).isNaN())
|
||||
|
||||
assertAlmostEquals(1.0F, tanh(Float.POSITIVE_INFINITY))
|
||||
assertAlmostEquals(-1.0F, tanh(Float.NEGATIVE_INFINITY))
|
||||
assertTrue(tanh(Float.MIN_VALUE) != 0.0F)
|
||||
assertTrue(tanh(Float.NaN).isNaN())
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicSin() {
|
||||
for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F, Float.MIN_VALUE, -Float.MIN_VALUE, 0.00001F)) {
|
||||
assertEquals(exact, asinh(sinh(exact)))
|
||||
}
|
||||
for (approx in listOf(Float.MIN_VALUE, 0.1F, 1.0F, 89.0F)) {
|
||||
assertAlmostEquals(approx, asinh(sinh(approx)))
|
||||
assertAlmostEquals(-approx, asinh(sinh(-approx)))
|
||||
}
|
||||
assertTrue(asinh(Float.NaN).isNaN())
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicCos() {
|
||||
for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F)) {
|
||||
assertEquals(abs(exact), acosh(cosh(exact)))
|
||||
}
|
||||
for (approx in listOf(Float.MIN_VALUE, 0.1F, 1.0F, 89.0F)) {
|
||||
assertAlmostEquals(approx, acosh(cosh(approx)))
|
||||
assertAlmostEquals(approx, acosh(cosh(-approx)))
|
||||
}
|
||||
for (invalid in listOf(-1.0F, 0.0F, 0.99999F, Float.NaN)) {
|
||||
assertTrue(acosh(invalid).isNaN())
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun inverseHyperbolicTan() {
|
||||
for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F, Float.MIN_VALUE, -Float.MIN_VALUE)) {
|
||||
assertEquals(exact, atanh(tanh(exact)))
|
||||
}
|
||||
|
||||
for (approx in listOf(0.00001F)) {
|
||||
assertAlmostEquals(approx, atanh(tanh(approx)))
|
||||
}
|
||||
|
||||
for (invalid in listOf(-1.00001F, 1.00001F, Float.NaN, Float.MAX_VALUE, -Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)) {
|
||||
assertTrue(atanh(invalid).isNaN())
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun powers() {
|
||||
assertEquals(5.0F, hypot(3.0F, 4.0F))
|
||||
assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NEGATIVE_INFINITY, Float.NaN))
|
||||
|
||||
@@ -3016,6 +3016,9 @@ public abstract interface class kotlin/jvm/internal/markers/KMutableSet : kotlin
|
||||
public final class kotlin/math/MathKt {
|
||||
public static final field E D
|
||||
public static final field PI D
|
||||
public static final fun acosh (D)D
|
||||
public static final fun asinh (D)D
|
||||
public static final fun atanh (D)D
|
||||
public static final fun getSign (I)I
|
||||
public static final fun getSign (J)I
|
||||
public static final fun log (DD)D
|
||||
|
||||
@@ -2024,6 +2024,9 @@ public final class kotlin/io/TextStreamsKt {
|
||||
public final class kotlin/math/MathKt {
|
||||
public static final field E D
|
||||
public static final field PI D
|
||||
public static final fun acosh (D)D
|
||||
public static final fun asinh (D)D
|
||||
public static final fun atanh (D)D
|
||||
public static final fun getSign (I)I
|
||||
public static final fun getSign (J)I
|
||||
public static final fun log (DD)D
|
||||
|
||||
@@ -34,6 +34,10 @@ the Kotlin IntelliJ IDEA plugin:
|
||||
- Path: js/js.libraries/src/js/long.js
|
||||
- License: Apache 2 (license/third_party/closure-compiler_LICENSE.txt)
|
||||
- Origin: Google Closure Library, Copyright 2009 The Closure Library Authors
|
||||
|
||||
- Path: js/js.libraries/src/js/polyfills.js
|
||||
- License: Boost Software License 1.0 (license/third_party/boost_LICENSE.txt)
|
||||
- Origin: Derived from boost special math functions, Copyright Eric Ford & Hubert Holin 2001.
|
||||
|
||||
- Path: js/js.parser/src/com/google
|
||||
- License: Netscape Public License 1.1 (license/third_party/rhino_LICENSE.txt)
|
||||
@@ -48,7 +52,11 @@ the Kotlin IntelliJ IDEA plugin:
|
||||
- Path: libraries/stdlib/src/kotlin/collections
|
||||
- License: Apache 2 (license/third_party/gwt_license.txt)
|
||||
- Origin: Derived from GWT, (C) 2007-08 Google Inc.
|
||||
|
||||
|
||||
- Path: libraries/stdlib/src/kotlin/util/MathJVM.kt
|
||||
- License: Boost Software License 1.0 (license/third_party/boost_LICENSE.txt)
|
||||
- Origin: Derived from boost special math functions, Copyright Eric Ford & Hubert Holin 2001.
|
||||
|
||||
- Path: plugins/lint/android-annotations
|
||||
- License: Apache 2 (license/third_party/aosp_license.txt)
|
||||
- Origin: Copyright (C) 2011-15 The Android Open Source Project
|
||||
|
||||
23
license/third_party/boost_LICENSE.txt
vendored
Normal file
23
license/third_party/boost_LICENSE.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
Reference in New Issue
Block a user