Make complex and quaternion NaN-hostile
This commit is contained in:
parent
b1ccca1019
commit
1539113e72
@ -57,26 +57,24 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
|
|||||||
Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
|
Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
|
||||||
|
|
||||||
public override fun divide(a: Complex, b: Complex): Complex = when {
|
public override fun divide(a: Complex, b: Complex): Complex = when {
|
||||||
b.re.isNaN() || b.im.isNaN() -> Complex(Double.NaN, Double.NaN)
|
|
||||||
|
|
||||||
abs(b.im) < abs(b.re) -> {
|
abs(b.im) < abs(b.re) -> {
|
||||||
val wr = b.im / b.re
|
val wr = b.im / b.re
|
||||||
val wd = b.re + wr * b.im
|
val wd = b.re + wr * b.im
|
||||||
|
|
||||||
if (wd.isNaN() || wd == 0.0)
|
if (wd.isNaN() || wd == 0.0)
|
||||||
Complex(Double.NaN, Double.NaN)
|
throw ArithmeticException("Division by zero or infinity")
|
||||||
else
|
else
|
||||||
Complex((a.re + a.im * wr) / wd, (a.im - a.re * wr) / wd)
|
Complex((a.re + a.im * wr) / wd, (a.im - a.re * wr) / wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.im == 0.0 -> Complex(Double.NaN, Double.NaN)
|
b.im == 0.0 -> throw ArithmeticException("Division by zero")
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val wr = b.re / b.im
|
val wr = b.re / b.im
|
||||||
val wd = b.im + wr * b.re
|
val wd = b.im + wr * b.re
|
||||||
|
|
||||||
if (wd.isNaN() || wd == 0.0)
|
if (wd.isNaN() || wd == 0.0)
|
||||||
Complex(Double.NaN, Double.NaN)
|
throw ArithmeticException("Division by zero or infinity")
|
||||||
else
|
else
|
||||||
Complex((a.re * wr + a.im) / wd, (a.im * wr - a.re) / wd)
|
Complex((a.re * wr + a.im) / wd, (a.im * wr - a.re) / wd)
|
||||||
}
|
}
|
||||||
@ -130,6 +128,11 @@ public data class Complex(val re: Double, val im: Double) : FieldElement<Complex
|
|||||||
public override val context: ComplexField
|
public override val context: ComplexField
|
||||||
get() = ComplexField
|
get() = ComplexField
|
||||||
|
|
||||||
|
init {
|
||||||
|
require(!re.isNaN()) { "Real component of complex is not-a-number" }
|
||||||
|
require(!im.isNaN()) { "Imaginary component of complex is not-a-number" }
|
||||||
|
}
|
||||||
|
|
||||||
public override fun unwrap(): Complex = this
|
public override fun unwrap(): Complex = this
|
||||||
public override fun Complex.wrap(): Complex = this
|
public override fun Complex.wrap(): Complex = this
|
||||||
public override fun compareTo(other: Complex): Int = r.compareTo(other.r)
|
public override fun compareTo(other: Complex): Int = r.compareTo(other.r)
|
||||||
|
@ -41,12 +41,12 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
|||||||
/**
|
/**
|
||||||
* The `i` quaternion unit.
|
* The `i` quaternion unit.
|
||||||
*/
|
*/
|
||||||
public val i: Quaternion by lazy { Quaternion(0, 1, 0, 0) }
|
public val i: Quaternion by lazy { Quaternion(0, 1) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `j` quaternion unit.
|
* The `j` quaternion unit.
|
||||||
*/
|
*/
|
||||||
public val j: Quaternion by lazy { Quaternion(0, 0, 1, 0) }
|
public val j: Quaternion by lazy { Quaternion(0, 0, 1) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `k` quaternion unit.
|
* The `k` quaternion unit.
|
||||||
@ -104,41 +104,23 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun pwr2(x: Quaternion): Quaternion {
|
private fun pwr2(x: Quaternion): Quaternion {
|
||||||
val aa = 2 * x.w
|
val aa = 2 * x.w
|
||||||
|
return Quaternion(x.w * x.w - (x.x * x.x + x.y * x.y + x.z * x.z), aa * x.x, aa * x.y, aa * x.z)
|
||||||
return Quaternion(
|
|
||||||
x.w * x.w - (x.x * x.x + x.y * x.y + x.z * x.z),
|
|
||||||
aa * x.x,
|
|
||||||
aa * x.y,
|
|
||||||
aa * x.z
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun pwr3(x: Quaternion): Quaternion {
|
private fun pwr3(x: Quaternion): Quaternion {
|
||||||
val a2 = x.w * x.w
|
val a2 = x.w * x.w
|
||||||
val n1 = x.x * x.x + x.y * x.y + x.z * x.z
|
val n1 = x.x * x.x + x.y * x.y + x.z * x.z
|
||||||
val n2 = 3.0 * a2 - n1
|
val n2 = 3.0 * a2 - n1
|
||||||
|
return Quaternion(x.w * (a2 - 3 * n1), x.x * n2, x.y * n2, x.z * n2)
|
||||||
return Quaternion(
|
|
||||||
x.w * (a2 - 3 * n1),
|
|
||||||
x.x * n2,
|
|
||||||
x.y * n2,
|
|
||||||
x.z * n2
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun pwr4(x: Quaternion): Quaternion {
|
private fun pwr4(x: Quaternion): Quaternion {
|
||||||
val a2 = x.w * x.w
|
val a2 = x.w * x.w
|
||||||
val n1 = x.x * x.x + x.y * x.y + x.z * x.z
|
val n1 = x.x * x.x + x.y * x.y + x.z * x.z
|
||||||
val n2 = 4 * x.w * (a2 - n1)
|
val n2 = 4 * x.w * (a2 - n1)
|
||||||
|
return Quaternion(a2 * a2 - 6 * a2 * n1 + n1 * n1, x.x * n2, x.y * n2, x.z * n2)
|
||||||
return Quaternion(
|
|
||||||
a2 * a2 - 6 * a2 * n1 + n1 * n1,
|
|
||||||
x.x * n2,
|
|
||||||
x.y * n2,
|
|
||||||
x.z * n2
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun exp(arg: Quaternion): Quaternion {
|
public override fun exp(arg: Quaternion): Quaternion {
|
||||||
@ -213,6 +195,13 @@ public data class Quaternion(val w: Double, val x: Double, val y: Double, val z:
|
|||||||
public constructor(wx: Complex, yz: Complex) : this(wx.re, wx.im, yz.re, yz.im)
|
public constructor(wx: Complex, yz: Complex) : this(wx.re, wx.im, yz.re, yz.im)
|
||||||
public constructor(wx: Complex) : this(wx.re, wx.im, 0, 0)
|
public constructor(wx: Complex) : this(wx.re, wx.im, 0, 0)
|
||||||
|
|
||||||
|
init {
|
||||||
|
require(!w.isNaN()) { "w-component of quaternion is not-a-number" }
|
||||||
|
require(!x.isNaN()) { "x-component of quaternion is not-a-number" }
|
||||||
|
require(!y.isNaN()) { "x-component of quaternion is not-a-number" }
|
||||||
|
require(!z.isNaN()) { "x-component of quaternion is not-a-number" }
|
||||||
|
}
|
||||||
|
|
||||||
public override val context: QuaternionField
|
public override val context: QuaternionField
|
||||||
get() = QuaternionField
|
get() = QuaternionField
|
||||||
|
|
||||||
|
@ -3,6 +3,13 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
|
all {
|
||||||
|
languageSettings.apply {
|
||||||
|
useExperimentalAnnotation("kotlinx.coroutines.FlowPreview")
|
||||||
|
useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":kmath-coroutines"))
|
api(project(":kmath-coroutines"))
|
||||||
|
Loading…
Reference in New Issue
Block a user