KT-48232: Implement kotlin.math.cbrt() (cubic roots)
cbrt() is the standard cubic root function that provides several advantages over pow(x, 1.0/3.0): - Better precision - Faster - Behaves better with negative values
This commit is contained in:
@@ -153,6 +153,8 @@ KDouble Kotlin_math_round(KDouble x) { return rint(x); }
|
|||||||
|
|
||||||
KDouble Kotlin_math_abs(KDouble x) { return fabs(x); }
|
KDouble Kotlin_math_abs(KDouble x) { return fabs(x); }
|
||||||
|
|
||||||
|
KDouble Kotlin_math_cbrt(KDouble x) { return cbrt(x); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) {
|
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) {
|
||||||
@@ -228,6 +230,8 @@ KFloat Kotlin_math_roundf(KFloat x) { return rintf(x); }
|
|||||||
|
|
||||||
KFloat Kotlin_math_absf(KFloat x) { return fabsf(x); }
|
KFloat Kotlin_math_absf(KFloat x) { return fabsf(x); }
|
||||||
|
|
||||||
|
KFloat Kotlin_math_cbrtf(KFloat x) { return cbrtf(x); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) {
|
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) {
|
||||||
@@ -311,6 +315,8 @@ KDouble Kotlin_math_abs(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_abs,
|
|||||||
KDouble Kotlin_math_atan2(KDouble y, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_atan2, y, x); }
|
KDouble Kotlin_math_atan2(KDouble y, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_atan2, y, x); }
|
||||||
KDouble Kotlin_math_hypot(KDouble x, KDouble y) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_hypot, x, y); }
|
KDouble Kotlin_math_hypot(KDouble x, KDouble y) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_hypot, x, y); }
|
||||||
|
|
||||||
|
KDouble Kotlin_math_cbrt(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_cbrt, x); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_pow, thiz, x); }
|
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_pow, thiz, x); }
|
||||||
@@ -406,6 +412,8 @@ KFloat Kotlin_math_absf(KFloat x) { return (KFloat)Kotlin_math_abs (x); }
|
|||||||
KFloat Kotlin_math_atan2f(KFloat y, KFloat x) { return (KFloat)Kotlin_math_atan2(y, x); }
|
KFloat Kotlin_math_atan2f(KFloat y, KFloat x) { return (KFloat)Kotlin_math_atan2(y, x); }
|
||||||
KFloat Kotlin_math_hypotf(KFloat x, KFloat y) { return (KFloat)Kotlin_math_hypot(x, y); }
|
KFloat Kotlin_math_hypotf(KFloat x, KFloat y) { return (KFloat)Kotlin_math_hypot(x, y); }
|
||||||
|
|
||||||
|
KDouble Kotlin_math_cbrtf(KFloat x) { return (KFloat)Kotlin_math_cbrt(x); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { return (KFloat)Kotlin_math_Double_pow(thiz, x); }
|
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { return (KFloat)Kotlin_math_Double_pow(thiz, x); }
|
||||||
@@ -504,6 +512,8 @@ KDouble Kotlin_math_round(KDouble x) { NotImplemented(); }
|
|||||||
|
|
||||||
KDouble Kotlin_math_abs(KDouble x) { NotImplemented(); }
|
KDouble Kotlin_math_abs(KDouble x) { NotImplemented(); }
|
||||||
|
|
||||||
|
KDouble Kotlin_math_cbrt(KDouble x) { NotImplemented(); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { NotImplemented(); }
|
KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { NotImplemented(); }
|
||||||
@@ -551,6 +561,8 @@ KFloat Kotlin_math_roundf(KFloat x) { NotImplemented(); }
|
|||||||
|
|
||||||
KFloat Kotlin_math_absf(KFloat x) { NotImplemented(); }
|
KFloat Kotlin_math_absf(KFloat x) { NotImplemented(); }
|
||||||
|
|
||||||
|
KFloat Kotlin_math_cbrtf(KFloat x) { NotImplemented(); }
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { NotImplemented(); }
|
KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { NotImplemented(); }
|
||||||
|
|||||||
@@ -384,6 +384,23 @@ public actual fun max(a: Double, b: Double): Double = when {
|
|||||||
else -> if (a > b) a else b
|
else -> if (a > b) a else b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@GCUnsafeCall("Kotlin_math_cbrt")
|
||||||
|
public external actual fun cbrt(x: Double): Double
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -934,6 +951,23 @@ public actual fun max(a: Float, b: Float): Float = when {
|
|||||||
else -> if (a > b) a else b
|
else -> if (a > b) a else b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@GCUnsafeCall("Kotlin_math_cbrtf")
|
||||||
|
public external actual fun cbrt(x: Float): Float
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -107,6 +107,16 @@ public inline fun atanh(x: kotlin.Double): kotlin.Double
|
|||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun atanh(x: kotlin.Float): kotlin.Float
|
public inline fun atanh(x: kotlin.Float): kotlin.Float
|
||||||
|
|
||||||
|
@kotlin.SinceKotlin(version = "1.7")
|
||||||
|
@kotlin.ExperimentalStdlibApi
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun cbrt(x: kotlin.Double): kotlin.Double
|
||||||
|
|
||||||
|
@kotlin.SinceKotlin(version = "1.7")
|
||||||
|
@kotlin.ExperimentalStdlibApi
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun cbrt(x: kotlin.Float): kotlin.Float
|
||||||
|
|
||||||
@kotlin.SinceKotlin(version = "1.2")
|
@kotlin.SinceKotlin(version = "1.2")
|
||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun ceil(x: kotlin.Double): kotlin.Double
|
public inline fun ceil(x: kotlin.Double): kotlin.Double
|
||||||
|
|||||||
@@ -107,6 +107,16 @@ public inline fun atanh(x: kotlin.Double): kotlin.Double
|
|||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun atanh(x: kotlin.Float): kotlin.Float
|
public inline fun atanh(x: kotlin.Float): kotlin.Float
|
||||||
|
|
||||||
|
@kotlin.SinceKotlin(version = "1.7")
|
||||||
|
@kotlin.ExperimentalStdlibApi
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun cbrt(x: kotlin.Double): kotlin.Double
|
||||||
|
|
||||||
|
@kotlin.SinceKotlin(version = "1.7")
|
||||||
|
@kotlin.ExperimentalStdlibApi
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public inline fun cbrt(x: kotlin.Float): kotlin.Float
|
||||||
|
|
||||||
@kotlin.SinceKotlin(version = "1.2")
|
@kotlin.SinceKotlin(version = "1.2")
|
||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun ceil(x: kotlin.Double): kotlin.Double
|
public inline fun ceil(x: kotlin.Double): kotlin.Double
|
||||||
|
|||||||
@@ -354,6 +354,22 @@ public expect fun min(a: Double, b: Double): Double
|
|||||||
@SinceKotlin("1.2")
|
@SinceKotlin("1.2")
|
||||||
public expect fun max(a: Double, b: Double): Double
|
public expect fun max(a: Double, b: Double): Double
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
public expect fun cbrt(x: Double): Double
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -817,6 +833,22 @@ public expect fun min(a: Float, b: Float): Float
|
|||||||
@SinceKotlin("1.2")
|
@SinceKotlin("1.2")
|
||||||
public expect fun max(a: Float, b: Float): Float
|
public expect fun max(a: Float, b: Float): Float
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
public expect fun cbrt(x: Float): Float
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ internal external object JsMath {
|
|||||||
fun sqrt(value: Double): Double
|
fun sqrt(value: Double): Double
|
||||||
fun tan(value: Double): Double
|
fun tan(value: Double): Double
|
||||||
fun log(value: Double): Double
|
fun log(value: Double): Double
|
||||||
|
fun cbrt(value: Double): Double
|
||||||
fun pow(base: Double, exp: Double): Double
|
fun pow(base: Double, exp: Double): Double
|
||||||
fun round(value: Number): Double
|
fun round(value: Number): Double
|
||||||
fun floor(value: Number): Double
|
fun floor(value: Number): Double
|
||||||
|
|||||||
@@ -380,6 +380,23 @@ public actual inline fun min(a: Double, b: Double): Double = nativeMath.min(a, b
|
|||||||
@InlineOnly
|
@InlineOnly
|
||||||
public actual inline fun max(a: Double, b: Double): Double = nativeMath.max(a, b)
|
public actual inline fun max(a: Double, b: Double): Double = nativeMath.max(a, b)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@InlineOnly
|
||||||
|
public actual inline fun cbrt(x: Double): Double = nativeMath.cbrt(x)
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -900,6 +917,23 @@ public actual inline fun min(a: Float, b: Float): Float = nativeMath.min(a, b)
|
|||||||
@InlineOnly
|
@InlineOnly
|
||||||
public actual inline fun max(a: Float, b: Float): Float = nativeMath.max(a, b)
|
public actual inline fun max(a: Float, b: Float): Float = nativeMath.max(a, b)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@InlineOnly
|
||||||
|
public actual inline fun cbrt(x: Float): Float = nativeMath.cbrt(x.toDouble()).toFloat()
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -463,6 +463,23 @@ public actual inline fun min(a: Double, b: Double): Double = nativeMath.min(a, b
|
|||||||
@InlineOnly
|
@InlineOnly
|
||||||
public actual inline fun max(a: Double, b: Double): Double = nativeMath.max(a, b)
|
public actual inline fun max(a: Double, b: Double): Double = nativeMath.max(a, b)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@InlineOnly
|
||||||
|
public actual inline fun cbrt(x: Double): Double = nativeMath.cbrt(x)
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
|
|
||||||
@@ -993,8 +1010,24 @@ public actual inline fun min(a: Float, b: Float): Float = nativeMath.min(a, b)
|
|||||||
@InlineOnly
|
@InlineOnly
|
||||||
public actual inline fun max(a: Float, b: Float): Float = nativeMath.max(a, b)
|
public actual inline fun max(a: Float, b: Float): Float = nativeMath.max(a, b)
|
||||||
|
|
||||||
// extensions
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
@InlineOnly
|
||||||
|
public actual inline fun cbrt(x: Float): Float = nativeMath.cbrt(x.toDouble()).toFloat()
|
||||||
|
|
||||||
|
|
||||||
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raises this value to the power [x].
|
* Raises this value to the power [x].
|
||||||
|
|||||||
@@ -22,6 +22,20 @@ fun assertAlmostEquals(expected: Float, actual: Float, tolerance: Double? = null
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For Kotlin JS tests
|
||||||
|
private val Float.ulpCommon: Float
|
||||||
|
get() = when {
|
||||||
|
isNaN() -> Float.NaN
|
||||||
|
isInfinite() -> Float.POSITIVE_INFINITY
|
||||||
|
this == Float.MAX_VALUE || this == -Float.MAX_VALUE -> 2.0f.pow(104)
|
||||||
|
else -> {
|
||||||
|
val d = absoluteValue
|
||||||
|
// Ensure we never have -0.0f
|
||||||
|
val valueOrPositiveZero = (this + 0.0f).toBits();
|
||||||
|
Float.fromBits(valueOrPositiveZero + (if (valueOrPositiveZero >= 0) 1 else -1)) - d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class DoubleMathTest {
|
class DoubleMathTest {
|
||||||
|
|
||||||
@Test fun trigonometric() {
|
@Test fun trigonometric() {
|
||||||
@@ -121,6 +135,30 @@ class DoubleMathTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun cubeRoots() {
|
||||||
|
val testingPairs = mapOf(
|
||||||
|
Double.NaN to Double.NaN,
|
||||||
|
Double.POSITIVE_INFINITY to Double.POSITIVE_INFINITY,
|
||||||
|
Double.NEGATIVE_INFINITY to Double.NEGATIVE_INFINITY,
|
||||||
|
Double.fromBits(0x0010000000000000) to 2.812644285236262E-103, // smallest normal value
|
||||||
|
Double.fromBits(0x1L) to 1.7031839360032603E-108, // smallest value (denormal)
|
||||||
|
Double.MAX_VALUE to 5.643803094122362E102,
|
||||||
|
0.0 to 0.0,
|
||||||
|
0.9 to 0.9654893846056297,
|
||||||
|
9.9 to 2.1472291690189413,
|
||||||
|
27.0 to 3.0,
|
||||||
|
399.1289 to 7.362710510208026,
|
||||||
|
8123.452 to 20.102351976782558,
|
||||||
|
21717.639 to 27.9,
|
||||||
|
392890.22 to 73.24147345684439
|
||||||
|
)
|
||||||
|
|
||||||
|
for ((x, result) in testingPairs) {
|
||||||
|
assertEquals(result, cbrt(x), if (result.isFinite()) 2.0 * result.ulp else 0.0)
|
||||||
|
assertEquals(cbrt(-x), -cbrt(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun powers() {
|
@Test fun powers() {
|
||||||
assertEquals(5.0, hypot(3.0, 4.0))
|
assertEquals(5.0, hypot(3.0, 4.0))
|
||||||
assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, Double.NaN))
|
assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, Double.NaN))
|
||||||
@@ -468,6 +506,30 @@ class FloatMathTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun cubeRoots() {
|
||||||
|
val testingPairs = mapOf(
|
||||||
|
Float.NaN to Float.NaN,
|
||||||
|
Float.POSITIVE_INFINITY to Float.POSITIVE_INFINITY,
|
||||||
|
Float.NEGATIVE_INFINITY to Float.NEGATIVE_INFINITY,
|
||||||
|
Float.fromBits(0x00800000) to 2.2737368E-13f, // smallest normal value
|
||||||
|
Float.fromBits(0x1) to 1.1190347E-15f, // smallest value (denormal)
|
||||||
|
Float.MAX_VALUE to 6.9814636E12f,
|
||||||
|
0.0f to 0.0f,
|
||||||
|
0.9f to 0.9654894f,
|
||||||
|
9.9f to 2.1472292f,
|
||||||
|
27.0f to 3.0f,
|
||||||
|
399.1289f to 7.3627105f,
|
||||||
|
8123.452f to 20.102352f,
|
||||||
|
21717.639f to 27.9f,
|
||||||
|
392890.22f to 73.24147f
|
||||||
|
)
|
||||||
|
|
||||||
|
for ((x, result) in testingPairs) {
|
||||||
|
assertEquals(result, cbrt(x), if (result.isFinite()) 2.0f * result.ulpCommon else 0.0f)
|
||||||
|
assertEquals(cbrt(-x), -cbrt(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun powers() {
|
@Test fun powers() {
|
||||||
assertEquals(5.0F, hypot(3.0F, 4.0F))
|
assertEquals(5.0F, hypot(3.0F, 4.0F))
|
||||||
assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NEGATIVE_INFINITY, Float.NaN))
|
assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NEGATIVE_INFINITY, Float.NaN))
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/* @(#)s_cbrt.c 1.3 95/01/18 */
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Developed at SunSoft, a Sun Microsystems, Inc. business.
|
||||||
|
* Permission to use, copy, modify, and distribute this
|
||||||
|
* software is freely granted, provided that this notice
|
||||||
|
* is preserved.
|
||||||
|
* ====================================================
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ieee_cbrt(x)
|
||||||
|
* Return cube root of x
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.math.fdlibm
|
||||||
|
|
||||||
|
private const val B1 = 715094163 /* B1 = (682-0.03306235651)*2**20 */
|
||||||
|
private const val B2 = 696219795 /* B2 = (664-0.03306235651)*2**20 */
|
||||||
|
private const val C = 5.42857142857142815906e-01 /* 19/35 = 0x3FE15F15, 0xF15F15F1 */
|
||||||
|
private const val D = -7.05306122448979611050e-01 /* -864/1225 = 0xBFE691DE, 0x2532C834 */
|
||||||
|
private const val E = 1.41428571428571436819e+00 /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */
|
||||||
|
private const val F = 1.60714285714285720630e+00 /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */
|
||||||
|
private const val G = 3.57142857142857150787e-01 /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */
|
||||||
|
|
||||||
|
internal fun __ieee754_cbrt(v: Double): Double {
|
||||||
|
var hx: Int = 0
|
||||||
|
var r: Double = 0.0
|
||||||
|
var s: Double = 0.0
|
||||||
|
var t: Double = 0.0
|
||||||
|
var w: Double = 0.0
|
||||||
|
var sign: Int = 0
|
||||||
|
|
||||||
|
var x = v
|
||||||
|
|
||||||
|
hx = __HI(x) /* high word of x */
|
||||||
|
sign = hx and 0x80000000.toInt() /* sign= sign(x) */
|
||||||
|
hx = hx xor sign
|
||||||
|
if (hx >= 0x7ff00000) { /* ieee_cbrt(NaN,INF) is itself */
|
||||||
|
return (x + x)
|
||||||
|
}
|
||||||
|
if ((hx or __LO(x)) == 0) {
|
||||||
|
return (x) /* ieee_cbrt(0) is itself */
|
||||||
|
}
|
||||||
|
|
||||||
|
x = doubleSetWord(d = x, hi = hx) /* x <- |x| */
|
||||||
|
/* rough cbrt to 5 bits */
|
||||||
|
if (hx < 0x00100000) { /* subnormal number */
|
||||||
|
t = doubleSetWord(d = t, hi = 0x43500000) /* set t= 2**54 */
|
||||||
|
t *= x
|
||||||
|
t = doubleSetWord(d = t, hi = __HI(t) / 3 + B2)
|
||||||
|
} else {
|
||||||
|
t = doubleSetWord(d = t, hi = hx / 3 + B1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* new cbrt to 23 bits, may be implemented in single precision */
|
||||||
|
r = t * t / x
|
||||||
|
s = C + r * t
|
||||||
|
t *= G + F / (s + E + D / s)
|
||||||
|
|
||||||
|
/* chopped to 20 bits and make it larger than ieee_cbrt(x) */
|
||||||
|
t = doubleSetWord(d = t, hi = __HI(t) + 0x00000001, lo = 0)
|
||||||
|
|
||||||
|
/* one step newton iteration to 53 bits with error less than 0.667 ulps */
|
||||||
|
s = t * t /* t*t is exact */
|
||||||
|
r = x / s
|
||||||
|
w = t + t
|
||||||
|
r = (r - t) / (w + r) /* r-s is exact */
|
||||||
|
t = t + t * r
|
||||||
|
|
||||||
|
/* retore the sign bit */
|
||||||
|
t = doubleSetWord(d = t, hi = __HI(t) or sign)
|
||||||
|
return (t)
|
||||||
|
}
|
||||||
@@ -349,6 +349,21 @@ public actual fun min(a: Double, b: Double): Double = kotlin.wasm.internal.wasm_
|
|||||||
@SinceKotlin("1.2")
|
@SinceKotlin("1.2")
|
||||||
public actual fun max(a: Double, b: Double): Double = kotlin.wasm.internal.wasm_f64_max(a, b)
|
public actual fun max(a: Double, b: Double): Double = kotlin.wasm.internal.wasm_f64_max(a, b)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
public actual fun cbrt(x: Double): Double = kotlin.math.fdlibm.__ieee754_cbrt(x)
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -841,6 +856,22 @@ public actual fun min(a: Float, b: Float): Float = kotlin.wasm.internal.wasm_f32
|
|||||||
@SinceKotlin("1.2")
|
@SinceKotlin("1.2")
|
||||||
public actual fun max(a: Float, b: Float): Float = kotlin.wasm.internal.wasm_f32_max(a ,b)
|
public actual fun max(a: Float, b: Float): Float = kotlin.wasm.internal.wasm_f32_max(a ,b)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cube root of [x]. For any `x`, `cbrt(-x) == -cbrt(x)`;
|
||||||
|
* that is, the cube root of a negative value is the negative of the cube root
|
||||||
|
* of that value's magnitude. Special cases:
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
* - If the argument is `NaN`, then the result is `NaN`.
|
||||||
|
* - If the argument is infinite, then the result is an infinity with the same sign as the argument.
|
||||||
|
* - If the argument is zero, then the result is a zero with the same sign as the argument.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.7")
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
public actual fun cbrt(x: Float): Float = kotlin.math.fdlibm.__ieee754_cbrt(x.toDouble()).toFloat()
|
||||||
|
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user