All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlinx.multik.ndarray.complex.Complex.kt Maven / Gradle / Ivy

/*
 * Copyright 2020-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package org.jetbrains.kotlinx.multik.ndarray.complex

import kotlin.math.abs
import kotlin.math.atan2
import kotlin.math.sqrt

public interface Complex {
    public companion object {

        public fun r(re: Float): ComplexFloat = ComplexFloat(re, 0f)

        public fun r(re: Double): ComplexDouble = ComplexDouble(re, 0.0)

        public fun i(im: Float): ComplexFloat = ComplexFloat(0f, im)

        public fun i(im: Double): ComplexDouble = ComplexDouble(0.0, im)
    }
}

public class ComplexFloat(public val re: Float, public val im: Float) : Complex {

    public constructor(re: Number, im: Number): this(re.toFloat(), im.toFloat())

    public constructor(re: Number): this(re.toFloat(), 0f)

    public companion object {
        public val one: ComplexFloat
            get() = ComplexFloat(1f, 0f)

        public val zero: ComplexFloat
            get() = ComplexFloat(0f, 0f)

        public val NaN: ComplexFloat
            get() = ComplexFloat(Float.NaN, Float.NaN)
    }

    /** Returns complex conjugate value. */
    public fun conjugate(): ComplexFloat = ComplexFloat(re, -im)

    /** Returns absolute value of complex number. */
    public fun abs(): Float = sqrt(re * re + im * im)

    /** Returns angle of complex number. */
    public fun angle(): Float = atan2(im, re)

    /** Adds the other value to this value. */
    public operator fun plus(other: Byte): ComplexFloat = ComplexFloat(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Short): ComplexFloat = ComplexFloat(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Int): ComplexFloat = ComplexFloat(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Long): ComplexFloat = ComplexFloat(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Float): ComplexFloat = ComplexFloat(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Double): ComplexDouble = ComplexDouble(re + other, im.toDouble())

    /** Adds the other value to this value. */
    public operator fun plus(other: ComplexFloat): ComplexFloat = ComplexFloat(re + other.re, im + other.im)

    /** Adds the other value to this value. */
    public operator fun plus(other: ComplexDouble): ComplexDouble = ComplexDouble(re + other.re, im + other.im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Byte): ComplexFloat = ComplexFloat(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Short): ComplexFloat = ComplexFloat(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Int): ComplexFloat = ComplexFloat(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Long): ComplexFloat = ComplexFloat(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Float): ComplexFloat = ComplexFloat(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Double): ComplexDouble = ComplexDouble(re - other, im.toDouble())

    /** Subtracts the other value from this value. */
    public operator fun minus(other: ComplexFloat): ComplexFloat = ComplexFloat(re - other.re, im - other.im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: ComplexDouble): ComplexDouble = ComplexDouble(re - other.re, im - other.im)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Byte): ComplexFloat = ComplexFloat(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Short): ComplexFloat = ComplexFloat(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Int): ComplexFloat = ComplexFloat(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Long): ComplexFloat = ComplexFloat(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Float): ComplexFloat = ComplexFloat(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Double): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: ComplexFloat): ComplexFloat =
        ComplexFloat(re * other.re - im * other.im, re * other.im + other.re * im)

    /** Multiplies this value by the other value. */
    public operator fun times(other: ComplexDouble): ComplexDouble =
        ComplexDouble(re * other.re - im * other.im, re * other.im + other.re * im)

    /** Divides this value by the other value. */
    public operator fun div(other: Byte): ComplexFloat = ComplexFloat(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Short): ComplexFloat = ComplexFloat(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Int): ComplexFloat = ComplexFloat(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Long): ComplexFloat = ComplexFloat(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Float): ComplexFloat = ComplexFloat(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Double): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: ComplexFloat): ComplexFloat = when {
        abs(other.re) > abs(other.im) -> {
            val dr = other.im / other.re
            val dd = other.re + dr * other.im

            if (dd.isNaN() || dd == 0f) throw ArithmeticException("Division by zero or infinity")

            ComplexFloat((re + im * dr) / dd, (im - re * dr) / dd)
        }

        other.im == 0f -> throw ArithmeticException("Division by zero")

        else -> {
            val dr = other.re / other.im
            val dd = other.im + dr * other.re

            if (dd.isNaN() || dd == 0f) throw ArithmeticException("Division by zero or infinity")

            ComplexFloat((re * dr + im) / dd, (im * dr - re) / dd)
        }
    }

    /** Divides this value by the other value. */
    @Suppress("DuplicatedCode")
    public operator fun div(other: ComplexDouble): ComplexDouble = when {
        abs(other.re) > abs(other.im) -> {
            val dr = other.im / other.re
            val dd = other.re + dr * other.im

            if (dd.isNaN() || dd == 0.0) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re + im * dr) / dd, (im - re * dr) / dd)
        }

        other.im == 0.0 -> throw ArithmeticException("Division by zero")

        else -> {
            val dr = other.re / other.im
            val dd = other.im + dr * other.re

            if (dd.isNaN() || dd == 0.0) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re * dr + im) / dd, (im * dr - re) / dd)
        }
    }

    /** Returns this value. */
    public operator fun unaryPlus(): ComplexFloat = this

    /** Returns the negative of this value. */
    public operator fun unaryMinus(): ComplexFloat = ComplexFloat(-re, -im)

    public operator fun component1(): Float = re

    public operator fun component2(): Float = im

    override fun equals(other: Any?): Boolean = when {
        this === other -> true
        other is ComplexFloat -> re == other.re && im == other.im
        else -> false
    }

    override fun hashCode(): Int = 31 * re.toBits() + im.toBits()

    override fun toString(): String = "$re+($im)i"
}

public class ComplexDouble(public val re: Double, public val im: Double) : Complex {

    public constructor(re: Number, im: Number): this(re.toDouble(), im.toDouble())

    public constructor(re: Number): this(re.toDouble(), 0.0)

    public companion object {
        public val one: ComplexDouble
            get() = ComplexDouble(1.0, 0.0)

        public val zero: ComplexDouble
            get() = ComplexDouble(0.0, 0.0)

        public val NaN: ComplexDouble
            get() = ComplexDouble(Double.NaN, Double.NaN)
    }

    /** Returns complex conjugate value. */
    public fun conjugate(): ComplexDouble = ComplexDouble(re, -im)

    /** Returns absolute value of complex number. */
    public fun abs(): Double = sqrt(re * re + im * im)

    /** Returns angle of complex number. */
    public fun angle(): Double = atan2(im, re)

    /** Adds the other value to this value. */
    public operator fun plus(other: Byte): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Short): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Int): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Long): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Float): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: Double): ComplexDouble = ComplexDouble(re + other, im)

    /** Adds the other value to this value. */
    public operator fun plus(other: ComplexFloat): ComplexDouble = ComplexDouble(re + other.re, im + other.im)

    /** Adds the other value to this value. */
    public operator fun plus(other: ComplexDouble): ComplexDouble = ComplexDouble(re + other.re, im + other.im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Byte): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Short): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Int): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Long): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Float): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: Double): ComplexDouble = ComplexDouble(re - other, im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: ComplexFloat): ComplexDouble = ComplexDouble(re - other.re, im - other.im)

    /** Subtracts the other value from this value. */
    public operator fun minus(other: ComplexDouble): ComplexDouble = ComplexDouble(re - other.re, im - other.im)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Byte): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Short): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Int): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Long): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Float): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: Double): ComplexDouble = ComplexDouble(re * other, im * other)

    /** Multiplies this value by the other value. */
    public operator fun times(other: ComplexFloat): ComplexDouble =
        ComplexDouble(re * other.re - im * other.im, re * other.im + other.re * im)

    /** Multiplies this value by the other value. */
    public operator fun times(other: ComplexDouble): ComplexDouble =
        ComplexDouble(re * other.re - im * other.im, re * other.im + other.re * im)

    /** Divides this value by the other value. */
    public operator fun div(other: Byte): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Short): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Int): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Long): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Float): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: Double): ComplexDouble = ComplexDouble(re / other, im / other)

    /** Divides this value by the other value. */
    public operator fun div(other: ComplexFloat): ComplexDouble = when {
        abs(other.re) > abs(other.im) -> {
            val dr = other.im / other.re
            val dd = other.re + dr * other.im

            if (dd.isNaN() || dd == 0f) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re + im * dr) / dd, (im - re * dr) / dd)
        }

        other.im == 0f -> throw ArithmeticException("Division by zero")

        else -> {
            val dr = other.re / other.im
            val dd = other.im + dr * other.re

            if (dd.isNaN() || dd == 0f) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re * dr + im) / dd, (im * dr - re) / dd)
        }
    }

    /** Divides this value by the other value. */
    @Suppress("DuplicatedCode")
    public operator fun div(other: ComplexDouble): ComplexDouble = when {
        abs(other.re) > abs(other.im) -> {
            val dr = other.im / other.re
            val dd = other.re + dr * other.im

            if (dd.isNaN() || dd == 0.0) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re + im * dr) / dd, (im - re * dr) / dd)
        }

        other.im == 0.0 -> throw ArithmeticException("Division by zero")

        else -> {
            val dr = other.re / other.im
            val dd = other.im + dr * other.re

            if (dd.isNaN() || dd == 0.0) throw ArithmeticException("Division by zero or infinity")

            ComplexDouble((re * dr + im) / dd, (im * dr - re) / dd)
        }
    }

    /** Returns this value. */
    public operator fun unaryPlus(): ComplexDouble = this

    /** Returns the negative of this value. */
    public operator fun unaryMinus(): ComplexDouble = ComplexDouble(-re, -im)

    public operator fun component1(): Double = re

    public operator fun component2(): Double = im

    override fun equals(other: Any?): Boolean = when {
        this === other -> true
        other is ComplexDouble -> re == other.re && im == other.im
        else -> false
    }

    override fun hashCode(): Int = 31 * re.toBits().hashCode() + im.toBits().hashCode()

    override fun toString(): String = "$re+($im)i"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy