From 8a754ace199d84959978b78fb1b175595a1d7af3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 7 Feb 2024 21:18:47 +0300 Subject: [PATCH] Fixed GitHub #524 (Complex power of real-valued number --- CHANGELOG.md | 1 + .../space/kscience/kmath/complex/Complex.kt | 15 +++++++++++- .../kmath/complex/ComplexFieldTest.kt | 23 ++++++++++--------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6523a0d..0bc556671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Fixed - Median statistics +- Complex power of negative real numbers ### Security diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index b5f1aabe7..08c44e036 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -129,13 +129,25 @@ public object ComplexField : } override fun power(arg: Complex, pow: Number): Complex = if (arg.im == 0.0) { - arg.re.pow(pow.toDouble()).toComplex() + val powDouble = pow.toDouble() + when { + arg.re > 0 -> arg.re.pow(powDouble).toComplex() + arg.re < 0 -> i * (-arg.re).pow(powDouble) + else -> if (powDouble == 0.0) { + one + } else { + zero + } + } + } else { exp(pow * ln(arg)) } public fun power(arg: Complex, pow: Complex): Complex = exp(pow * ln(arg)) + public fun Complex.pow(power: Complex): Complex = power(this, power) + override fun exp(arg: Complex): Complex = exp(arg.re) * (cos(arg.im) + i * sin(arg.im)) @@ -189,6 +201,7 @@ public object ComplexField : override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg) } + /** * Represents `double`-based complex number. * diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt index e11f1c1ea..a545a0792 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt @@ -58,24 +58,25 @@ internal class ComplexFieldTest { } @Test - fun testInverseHyperbolicSine() { - assertEquals( - ComplexField { i * PI.toComplex() / 2 }, - ComplexField { asinh(i) }) + fun testInverseHyperbolicSine() = ComplexField { + assertEquals(i * PI.toComplex() / 2, asinh(i)) } @Test - fun testPower() { - assertEquals(ComplexField.zero, ComplexField { zero pow 2 }) - assertEquals(ComplexField.zero, ComplexField { zero pow 2 }) + fun testPower() = ComplexField { + assertEquals(zero, zero pow 2) + assertEquals(zero, zero pow 2) assertEquals( - ComplexField { i * 8 }.let { it.im.toInt() to it.re.toInt() }, - ComplexField { Complex(2, 2) pow 2 }.let { it.im.toInt() to it.re.toInt() }) + (i * 8).let { it.im.toInt() to it.re.toInt() }, + (Complex(2, 2) pow 2).let { it.im.toInt() to it.re.toInt() }) + + assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5 + 0 * i).im, 0.01) + assertEquals(2.0, power(Complex(-4.0, 0.0), 0.5).im, 0.01) } @Test - fun testNorm() { - assertEquals(2.toComplex(), ComplexField { norm(2 * i) }) + fun testNorm() = ComplexField { + assertEquals(2.toComplex(), norm(2 * i)) } }