Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
fuookami.ospf.kotlin.utils.math.ValueRange.kt Maven / Gradle / Ivy
package fuookami.ospf.kotlin.utils.math
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.ordinary.*
import fuookami.ospf.kotlin.utils.operator.*
private data object IntervalTypeSerializer : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("IntervalType", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: IntervalType) {
encoder.encodeString(value.toString().lowercase(Locale.getDefault()))
}
override fun deserialize(decoder: Decoder): IntervalType {
return IntervalType.valueOf(decoder.decodeString()
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() })
}
}
@Serializable(with = IntervalTypeSerializer::class)
enum class IntervalType {
Open {
override val lowerSign = "("
override val upperSign = ")"
override fun union(rhs: IntervalType) = rhs
override fun intersect(rhs: IntervalType) = Open
},
Closed {
override val lowerSign = "["
override val upperSign = "]"
override fun union(rhs: IntervalType) = Closed
override fun intersect(rhs: IntervalType) = rhs
};
abstract val lowerSign: String
abstract val upperSign: String
abstract infix fun union(rhs: IntervalType): IntervalType
abstract infix fun intersect(rhs: IntervalType): IntervalType
}
private typealias GlobalInfinity = Infinity
private 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
}
}
open class ValueRangeSerializer(
private val valueSerializer: ValueWrapperSerializer
) : KSerializer> where T : RealNumber, T : NumberField {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("ValueRange") {
element("lowerBound")
element("upperBound")
element("lowerInterval")
element("upperInterval")
}
override fun serialize(encoder: Encoder, value: ValueRange) {
require(encoder is JsonEncoder)
encoder.encodeJsonElement(
buildJsonObject {
put("lowerBound", encoder.json.encodeToJsonElement(valueSerializer, value.lowerBound))
put("upperBound", encoder.json.encodeToJsonElement(valueSerializer, value.upperBound))
put("lowerInterval", value.lowerInterval.toString().lowercase(Locale.getDefault()))
put("upperInterval", value.upperInterval.toString().lowercase(Locale.getDefault()))
}
)
}
@OptIn(ExperimentalSerializationApi::class)
override fun deserialize(decoder: Decoder): ValueRange {
require(decoder is JsonDecoder)
val element = decoder.decodeJsonElement()
require(element is JsonObject)
require(descriptor.elementNames.all { it in element })
return ValueRange(
decoder.json.decodeFromJsonElement(valueSerializer, element["lowerBound"]!!),
decoder.json.decodeFromJsonElement(valueSerializer, element["upperBound"]!!),
IntervalType.valueOf(element["lowerInterval"]!!.jsonPrimitive.content.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
}),
IntervalType.valueOf(element["upperInterval"]!!.jsonPrimitive.content.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
}),
valueSerializer.constants
)
}
}
data object ValueRangeInt64Serializer : ValueRangeSerializer(ValueWrapperSerializer())
data object ValueRangeUInt64Serializer : ValueRangeSerializer(ValueWrapperSerializer())
data object ValueRangeFlt64Serializer : ValueRangeSerializer(ValueWrapperSerializer())
// todo: Bound
data class ValueRange(
private val _lowerBound: ValueWrapper,
private val _upperBound: ValueWrapper,
val lowerInterval: IntervalType,
val upperInterval: IntervalType,
private val constants: RealNumberConstants
) : Cloneable, Copyable>,
Plus, ValueRange>, Minus, ValueRange>,
Times, ValueRange>, Div>, Eq>
where T : RealNumber, T : NumberField {
companion object {
@Suppress("UNCHECKED_CAST")
inline operator fun invoke(
lowerBound: T,
upperBound: T,
lowerInterval: IntervalType = IntervalType.Closed,
upperInterval: IntervalType = IntervalType.Closed
): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Value(upperBound, constants),
lowerInterval,
upperInterval,
constants
)
}
operator fun invoke(
lowerBound: T,
upperBound: T,
lowerInterval: IntervalType,
upperInterval: IntervalType,
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Value(upperBound, constants),
lowerInterval,
upperInterval,
constants
)
}
@Suppress("UNCHECKED_CAST")
inline operator fun invoke(
_inf: GlobalNegativeInfinity,
upperBound: T,
upperInterval: IntervalType = IntervalType.Closed
): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Value(upperBound, constants),
IntervalType.Open,
upperInterval,
constants
)
}
operator fun invoke(
_inf: GlobalNegativeInfinity,
upperBound: T,
upperInterval: IntervalType,
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Value(upperBound, constants),
IntervalType.Open,
upperInterval,
constants
)
}
@Suppress("UNCHECKED_CAST")
inline operator fun invoke(
lowerBound: T,
_inf: GlobalInfinity,
lowerInterval: IntervalType = IntervalType.Closed
): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Infinity(constants),
lowerInterval,
IntervalType.Open,
constants
)
}
operator fun invoke(
lowerBound: T,
_inf: GlobalInfinity,
lowerInterval: IntervalType,
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Infinity(constants),
lowerInterval,
IntervalType.Open,
constants
)
}
@Suppress("UNCHECKED_CAST")
inline operator fun invoke(): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Infinity(constants),
IntervalType.Open,
IntervalType.Open,
constants
)
}
operator fun invoke(
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Infinity(constants),
IntervalType.Open,
IntervalType.Open,
constants
)
}
}
override fun copy() = ValueRange(
_lowerBound,
_upperBound,
lowerInterval,
upperInterval,
constants
)
public override fun clone() = copy()
val lowerBound: ValueWrapper
get() {
@Throws(IllegalArgumentException::class)
if (empty) {
throw IllegalArgumentException("Illegal argument of value range: ${lowerInterval.lowerSign}${_lowerBound}, ${_upperBound}${upperInterval.upperSign}!!!")
}
return _lowerBound
}
val upperBound: ValueWrapper
get() {
@Throws(IllegalArgumentException::class)
if (empty) {
throw IllegalArgumentException("Illegal argument of value range: ${lowerInterval.lowerSign}${_lowerBound}, ${_upperBound}${upperInterval.upperSign}!!!")
}
return _upperBound
}
val mean: ValueWrapper
get() {
@Throws(IllegalArgumentException::class)
if (empty) {
throw IllegalArgumentException("Illegal argument of value range: ${lowerInterval.lowerSign}${_lowerBound}, ${_upperBound}${upperInterval.upperSign}!!!")
}
return (_lowerBound + _upperBound) / constants.two
}
val fixed by lazy {
lowerInterval == IntervalType.Closed
&& upperInterval == IntervalType.Closed
&& !lowerBound.isInfinityOrNegativeInfinity
&& !upperBound.isInfinityOrNegativeInfinity
&& lowerBound eq upperBound
}
val empty by lazy {
if (lowerInterval == IntervalType.Closed && upperInterval == IntervalType.Closed) {
_lowerBound gr _upperBound
} else {
_lowerBound geq _upperBound
}
}
val fixedValue: T? by lazy {
if (fixed) {
(lowerBound as ValueWrapper.Value).value
} else {
null
}
}
operator fun contains(value: T): Boolean {
val wrapper = ValueWrapper.Value(value, constants)
return when (lowerInterval) {
IntervalType.Open -> lowerBound ls wrapper
IntervalType.Closed -> lowerBound leq wrapper
} && when (upperInterval) {
IntervalType.Open -> upperBound gr wrapper
IntervalType.Closed -> upperBound geq wrapper
}
}
operator fun contains(value: ValueRange): Boolean {
return when (lowerInterval) {
IntervalType.Open -> lowerBound ls value.lowerBound
IntervalType.Closed -> lowerBound leq value.lowerBound
} && when (upperInterval) {
IntervalType.Open -> upperBound gr value.upperBound
IntervalType.Closed -> upperBound geq value.upperBound
}
}
override fun plus(rhs: ValueRange) = ValueRange(
lowerBound + rhs.lowerBound,
upperBound + rhs.upperBound,
lowerInterval intersect rhs.lowerInterval,
upperInterval intersect rhs.upperInterval,
constants
)
operator fun plus(rhs: T) = ValueRange(
lowerBound + rhs,
upperBound + rhs,
lowerInterval,
upperInterval,
constants
)
override fun minus(rhs: ValueRange) = ValueRange(
lowerBound - rhs.upperBound,
upperBound - rhs.lowerBound,
lowerInterval intersect rhs.lowerInterval,
upperInterval intersect rhs.upperInterval,
constants
)
operator fun minus(rhs: T) = ValueRange(
lowerBound - rhs,
upperBound - rhs,
lowerInterval,
upperInterval,
constants
)
override fun times(rhs: ValueRange): ValueRange {
val bounds = listOf(
Pair(lowerBound * rhs.lowerBound, lowerInterval intersect rhs.lowerInterval),
Pair(lowerBound * rhs.upperBound, lowerInterval intersect rhs.upperInterval),
Pair(upperBound * rhs.lowerBound, upperInterval intersect rhs.lowerInterval),
Pair(upperBound * rhs.upperBound, upperInterval intersect rhs.upperInterval)
)
val newLowerBound = bounds.minBy { it.first }
val newUpperBound = bounds.maxBy { it.first }
return ValueRange(
newLowerBound.first,
newUpperBound.first,
newLowerBound.second,
newUpperBound.second,
constants
)
}
operator fun times(rhs: T) = when {
rhs < constants.zero -> ValueRange(
upperBound * rhs,
lowerBound * rhs,
lowerInterval,
upperInterval,
constants
)
else -> ValueRange(
lowerBound * rhs,
upperBound * rhs,
lowerInterval,
upperInterval,
constants
)
}
override fun div(rhs: T) = when {
rhs < constants.zero -> ValueRange(
upperBound / rhs,
lowerBound / rhs,
lowerInterval,
upperInterval,
constants
)
else -> ValueRange(
lowerBound / rhs,
upperBound / rhs,
lowerInterval,
upperInterval,
constants
)
}
override fun partialEq(rhs: ValueRange): Boolean {
return lowerBound eq rhs.lowerBound
&& upperBound eq rhs.upperBound
&& lowerInterval == rhs.lowerInterval
&& upperInterval == rhs.upperInterval
}
infix fun intersect(rhs: ValueRange) = ValueRange(
max(lowerBound, rhs.lowerBound),
min(upperBound, rhs.upperBound),
lowerInterval intersect rhs.lowerInterval,
upperInterval intersect rhs.upperInterval,
constants
)
fun toFlt64() = ValueRange(
lowerBound.toFlt64(),
upperBound.toFlt64(),
lowerInterval,
upperInterval
)
override fun toString() = "${lowerInterval.lowerSign}$lowerBound, $upperBound${upperInterval.upperSign}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ValueRange<*>
if (_lowerBound != other._lowerBound) return false
if (_upperBound != other._upperBound) return false
if (lowerInterval != other.lowerInterval) return false
if (upperInterval != other.upperInterval) return false
return true
}
override fun hashCode(): Int {
var result = _lowerBound.hashCode()
result = 31 * result + _upperBound.hashCode()
result = 31 * result + lowerInterval.hashCode()
result = 31 * result + upperInterval.hashCode()
return result
}
}
operator fun T.times(rhs: ValueRange) where T : RealNumber, T : NumberField = rhs * this