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.*
import fuookami.ospf.kotlin.utils.math.value_range.*
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"]!!),
Interval.valueOf(element["lowerInterval"]!!.jsonPrimitive.content.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
}),
Interval.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: Interval,
val upperInterval: Interval,
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: Interval = Interval.Closed,
upperInterval: Interval = Interval.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: Interval,
upperInterval: Interval,
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: Interval = Interval.Closed
): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Value(upperBound, constants),
Interval.Open,
upperInterval,
constants
)
}
operator fun invoke(
_inf: GlobalNegativeInfinity,
upperBound: T,
upperInterval: Interval,
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Value(upperBound, constants),
Interval.Open,
upperInterval,
constants
)
}
@Suppress("UNCHECKED_CAST")
inline operator fun invoke(
lowerBound: T,
_inf: GlobalInfinity,
lowerInterval: Interval = Interval.Closed
): ValueRange where T : RealNumber, T : NumberField {
val constants = (T::class.companionObjectInstance!! as RealNumberConstants)
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Infinity(constants),
lowerInterval,
Interval.Open,
constants
)
}
operator fun invoke(
lowerBound: T,
_inf: GlobalInfinity,
lowerInterval: Interval,
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.Value(lowerBound, constants),
ValueWrapper.Infinity(constants),
lowerInterval,
Interval.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),
Interval.Open,
Interval.Open,
constants
)
}
operator fun invoke(
constants: RealNumberConstants
): ValueRange where T : RealNumber, T : NumberField {
return ValueRange(
ValueWrapper.NegativeInfinity(constants),
ValueWrapper.Infinity(constants),
Interval.Open,
Interval.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 == Interval.Closed
&& upperInterval == Interval.Closed
&& !lowerBound.isInfinityOrNegativeInfinity
&& !upperBound.isInfinityOrNegativeInfinity
&& lowerBound eq upperBound
}
val empty by lazy {
if (lowerInterval == Interval.Closed && upperInterval == Interval.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) {
Interval.Open -> lowerBound ls wrapper
Interval.Closed -> lowerBound leq wrapper
} && when (upperInterval) {
Interval.Open -> upperBound gr wrapper
Interval.Closed -> upperBound geq wrapper
}
}
operator fun contains(value: ValueRange): Boolean {
return when (lowerInterval) {
Interval.Open -> lowerBound ls value.lowerBound
Interval.Closed -> lowerBound leq value.lowerBound
} && when (upperInterval) {
Interval.Open -> upperBound gr value.upperBound
Interval.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.toFlt64() neq other._lowerBound.toFlt64()) return false
if (_upperBound.toFlt64() neq other._upperBound.toFlt64()) 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