コンテンツにスキップ

# Kotlin/Complex.kt

Complex.kt
```import kotlin.math.abs
import kotlin.math.atan2
import kotlin.math.hypot

import kotlin.math.sin
import kotlin.math.cos
import kotlin.math.tan
import kotlin.math.sinh
import kotlin.math.cosh
import kotlin.math.tanh

import kotlin.math.PI

class Complex(real_: Double, imag_: Double) : Number() {
private val pair = doubleArrayOf(real_, imag_)
val real get() = pair[0]
val imag  get() = pair[1]
constructor(real_: Number, imag_: Number) : this(real_.toDouble(), imag_.toDouble()) {
// println("(\$real_, \${imag_}.i) => (\${this.real}, \${this.imag}.i)")
}
companion object {
public val i = Complex(0, 1)
public val NaN = Complex(Double.NaN, Double.NaN)
public val INFINITY = Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)
}
fun isNaN() = real.isNaN() or imag.isNaN()
fun isFinite() = real.isFinite() and imag.isFinite()
fun imagAsZero() = abs(imag) < 1e-12
fun check() =
when {
this.isNaN() -> throw Exception("NaN!")
!this.imagAsZero() -> throw Exception("imag(\$imag) != 0")
else -> true
}
override fun toChar()   = toInt().toChar()
override fun toByte()   = toInt().toByte()
override fun toShort()  = toInt().toShort()
override fun toInt()    = if (check()) real.toInt() else 0
override fun toLong()   = if (check()) real.toLong() else 0L
override fun toFloat()  = if (check()) real.toFloat() else 0.0F
override fun toDouble() = if (check()) real else 0.0
override fun toString() = "\${real.toString()}+\${imag.toString()}.i".replace("+-","-")
val abs get() = hypot(real, imag)
val arg get() =
when {
isNaN() -> Double.NaN
!isFinite() -> Double.NaN
real > 0.0 -> atan2(imag, real)
real < 0.0 && imag >= 0.0 -> atan2(imag, real) + PI
real < 0.0 && imag < 0.0 -> atan2(imag, real) - PI
real == 0.0 && imag > 0.0 -> +PI / 2
real == 0.0 && imag < 0.0 -> -PI / 2
else -> 0.0 // indeterminate
}
val angle get() = arg
val phase get() = arg
val conjugate get() = Complex(+real, -imag)
val conj get() = conjugate
operator fun plus(r: Number)  = Complex(real + r.toDouble(), imag)
operator fun plus(r: Complex) = Complex(real + r.real, imag + r.imag)
operator fun minus(r: Number) = Complex(real - r.toDouble(), imag)
operator fun minus(r: Complex) = Complex(real - r.real, imag - r.imag)
operator fun times(r: Number) = Complex(real * r.toDouble(), imag * r.toDouble())
// (a+bi)(c+di) = a c + bi c + a di + bi di = ac - b d + (b c + a d)i
operator fun times(r: Complex) = Complex(real * r.real - imag * r.imag, imag * r.real + real * r.imag)
operator fun div(r: Number) = Complex(real / r.toDouble(), imag / r.toDouble())
// this / r = this * r.conjugate / r * r.conjugate
operator fun div(r: Complex) = this * r.conjugate / (r.real * r.real + r.imag * r.imag)
operator fun unaryMinus() = Complex(-real, -imag)
override fun equals(other: Any?) = when {
this === other -> true
other !is Complex -> false
real != other.real -> false
else ->  imag == other.imag
}
fun sin() : Complex { val c = Complex(-imag, real).sinh(); return Complex(c.imag, -c.real) }
fun sinh()  = sinh(real) * cos(imag) + (cosh(real) * sin(imag)).i
}
operator fun Number.plus(c:Complex)  = Complex(this.toDouble(), 0.0) + c
operator fun Number.minus(c:Complex) = Complex(this.toDouble(), 0.0) - c
operator fun Number.times(c:Complex) = Complex(this.toDouble(), 0.0) * c
operator fun Number.div(c:Complex)   = Complex(this.toDouble(), 0.0) / c
val Number.r get() = Complex(toDouble(), 0.0)
val Number.i get() = Complex(0.0, toDouble())

fun main() {
val a =  2.1 +  3.9.i
val b = -7.8 + 11.11.i
val c =  3 + 4.i
val p = 2.3.r
val q = 1.3.i

try { Complex.NaN.toDouble()                } catch (e: Exception) { println("Complex.NaN.toDouble() raises \$e") }
try { Complex.INFINITY.toDouble()           } catch (e: Exception) { println("Complex.INFINITY.toDouble() raises \$e")}
try { Double.POSITIVE_INFINITY.r.toDouble() } catch (e: Exception) { println("Double.POSITIVE_INFINITY.r.toDouble() raises \$e")}
try { 1.i.toDouble()                        } catch (e: Exception) { println("1.i.toDouble() raises \$e")}

println(
"""
a == a => \${a == a}
a != a => \${a != a}
a == 2.1 + 3.9.i => \${a == 2.1 + 3.9.i}
3.14.i == 3.14.i => \${3.14.i == 3.14.i}
Double.NaN.i == Double.NaN.i => \${Double.NaN.i == Double.NaN.i}
Double.POSITIVE_INFINITY.r == Double.POSITIVE_INFINITY.r + 1 => \${Double.POSITIVE_INFINITY.r == Double.POSITIVE_INFINITY.r + 1}

Complex(0, 1).arg => \${Complex(0.0, 1).arg}
Complex(0, -1).arg => \${Complex(0.0, -1).arg}
Complex(1, 1).arg => \${Complex(1.0, 1).arg}
Complex(1, -1).arg => \${Complex(1.0, -1).arg}
Complex(1, 0.0).arg => \${Complex(1.0, 0.0).arg}
Complex(-1, 0.0).arg => \${Complex(-1.0, 0.0).arg}
Complex(0.0, 0.0).arg => \${Complex(0.0, 0.0).arg}

2.toBigDecimal() = \${2.toBigDecimal()}
2.toBigDecimal().i = \${2.toBigDecimal().i}
a => \$a
b => \$b
c => \$c
p => \$p
q => \$q

Double.NaN.r => \${Double.NaN.r}
Double.NaN.i => \${Double.NaN.i}
Double.POSITIVE_INFINITY.r => \${Double.POSITIVE_INFINITY.r}
Double.POSITIVE_INFINITY.i => \${Double.POSITIVE_INFINITY.i}
-Double.POSITIVE_INFINITY.r => \${-Double.POSITIVE_INFINITY.r}
Double.POSITIVE_INFINITY.i.conj => \${Double.POSITIVE_INFINITY.i.conj}

(1+2.i) / 0 => \${(1+2.i) / 0}
(0+0.i) / 0 => \${(0+0.i) / 0.0}
Double.NaN.i.isNaN() => \${Double.NaN.i.isNaN()}
Double.NaN.i.isFinite() => \${Double.NaN.i.isFinite()}
1.i.isNaN() => \${1.i.isNaN()}
1.i.isFinite() => \${1.i.isFinite()}
Complex.INFINITY.isNaN() => \${Complex.INFINITY.isNaN()}
Complex.INFINITY.isFinite() => \${Complex.INFINITY.isFinite()}

-a => \${-a}
a + 8 => \${a + 8}
8 + a => \${8 + a}
a + b => \${a + b}
a - b => \${a - b}
a * b => \${a * b}
a * Complex(1, 1) => \${a * Complex(1, 1)}
a / 2 => \${a / 2}
a / b => \${a / b}
a / b * b => \${a / b * b}
a * 1.i => \${a * 1.i}
a / 1.i => \${a / 1.i}
1.i => \${1.i}
1.i / 1.i => \${1.i / 1.i}
1.0 + 3.2.i => \${1.0 + 3.2.i}
a + 3.2 => \${a + 3.2}
a.conjugate => \${a.conjugate}
1 + 2.i => \${1 + 2.i}
"""
)
}
```

```Complex.NaN.toDouble() raises java.lang.Exception: NaN!
Complex.INFINITY.toDouble() raises java.lang.Exception: imag(Infinity) != 0
1.i.toDouble() raises java.lang.Exception: imag(1.0) != 0

a == a => true
a != a => false
a == 2.1 + 3.9.i => true
3.14.i == 3.14.i => true
Double.NaN.i == Double.NaN.i => false
Double.POSITIVE_INFINITY.r == Double.POSITIVE_INFINITY.r + 1 => true

Complex(0, 1).arg => 1.5707963267948966
Complex(0, -1).arg => -1.5707963267948966
Complex(1, 1).arg => 0.7853981633974483
Complex(1, -1).arg => -0.7853981633974483
Complex(1, 0.0).arg => 0.0
Complex(-1, 0.0).arg => 6.283185307179586
Complex(0.0, 0.0).arg => 0.0

2.toBigDecimal() = 2
2.toBigDecimal().i = 0.0+2.0.i
a => 2.1+3.9.i
b => -7.8+11.11.i
c => 3.0+4.0.i
p => 2.3+0.0.i
q => 0.0+1.3.i

Double.NaN.r => NaN+0.0.i
Double.NaN.i => 0.0+NaN.i
Double.POSITIVE_INFINITY.r => Infinity+0.0.i
Double.POSITIVE_INFINITY.i => 0.0+Infinity.i
-Double.POSITIVE_INFINITY.r => -Infinity-0.0.i
Double.POSITIVE_INFINITY.i.conj => 0.0-Infinity.i

(1+2.i) / 0 => Infinity+Infinity.i
(0+0.i) / 0 => NaN+NaN.i
Double.NaN.i.isNaN() => true
Double.NaN.i.isFinite() => false
1.i.isNaN() => false
1.i.isFinite() => true
Complex.INFINITY.isNaN() => false
Complex.INFINITY.isFinite() => false

-a => -2.1-3.9.i
a + 8 => 10.1+3.9.i
8 + a => 10.1+3.9.i
a + b => -5.699999999999999+15.01.i
a - b => 9.9-7.209999999999999.i
a * b => -59.70899999999999-7.088999999999999.i
a * Complex(1, 1) => -1.7999999999999998+6.0.i
a / 2 => 1.05+1.95.i
a / b => 0.14624568776282462-0.2916936421737203.i
a / b * b => 2.1000000000000005+3.8999999999999995.i
a * 1.i => -3.9+2.1.i
a / 1.i => 3.9-2.1.i
1.i => 0.0+1.0.i
1.i / 1.i => 1.0+0.0.i
1.0 + 3.2.i => 1.0+3.2.i
a + 3.2 => 5.300000000000001+3.9.i
a.conjugate => 2.1-3.9.i
1 + 2.i => 1.0+2.0.i
```