0.1.4 #137
@ -9,11 +9,20 @@ import scientifik.memory.MemoryWriter
|
|||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A complex conjugate.
|
* This complex's conjugate.
|
||||||
*/
|
*/
|
||||||
val Complex.conjugate: Complex
|
val Complex.conjugate: Complex
|
||||||
get() = Complex(re, -im)
|
get() = Complex(re, -im)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This complex's reciprocal.
|
||||||
|
*/
|
||||||
|
val Complex.reciprocal: Complex
|
||||||
|
get() {
|
||||||
|
val scale = re * re + im * im
|
||||||
|
return Complex(re / scale, -im / scale)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Absolute value of complex number.
|
* Absolute value of complex number.
|
||||||
*/
|
*/
|
||||||
@ -46,16 +55,48 @@ object ComplexField : ExtendedField<Complex> {
|
|||||||
override fun multiply(a: Complex, b: Complex): Complex =
|
override fun multiply(a: Complex, b: 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)
|
||||||
|
|
||||||
override fun divide(a: Complex, b: Complex): Complex {
|
override fun divide(a: Complex, b: Complex): Complex = when {
|
||||||
val scale = b.re * b.re + b.im * b.im
|
b.re.isNaN() || b.im.isNaN() -> Complex(Double.NaN, Double.NaN)
|
||||||
return a * Complex(b.re / scale, -b.im / scale)
|
|
||||||
|
(if (b.im < 0) -b.im else +b.im) < (if (b.re < 0) -b.re else +b.re) -> {
|
||||||
|
val wr = b.im / b.re
|
||||||
|
val wd = b.re + wr * b.im
|
||||||
|
|
||||||
|
if (wd.isNaN() || wd == 0.0)
|
||||||
|
Complex(Double.NaN, Double.NaN)
|
||||||
|
else
|
||||||
|
Complex((a.re + a.im * wr) / wd, (a.im - a.re * wr) / wd)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.im == 0.0 -> Complex(Double.NaN, Double.NaN)
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val wr = b.re / b.im
|
||||||
|
val wd = b.im + wr * b.re
|
||||||
|
|
||||||
|
if (wd.isNaN() || wd == 0.0)
|
||||||
|
Complex(Double.NaN, Double.NaN)
|
||||||
|
else
|
||||||
|
Complex((a.re * wr + a.im) / wd, (a.im * wr - a.re) / wd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2
|
override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2
|
||||||
override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2
|
override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2
|
||||||
|
|
||||||
|
override fun tan(arg: Complex): Complex {
|
||||||
|
val e1 = exp(-i * arg)
|
||||||
|
val e2 = exp(i * arg)
|
||||||
|
return i * (e1 - e2) / (e1 + e2)
|
||||||
|
}
|
||||||
|
|
||||||
override fun asin(arg: Complex): Complex = -i * ln(sqrt(one - arg pow 2) + i * arg)
|
override fun asin(arg: Complex): Complex = -i * ln(sqrt(one - arg pow 2) + i * arg)
|
||||||
override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(one - arg pow 2) + i * arg)
|
override fun acos(arg: Complex): Complex = PI_DIV_2 + i * ln(sqrt(one - arg pow 2) + i * arg)
|
||||||
override fun atan(arg: Complex): Complex = i * (ln(one - i * arg) - ln(one + i * arg)) / 2
|
|
||||||
|
override fun atan(arg: Complex): Complex {
|
||||||
|
val iArg = i * arg
|
||||||
|
return i * (ln(one - iArg) - ln(one + iArg)) / 2
|
||||||
|
}
|
||||||
|
|
||||||
override fun sinh(arg: Complex): Complex = (exp(arg) - exp(-arg)) / 2
|
override fun sinh(arg: Complex): Complex = (exp(arg) - exp(-arg)) / 2
|
||||||
override fun cosh(arg: Complex): Complex = (exp(arg) + exp(-arg)) / 2
|
override fun cosh(arg: Complex): Complex = (exp(arg) + exp(-arg)) / 2
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package scientifik.kmath.operations
|
||||||
|
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
internal class ComplexFieldTest {
|
||||||
|
@Test
|
||||||
|
fun testAddition() {
|
||||||
|
assertEquals(Complex(42, 42), ComplexField { Complex(16, 16) + Complex(26, 26) })
|
||||||
|
assertEquals(Complex(42, 16), ComplexField { Complex(16, 16) + 26 })
|
||||||
|
assertEquals(Complex(42, 16), ComplexField { 26 + Complex(16, 16) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSubtraction() {
|
||||||
|
assertEquals(Complex(42, 42), ComplexField { Complex(86, 55) - Complex(44, 13) })
|
||||||
|
assertEquals(Complex(42, 56), ComplexField { Complex(86, 56) - 44 })
|
||||||
|
assertEquals(Complex(42, 56), ComplexField { 86 - Complex(44, -56) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMultiplication() {
|
||||||
|
assertEquals(Complex(42, 42), ComplexField { Complex(4.2, 0) * Complex(10, 10) })
|
||||||
|
assertEquals(Complex(42, 21), ComplexField { Complex(4.2, 2.1) * 10 })
|
||||||
|
assertEquals(Complex(42, 21), ComplexField { 10 * Complex(4.2, 2.1) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDivision() {
|
||||||
|
assertEquals(Complex(42, 42), ComplexField { Complex(0, 168) / Complex(2, 2) })
|
||||||
|
assertEquals(Complex(42, 56), ComplexField { Complex(86, 56) - 44 })
|
||||||
|
assertEquals(Complex(42, 56), ComplexField { 86 - Complex(44, -56) })
|
||||||
|
assertEquals(Complex(Double.NaN, Double.NaN), ComplexField { Complex(1, 1) / Complex(Double.NaN, Double.NaN) })
|
||||||
|
assertEquals(Complex(Double.NaN, Double.NaN), ComplexField { Complex(1, 1) / Complex(0, 0) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSine() {
|
||||||
|
assertEquals(Complex(1.2246467991473532E-16, 0), ComplexField { sin(PI.toComplex()) })
|
||||||
|
assertEquals(Complex(0, 11.548739357257748), ComplexField { sin(i * PI.toComplex()) })
|
||||||
|
assertEquals(Complex(0, 1.1752011936438014), ComplexField { sin(i) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testArcsine() {
|
||||||
|
assertEquals(Complex(0, -0.0), ComplexField { asin(zero) })
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user