Kotlin/Complex.kt
表示
< Kotlin
- 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