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

fuookami.ospf.kotlin.utils.math.value_range.ValueWrapper.kt Maven / Gradle / Ivy

There is a newer version: 1.0.29
Show newest version
package fuookami.ospf.kotlin.utils.math.value_range

import java.util.*
import kotlin.reflect.full.*
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
import fuookami.ospf.kotlin.utils.concept.*
import fuookami.ospf.kotlin.utils.math.*
import fuookami.ospf.kotlin.utils.math.ordinary.*
import fuookami.ospf.kotlin.utils.operator.*

internal typealias GlobalInfinity = Infinity
internal typealias GlobalNegativeInfinity = NegativeInfinity

class ValueWrapperSerializer(
    private val valueSerializer: KSerializer,
    internal val constants: RealNumberConstants
) : KSerializer> where T : RealNumber, T : NumberField {
    companion object {
        @Suppress("UNCHECKED_CAST")
        @OptIn(InternalSerializationApi::class)
        inline operator fun  invoke(): ValueWrapperSerializer where T : RealNumber, T : NumberField {
            val serializer = T::class.serializer()
            val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
            return ValueWrapperSerializer(serializer, constants)
        }
    }

    @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
    override val descriptor: SerialDescriptor = buildSerialDescriptor("ValueWrapper", PolymorphicKind.SEALED) {
        element("Value", valueSerializer.descriptor)
        element("Infinity", PrimitiveSerialDescriptor("Infinity", PrimitiveKind.DOUBLE))
        element("NegativeInfinity", PrimitiveSerialDescriptor("NegativeInfinity", PrimitiveKind.DOUBLE))
    }

    override fun serialize(encoder: Encoder, value: ValueWrapper) {
        require(encoder is JsonEncoder)
        val element = when (value) {
            is ValueWrapper.Value -> encoder.json.encodeToJsonElement(valueSerializer, value.value)
            is ValueWrapper.Infinity -> encoder.json.encodeToJsonElement(Double.POSITIVE_INFINITY)
            is ValueWrapper.NegativeInfinity -> encoder.json.encodeToJsonElement(Double.NEGATIVE_INFINITY)
        }
        encoder.encodeJsonElement(element)
    }

    override fun deserialize(decoder: Decoder): ValueWrapper {
        require(decoder is JsonDecoder)
        val element = decoder.decodeJsonElement()
        return when (element.jsonPrimitive.doubleOrNull) {
            Double.POSITIVE_INFINITY -> {
                ValueWrapper.Infinity(constants)
            }

            Double.NEGATIVE_INFINITY -> {
                ValueWrapper.NegativeInfinity(constants)
            }

            else -> {
                ValueWrapper.Value(decoder.json.decodeFromJsonElement(valueSerializer, element), constants)
            }
        }
    }
}

