commonMain.io.nacular.measured.units2.Measure2.kt Maven / Gradle / Ivy
package io.nacular.measured.units2
import io.nacular.measured.units.*
import kotlin.jvm.JvmName
import kotlin.math.roundToInt
/**
* Created by Nicholas Eddy on 6/14/20.
*/
interface Measure2 {
val amount: Double
infix fun `as`(other: A): Measure2
infix fun `in`(other: A): Double
operator fun unaryMinus(): Measure2
/**
* Multiply this by a scalar value, used for things like "double this distance",
* "1.5 times the speed", etc
*/
operator fun times(other: Number): Measure2
/**
* Divide this by a scalar, used for things like "halve the speed"
*/
operator fun div(other: Number): Measure2
fun roundToInt(): Measure2
fun print(units: T): String
}
class ConcreteMeasure(override val amount: Double, val units: T): Measure2 {
/**
* Convert this type into another compatible type.
* Type must share parent
* (eg Mile into Kilometer, because they both are made from Distance)
*/
override infix fun `as`(other: A): Measure2 = if (units == other) this else ConcreteMeasure(this `in` other, other)
override infix fun `in`(other: A): Double = if (units == other) amount else amount * (units.ratio / other.ratio)
override operator fun unaryMinus(): Measure2 = ConcreteMeasure(-amount, units)
/**
* Multiply this by a scalar value, used for things like "double this distance",
* "1.5 times the speed", etc
*/
override operator fun times(other: Number): Measure2 = ConcreteMeasure(amount * other.toDouble(), units)
/**
* Divide this by a scalar, used for things like "halve the speed"
*/
override operator fun div(other: Number): Measure2 = ConcreteMeasure(amount / other.toDouble(), units)
override fun roundToInt(): Measure2 = ConcreteMeasure(amount.roundToInt().toDouble(), units)
// override fun equals(other: Any?): Boolean {
// if (this === other) return true
// if (other !is Measure2<*>) return false
//// if (this.amount == 0.0 && other.amount == 0.0) return true TODO: Should this be true?
//
// val resultUnits = minOf(Units, (other as Measure2).Units)
//
// val a = this `in` resultUnits
// val b = other `in` resultUnits
//
// return a == b
// }
override fun hashCode(): Int {
return (amount * units.ratio).hashCode()
}
override fun print(units: T) = "$amount${this.units.measureSuffix()}"
override fun toString(): String = print(units)
fun inline(): InlineMeasure = InlineMeasure(amount * units.ratio)
}
inline class InlineMeasure(override val amount: Double): Measure2 {
override infix fun `as`(other: A): Measure2 = InlineMeasure(amount / other.ratio)
override infix fun `in`(other: A): Double = amount / other.ratio
override fun unaryMinus(): Measure2 = InlineMeasure(-amount)
override fun times(other: Number): Measure2 = InlineMeasure(amount * other.toDouble())
override fun div(other: Number): Measure2 = InlineMeasure(amount / other.toDouble())
override fun roundToInt(): Measure2 = InlineMeasure(amount.roundToInt().toDouble())
override fun print(units: T) = ConcreteMeasure(amount / units.ratio, units).toString()
}
/** A * (B / A) */ operator fun A.times(other: UnitsRatio): ConcreteMeasure = this.ratio / other.denominator.ratio * other.numerator
/** A / (A / B) == A * (B / A) */ operator fun A.div (other: UnitsRatio): ConcreteMeasure = this * other.reciprocal
/** (A * B) / A */ @JvmName("div1") operator fun UnitsProduct.div(other: A ): ConcreteMeasure = first.ratio / other.ratio * second
/** (A * B) / B */ @JvmName("div2") operator fun UnitsProduct.div(other: B ): ConcreteMeasure = second.ratio / other.ratio * first
/** (A * A) / A */ @JvmName("div3") operator fun UnitsProduct.div(other: A ): ConcreteMeasure = first.ratio / other.ratio * second
/** (A * B) / (B * B) */ @JvmName("div8") operator fun UnitsProduct.div(other: UnitsProduct): ConcreteMeasure> = second.ratio / other.second.ratio * (first / other.first)
/** (A / B) * B */ @JvmName("times1") operator fun UnitsRatio. times(other: B ): ConcreteMeasure = other.ratio / denominator.ratio * numerator
/** (A / (B * C)) * B */ @JvmName("times2") operator fun UnitsRatio>.times(other: B ): ConcreteMeasure> = other.ratio / denominator.first.ratio * (numerator / denominator.second)
@JvmName("div1") operator fun UnitsRatio, UnitsProduct>.div(other: A ): ConcreteMeasure>> = numerator.first.ratio / other.ratio * (numerator.second / denominator)
@JvmName("div2") operator fun UnitsRatio, UnitsProduct>.div(other: A ): ConcreteMeasure>> = numerator.first.ratio / other.ratio * (numerator.second / denominator)
@JvmName("div3") operator fun UnitsRatio, UnitsProduct>.div(other: A ): ConcreteMeasure>> = numerator.first.ratio / other.ratio * (numerator.second / denominator)
// m/s * (s2/m) => s
operator fun UnitsRatio.div(other: UnitsRatio>): ConcreteMeasure = numerator.ratio / other.numerator.ratio * (other.denominator / denominator)
@JvmName("times1") operator fun ConcreteMeasure. times(other: ConcreteMeasure): ConcreteMeasure> = amount * other.amount * (units * other.units)
@JvmName("times2") operator fun ConcreteMeasure. times(other: ConcreteMeasure>): ConcreteMeasure = amount * other.amount * (units * other.units)
@JvmName("times7") operator fun ConcreteMeasure. times(other: ConcreteMeasure>): ConcreteMeasure> = amount * other.amount * (units * other.units)
@JvmName("times3") operator fun ConcreteMeasure>. times(other: ConcreteMeasure): ConcreteMeasure = amount * other.amount * (units * other.units)
@JvmName("times4") operator fun ConcreteMeasure>. times(other: ConcreteMeasure>): ConcreteMeasure, UnitsProduct>> = amount * other.amount * (units * other.units)
@JvmName("times5") operator fun ConcreteMeasure>>.times(other: ConcreteMeasure): ConcreteMeasure> = amount * other.amount * (units * other.units)
@JvmName("times6") operator fun ConcreteMeasure>>.times(other: ConcreteMeasure): ConcreteMeasure, UnitsProduct>> = amount * other.amount * (units * other.units)
@JvmName("times1") operator fun ConcreteMeasure. times(other: B ): ConcreteMeasure> = amount * (units * other)
@JvmName("times2") operator fun ConcreteMeasure. times(other: UnitsRatio): ConcreteMeasure = amount * (units * other)
@JvmName("times7") operator fun ConcreteMeasure. times(other: InverseUnits ): ConcreteMeasure> = amount * (units * other)
@JvmName("times3") operator fun ConcreteMeasure>. times(other: B ): ConcreteMeasure = amount * (units * other)
@JvmName("times4") operator fun ConcreteMeasure>. times(other: UnitsRatio): ConcreteMeasure, UnitsProduct>> = amount * (units * other)
@JvmName("times5") operator fun ConcreteMeasure>>.times(other: B ): ConcreteMeasure> = amount * (units * other)
@JvmName("times6") operator fun ConcreteMeasure>>.times(other: D ): ConcreteMeasure, UnitsProduct>> = amount * (units * other)
// TODO: Kapt code generation possible?
operator fun ConcreteMeasure.rem(other: ConcreteMeasure): Double = amount % other.amount * (units.ratio % other.units.ratio)
@JvmName("div16") operator fun ConcreteMeasure. div(other: ConcreteMeasure): Double = amount / other.amount * (units.ratio / other.units.ratio)
@JvmName("div16") operator fun ConcreteMeasure. div(other: ConcreteMeasure): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div1" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure): ConcreteMeasure = amount / other.amount * (units / other.units)
@JvmName("div2" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure): ConcreteMeasure = amount / other.amount * (units / other.units)
@JvmName("div3" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div4" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div5" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div6" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div7" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div8" ) operator fun ConcreteMeasure>.div(other: ConcreteMeasure>): ConcreteMeasure> = amount / other.amount * (units / other.units)
@JvmName("div16") operator fun ConcreteMeasure. div(other: A ): Double = amount * (units.ratio / other.ratio)
@JvmName("div16") operator fun ConcreteMeasure. div(other: B ): ConcreteMeasure> = amount * (units / other)
@JvmName("div1" ) operator fun ConcreteMeasure>.div(other: A ): ConcreteMeasure = amount * (units / other)
@JvmName("div2" ) operator fun ConcreteMeasure>.div(other: B ): ConcreteMeasure = amount * (units / other)
@JvmName("div3" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div4" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div5" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div6" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div7" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div8" ) operator fun ConcreteMeasure>.div(other: UnitsProduct): ConcreteMeasure> = amount * (units / other)
@JvmName("div9" ) operator fun ConcreteMeasure>. div(other: ConcreteMeasure): ConcreteMeasure>> = amount / other.amount * (units / other.units)
@JvmName("div10") operator fun ConcreteMeasure>. div(other: ConcreteMeasure>): ConcreteMeasure, UnitsProduct>> = amount / other.amount * (units / other.units)
@JvmName("div11") operator fun ConcreteMeasure>. div(other: ConcreteMeasure>>): ConcreteMeasure = amount / other.amount * (units / other.units)
@JvmName("div12") operator fun ConcreteMeasure, UnitsProduct>>.div(other: ConcreteMeasure): ConcreteMeasure>> = amount / other.amount * (units / other.units)
@JvmName("div13") operator fun ConcreteMeasure, UnitsProduct>>.div(other: ConcreteMeasure): ConcreteMeasure>> = amount / other.amount * (units / other.units)
@JvmName("div14") operator fun ConcreteMeasure, UnitsProduct>>.div(other: ConcreteMeasure): ConcreteMeasure>> = amount / other.amount * (units / other.units)
@JvmName("div15") operator fun ConcreteMeasure. div(other: ConcreteMeasure>): ConcreteMeasure = amount / other.amount * (units / other.units)
@JvmName("div9" ) operator fun ConcreteMeasure>. div(other: B ): ConcreteMeasure>> = amount * (units / other)
@JvmName("div10") operator fun ConcreteMeasure>. div(other: UnitsRatio): ConcreteMeasure, UnitsProduct>> = amount * (units / other)
@JvmName("div11") operator fun ConcreteMeasure>. div(other: UnitsRatio>): ConcreteMeasure = amount * (units / other)
@JvmName("div12") operator fun ConcreteMeasure, UnitsProduct>>.div(other: A ): ConcreteMeasure>> = amount * (units / other)
@JvmName("div13") operator fun ConcreteMeasure, UnitsProduct>>.div(other: A ): ConcreteMeasure>> = amount * (units / other)
@JvmName("div14") operator fun ConcreteMeasure, UnitsProduct>>.div(other: A ): ConcreteMeasure