Add field test, minor refactor

This commit is contained in:
Iaroslav Postovalov 2020-10-27 20:31:28 +07:00
parent 828e40c452
commit 202ea3582c
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
4 changed files with 89 additions and 40 deletions

View File

@ -59,7 +59,7 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
public override fun divide(a: Complex, b: Complex): Complex = when {
b.re.isNaN() || b.im.isNaN() -> Complex(Double.NaN, Double.NaN)
(if (b.im < 0) -b.im else +b.im) < (if (b.re < 0) -b.re else +b.re) -> {
abs(b.im) < abs(b.re) -> {
val wr = b.im / b.re
val wd = b.re + wr * b.im
@ -91,8 +91,8 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
return i * (e1 - e2) / (e1 + e2)
}
public override fun asin(arg: Complex): Complex = -i * ln(sqrt(1 - (arg * arg)) + i * arg)
public override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(1 - (arg * arg)) + i * arg)
public override fun asin(arg: Complex): Complex = -i * ln(sqrt(one - (arg * arg)) + i * arg)
public override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(one - (arg * arg)) + i * arg)
public override fun atan(arg: Complex): Complex {
val iArg = i * arg
@ -125,6 +125,7 @@ public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
public data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Complex, ComplexField>,
Comparable<Complex> {
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
public constructor(re: Number) : this(re.toDouble(), 0.0)
public override val context: ComplexField
get() = ComplexField
@ -155,7 +156,7 @@ public data class Complex(val re: Double, val im: Double) : FieldElement<Complex
* @receiver the real part.
* @return the new complex number.
*/
public fun Number.toComplex(): Complex = Complex(this, 0)
public fun Number.toComplex(): Complex = Complex(this)
/**
* Creates a new buffer of complex numbers with the specified [size], where each element is calculated by calling the

View File

@ -85,20 +85,23 @@ public object QuaternionField : Field<Quaternion>, Norm<Quaternion, Quaternion>,
return exp(pow * ln(arg))
}
private fun pwr(x: Quaternion, a: Int): Quaternion {
if (a < 0) return -(pwr(x, -a))
if (a == 0) return one
if (a == 1) return x
if (a == 2) return pwr2(x)
if (a == 3) return pwr3(x)
if (a == 4) return pwr4(x)
private fun pwr(x: Quaternion, a: Int): Quaternion = when {
a < 0 -> -(pwr(x, -a))
a == 0 -> one
a == 1 -> x
a == 2 -> pwr2(x)
a == 3 -> pwr3(x)
a == 4 -> pwr4(x)
else -> {
val x4 = pwr4(x)
var y = x4
repeat((1 until a / 4).count()) { y *= x4 }
if (a % 4 == 3) y *= pwr3(x)
if (a % 4 == 2) y *= pwr2(x)
if (a % 4 == 1) y *= x
return y
y
}
}
private inline fun pwr2(x: Quaternion): Quaternion {
@ -204,7 +207,11 @@ public data class Quaternion(val w: Double, val x: Double, val y: Double, val z:
z.toDouble()
)
public constructor(w: Number, x: Number, y: Number) : this(w.toDouble(), x.toDouble(), y.toDouble(), 0.0)
public constructor(w: Number, x: Number) : this(w.toDouble(), x.toDouble(), 0.0, 0.0)
public constructor(w: Number) : this(w.toDouble(), 0.0, 0.0, 0.0)
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 override val context: QuaternionField
get() = QuaternionField
@ -241,7 +248,7 @@ public data class Quaternion(val w: Double, val x: Double, val y: Double, val z:
* @receiver the real part.
* @return a new quaternion.
*/
public fun Number.toQuaternion(): Quaternion = Quaternion(this, 0, 0, 0)
public fun Number.toQuaternion(): Quaternion = Quaternion(this)
/**
* Creates a quaternion with `w`-component equal to `re`-component of given complex and `x`-component equal to
@ -250,7 +257,7 @@ public fun Number.toQuaternion(): Quaternion = Quaternion(this, 0, 0, 0)
* @receiver the complex number.
* @return a new quaternion.
*/
public fun Complex.toQuaternion(): Quaternion = Quaternion(re, im, 0, 0)
public fun Complex.toQuaternion(): Quaternion = Quaternion(this)
/**
* Creates a new buffer of quaternions with the specified [size], where each element is calculated by calling the

View File

@ -1,39 +1,30 @@
package kscience.kmath.operations
import kotlin.math.sqrt
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
internal class ComplexTest {
@Test
fun conjugate() {
assertEquals(
Complex(0, -42), (ComplexField.i * 42).conjugate
)
}
fun conjugate() = assertEquals(Complex(0, -42), (ComplexField.i * 42).conjugate)
@Test
fun reciprocal() {
assertTrue { (Complex(0.5, -0.0) - 2.toComplex().reciprocal).r < 1e-10}
}
fun reciprocal() = assertTrue((Complex(0.5, -0.0) - 2.toComplex().reciprocal).r < 1e-10)
@Test
fun r() {
assertEquals(kotlin.math.sqrt(2.0), (ComplexField.i + 1.0.toComplex()).r)
}
fun r() = assertEquals(sqrt(2.0), (ComplexField.i + 1.0.toComplex()).r)
@Test
fun theta() {
assertEquals(0.0, 1.toComplex().theta)
}
fun theta() = assertEquals(0.0, 1.toComplex().theta)
@Test
fun toComplex() {
assertEquals(Complex(42, 0), 42.toComplex())
assertEquals(Complex(42.0, 0), 42.0.toComplex())
assertEquals(Complex(42f, 0), 42f.toComplex())
assertEquals(Complex(42.0, 0), 42.0.toComplex())
assertEquals(Complex(42.toByte(), 0), 42.toByte().toComplex())
assertEquals(Complex(42.toShort(), 0), 42.toShort().toComplex())
assertEquals(Complex(42), 42.toComplex())
assertEquals(Complex(42.0), 42.0.toComplex())
assertEquals(Complex(42f), 42f.toComplex())
assertEquals(Complex(42.0), 42.0.toComplex())
assertEquals(Complex(42.toByte()), 42.toByte().toComplex())
assertEquals(Complex(42.toShort()), 42.toShort().toComplex())
}
}

View File

@ -0,0 +1,50 @@
package kscience.kmath.operations
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
internal class QuaternionFieldTest {
@Test
fun testAddition() {
assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(16, 16) + Quaternion(26, 26) })
assertEquals(Quaternion(42, 16), QuaternionField { Quaternion(16, 16) + 26 })
assertEquals(Quaternion(42, 16), QuaternionField { 26 + Quaternion(16, 16) })
}
@Test
fun testSubtraction() {
assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(86, 55) - Quaternion(44, 13) })
assertEquals(Quaternion(42, 56), QuaternionField { Quaternion(86, 56) - 44 })
assertTrue(Quaternion(42, 56) - QuaternionField { 86 - Quaternion(44, -56) } < 1e-10.toQuaternion())
}
@Test
fun testMultiplication() {
assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(4.2, 0) * Quaternion(10, 10) })
assertEquals(Quaternion(42, 21), QuaternionField { Quaternion(4.2, 2.1) * 10 })
assertEquals(Quaternion(42, 21), QuaternionField { 10 * Quaternion(4.2, 2.1) })
}
@Test
fun testDivision() {
assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(0, 168) / Quaternion(2, 2) })
assertEquals(Quaternion(42, 56), QuaternionField { Quaternion(86, 56) - 44 })
assertTrue(Quaternion(42, 56) - QuaternionField { 86 - Quaternion(44, -56) } < 1e-10.toQuaternion())
}
@Test
fun testPower() {
assertEquals(QuaternionField.zero, QuaternionField { zero pow 2 })
assertEquals(QuaternionField.zero, QuaternionField { zero pow 2 })
assertEquals(
QuaternionField { i * 8 }.let { it.x.toInt() to it.w.toInt() },
QuaternionField { Quaternion(2, 2) pow 2 }.let { it.x.toInt() to it.w.toInt() })
}
@Test
fun testNorm() {
assertEquals(2.toQuaternion(), QuaternionField { norm(2 * i) })
}
}