sealed class ValueWrapper(
    val constants: RealNumberConstants
) : Cloneable, Copyable>, Ord>, Eq>,
    Plus, ValueWrapper>, Minus, ValueWrapper>,
    Times, ValueWrapper>, Div, ValueWrapper>
        where T : RealNumber, T : NumberField {
    companion object {
        @Throws(IllegalArgumentException::class)
        @Suppress("UNCHECKED_CAST")
        inline operator fun  invoke(
            value: T
        ): ValueWrapper where T : RealNumber, T : NumberField {
            val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
            return when (value) {
                constants.infinity -> Infinity(constants)
                constants.negativeInfinity -> NegativeInfinity(constants)
                constants.nan -> throw IllegalArgumentException("Illegal argument NaN for value range!!!")
                else -> Value(value, constants)
            }
        }

        @Suppress("UNCHECKED_CAST")
        inline operator fun  invoke(
            _inf: GlobalInfinity
        ): ValueWrapper where T : RealNumber, T : NumberField {
            val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
            return Infinity(constants)
        }

        @Suppress("UNCHECKED_CAST")
        inline operator fun  invoke(
            _negInf: GlobalNegativeInfinity
        ): ValueWrapper where T : RealNumber, T : NumberField {
            val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
            return NegativeInfinity(constants)
        }
    }

    val isInfinity get() = this is Infinity
    val isNegativeInfinity get() = this is NegativeInfinity
    val isInfinityOrNegativeInfinity by lazy { isInfinity && isNegativeInfinity }

    abstract operator fun plus(rhs: T): ValueWrapper
    abstract operator fun minus(rhs: T): ValueWrapper
    abstract operator fun times(rhs: T): ValueWrapper
    abstract operator fun div(rhs: T): ValueWrapper

    abstract fun toFlt64(): Flt64

    fun unwrap(): T {
        return (this as Value).value
    }

    fun unwrapOrNull(): T? {
        return when (this) {
            is Value -> {
                this.value
            }

            is Infinity -> {
                constants.infinity
            }

            is NegativeInfinity -> {
                constants.negativeInfinity
            }
        }
    }

    class Value(val value: T, constants: RealNumberConstants) :
        ValueWrapper(constants) where T : RealNumber, T : NumberField {
        init {
            assert(value != constants.infinity)
            assert(value != constants.negativeInfinity)
            assert(value != constants.nan)
        }

        override fun copy() = Value(value.copy(), constants)
        public override fun clone() = copy()

        override fun partialEq(rhs: ValueWrapper): Boolean = when (rhs) {
            is Value -> value.eq(rhs.value)
            else -> false
        }

        override fun partialOrd(rhs: ValueWrapper) = when (rhs) {
            is Value -> value.ord(rhs.value)
            is Infinity -> orderOf(-1)
            is NegativeInfinity -> orderOf(1)
        }

        override fun plus(rhs: T): ValueWrapper = Value(value + rhs, constants)
        override fun plus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Value(value + rhs.value, constants)
            is Infinity -> Infinity(constants)
            is NegativeInfinity -> NegativeInfinity(constants)
        }

        override fun minus(rhs: T): ValueWrapper = Value(value - rhs, constants)
        override fun minus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Value(value - rhs.value, constants)
            is Infinity -> NegativeInfinity(constants)
            is NegativeInfinity -> Infinity(constants)
        }

        override fun times(rhs: T): ValueWrapper = Value(value * rhs, constants)
        override fun times(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Value(value * rhs.value, constants)
            is Infinity -> if (value < constants.zero) {
                NegativeInfinity(constants)
            } else if (value > constants.zero) {
                Infinity(constants)
            } else {
                Value(constants.zero, constants)
            }

            is NegativeInfinity -> if (value < constants.zero) {
                Infinity(constants)
            } else if (value > constants.zero) {
                NegativeInfinity(constants)
            } else {
                Value(constants.zero, constants)
            }
        }

        override fun div(rhs: T): ValueWrapper = Value(value / rhs, constants)
        override fun div(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Value(value / rhs.value, constants)
            is Infinity -> if (value < constants.zero) {
                Value(-constants.epsilon, constants)
            } else if (value > constants.zero) {
                Value(constants.epsilon, constants)
            } else {
                Value(constants.zero, constants)
            }

            is NegativeInfinity -> if (value < constants.zero) {
                Value(constants.epsilon, constants)
            } else if (value > constants.zero) {
                Value(-constants.epsilon, constants)
            } else {
                Value(constants.zero, constants)
            }
        }

        override fun toString() = "$value"
        override fun toFlt64() = value.toFlt64()
    }

    class Infinity(constants: RealNumberConstants) :
        ValueWrapper(constants) where T : RealNumber, T : NumberField {
        override fun copy() = Infinity(constants)
        public override fun clone() = copy()

        override fun partialEq(rhs: ValueWrapper): Boolean = rhs is Infinity
        override fun partialOrd(rhs: ValueWrapper) = when (rhs) {
            is Infinity -> orderOf(0)
            else -> orderOf(1)
        }

        @Throws(IllegalArgumentException::class)
        override fun plus(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid plus between inf and nan!!!")
            rhs.constants.negativeInfinity -> throw IllegalArgumentException("Invalid plus between inf and -inf!!!")
            else -> Infinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun plus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Infinity(constants)
            is Infinity -> Infinity(constants)
            is NegativeInfinity -> throw IllegalArgumentException("Invalid plus between inf and -inf!!!")
        }

        @Throws(IllegalArgumentException::class)
        override fun minus(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid minus between inf and nan!!!")
            rhs.constants.infinity -> throw IllegalArgumentException("Invalid minus between inf and inf!!!")
            else -> Infinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun minus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> Infinity(constants)
            is Infinity -> throw IllegalArgumentException("Invalid minus between inf and inf!!!")
            is NegativeInfinity -> Infinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun times(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid times between inf and nan!!!")
            rhs.constants.negativeInfinity -> NegativeInfinity(constants)
            rhs.constants.infinity -> Infinity(constants)
            rhs.constants.zero -> Value(constants.zero, constants)
            else -> if (rhs < rhs.constants.zero) {
                NegativeInfinity(constants)
            } else {
                Infinity(constants)
            }
        }

        @Throws(IllegalArgumentException::class)
        override fun times(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> if (rhs.value < rhs.constants.zero) {
                NegativeInfinity(constants)
            } else if (rhs.value > rhs.constants.zero) {
                Infinity(constants)
            } else {
                Value(constants.zero, constants)
            }

            is Infinity -> Infinity(constants)
            is NegativeInfinity -> NegativeInfinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun div(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid div between inf and nan!!!")
            rhs.constants.infinity -> throw IllegalArgumentException("Invalid div between inf and inf!!!")
            rhs.constants.negativeInfinity -> throw IllegalArgumentException("Invalid div between inf and -inf!!!")
            rhs.constants.zero -> throw IllegalArgumentException("Invalid div between inf and 0!!!")
            else -> if (rhs < rhs.constants.zero) {
                NegativeInfinity(constants)
            } else {
                Infinity(constants)
            }
        }

        @Throws(IllegalArgumentException::class)
        override fun div(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> if (rhs.value < rhs.constants.zero) {
                NegativeInfinity(constants)
            } else if (rhs.value > rhs.constants.zero) {
                Infinity(constants)
            } else {
                throw IllegalArgumentException("Invalid div between inf and 0!!!")
            }

            is Infinity -> throw IllegalArgumentException("Invalid div between inf and inf!!!")
            is NegativeInfinity -> throw IllegalArgumentException("Invalid div between inf and -inf!!!")
        }

        override fun toString() = "inf"
        override fun toFlt64() = Flt64.infinity
    }

    class NegativeInfinity(constants: RealNumberConstants) :
        ValueWrapper(constants) where T : RealNumber, T : NumberField {
        override fun copy() = Infinity(constants)
        public override fun clone() = copy()

        override fun partialEq(rhs: ValueWrapper): Boolean = rhs is NegativeInfinity
        override fun partialOrd(rhs: ValueWrapper) = when (rhs) {
            is NegativeInfinity -> orderOf(0)
            else -> orderOf(-1)
        }

        @Throws(IllegalArgumentException::class)
        override fun plus(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid plus between inf and nan!!!")
            rhs.constants.infinity -> throw IllegalArgumentException("Invalid plus between -inf and inf!!!")
            else -> NegativeInfinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun plus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> NegativeInfinity(constants)
            is Infinity -> throw IllegalArgumentException("Invalid plus between -inf and inf!!!")
            is NegativeInfinity -> NegativeInfinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun minus(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid minus between -inf and nan!!!")
            rhs.constants.negativeInfinity -> throw IllegalArgumentException("Invalid minus between -inf and -inf!!!")
            else -> NegativeInfinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun minus(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> NegativeInfinity(constants)
            is Infinity -> NegativeInfinity(constants)
            is NegativeInfinity -> throw IllegalArgumentException("Invalid minus between -inf and -inf!!!")
        }

        @Throws(IllegalArgumentException::class)
        override fun times(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid times between -inf and nan!!!")
            rhs.constants.negativeInfinity -> Infinity(constants)
            rhs.constants.infinity -> NegativeInfinity(constants)
            rhs.constants.zero -> Value(constants.zero, constants)
            else -> if (rhs < rhs.constants.zero) {
                Infinity(constants)
            } else {
                NegativeInfinity(constants)
            }
        }

        @Throws(IllegalArgumentException::class)
        override fun times(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> if (rhs.value < rhs.constants.zero) {
                Infinity(constants)
            } else if (rhs.value > rhs.constants.zero) {
                NegativeInfinity(constants)
            } else {
                Value(constants.zero, constants)
            }

            is Infinity -> NegativeInfinity(constants)
            is NegativeInfinity -> Infinity(constants)
        }

        @Throws(IllegalArgumentException::class)
        override fun div(rhs: T): ValueWrapper = when (rhs) {
            rhs.constants.nan -> throw IllegalArgumentException("Invalid div between -inf and nan!!!")
            rhs.constants.negativeInfinity -> throw IllegalArgumentException("Invalid div between -inf and -inf!!!")
            rhs.constants.infinity -> throw IllegalArgumentException("Invalid div between -inf and inf!!!")
            rhs.constants.zero -> throw IllegalArgumentException("Invalid div between -inf and 0!!!")
            else -> if (rhs < rhs.constants.zero) {
                Infinity(constants)
            } else {
                NegativeInfinity(constants)
            }
        }

        @Throws(IllegalArgumentException::class)
        override fun div(rhs: ValueWrapper): ValueWrapper = when (rhs) {
            is Value -> if (rhs.value < rhs.constants.zero) {
                Infinity(constants)
            } else if (rhs.value > rhs.constants.zero) {
                NegativeInfinity(constants)
            } else {
                throw IllegalArgumentException("Invalid div between -inf and 0!!!")
            }

            is Infinity -> throw IllegalArgumentException("Invalid div between -inf and inf!!!")
            is NegativeInfinity -> throw IllegalArgumentException("Invalid div between -inf and -inf!!!")
        }

        override fun toString() = "-inf"
        override fun toFlt64() = Flt64.negativeInfinity
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy