Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement times(Double) and div(Double) #60

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package io.github.kevincianfarini.alchemist.internal

import kotlin.jvm.JvmInline
import kotlin.math.absoluteValue
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import kotlin.math.sign

/**
Expand Down Expand Up @@ -84,6 +86,12 @@ internal value class SaturatingLong(val rawValue: Long) {
return times(other.toLong())
}

inline operator fun times(other: Double): SaturatingLong {
val thisDouble = toDouble()
val result = thisDouble * other
return SaturatingLong(result.roundToLong())
}

operator fun div(other: SaturatingLong): SaturatingLong {
val thisInfinite = isInfinite()
val otherInfinite = other.isInfinite()
Expand Down Expand Up @@ -163,4 +171,4 @@ internal inline val Long.saturated get() = SaturatingLong(this)

// Inline the constants versus using `MIN_VALUE` and `MAX_VALUE` to avoid accessing Long's companion.
internal inline val POSITIVE_INFINITY get() = SaturatingLong(9223372036854775807L)
internal inline val NEGATIVE_INFINITY get() = SaturatingLong(-9223372036854775807L - 1L)
internal inline val NEGATIVE_INFINITY get() = SaturatingLong(-9223372036854775807L - 1L)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.scalar.nmPerSecond
import io.github.kevincianfarini.alchemist.unit.LengthUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import kotlin.text.Typography.nbsp
import kotlin.time.Duration
Expand Down Expand Up @@ -151,6 +152,22 @@ public value class Acceleration internal constructor(
*/
public operator fun times(scale: Long): Acceleration = Acceleration(rawNanometersPerSecondSquared * scale)

/**
* Returns an acceleration whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this acceleration is [infinite][isInfinite] and [scale] is 0.0 or when this acceleration is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Acceleration {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Acceleration(rawNanometersPerSecondSquared * scale)
}
sargunv marked this conversation as resolved.
Show resolved Hide resolved
}

// endregion

// region Acceleration to Scalar Conversions
Expand Down Expand Up @@ -225,4 +242,4 @@ public value class Acceleration internal constructor(
return rawNanometersPerSecondSquared.compareTo(other.rawNanometersPerSecondSquared)
}
// endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.github.kevincianfarini.alchemist.unit.AreaUnit
import io.github.kevincianfarini.alchemist.unit.LengthUnit
import kotlin.jvm.JvmInline
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.roundToLong

/**
Expand Down Expand Up @@ -146,6 +147,22 @@ public value class Area internal constructor(internal val rawMillimetersSquared:
*/
public operator fun times(scale: Long): Area = Area(rawMillimetersSquared * scale)

/**
* Returns an area whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this area is [infinite][isInfinite] and [scale] is 0.0 or when this area is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Area {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Area(rawMillimetersSquared * scale)
}
}

// endregion

// region Area to Scalar Conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import io.github.kevincianfarini.alchemist.scalar.milliwatts
import io.github.kevincianfarini.alchemist.scalar.watts
import io.github.kevincianfarini.alchemist.unit.EnergyUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.time.Duration

/**
Expand Down Expand Up @@ -187,6 +188,22 @@ public value class Energy internal constructor(private val rawMillijoules: Satur
return Energy(rawMillijoules * scale)
}

/**
* Returns an energy whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this energy is [infinite][isInfinite] and [scale] is 0.0 or when this energy is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Energy {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Energy(rawMillijoules * scale)
}
}

// endregion

// region Energy to Scalar Conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.scalar.nmPerSecond2
import io.github.kevincianfarini.alchemist.unit.ForceUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt

/**
* Represents a measure of force and is capable of storing ±9.2 billion newtons at nanonewton precision.
Expand Down Expand Up @@ -137,6 +138,22 @@ public value class Force internal constructor(private val rawNanonewtons: Satura
*/
public operator fun times(scale: Long): Force = Force(rawNanonewtons * scale)

/**
* Returns a force whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this force is [infinite][isInfinite] and [scale] is 0.0 or when this force is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Force {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Force(rawNanonewtons * scale)
}
}

// endregion

// region Force to Scalar Conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.scalar.nanometers
import io.github.kevincianfarini.alchemist.scalar.nmPerSecond
import io.github.kevincianfarini.alchemist.unit.LengthUnit
import io.github.kevincianfarini.alchemist.unit.LengthUnit.International.Nanometer
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import kotlin.time.Duration
import kotlin.time.Duration.Companion.microseconds
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.toDuration

/**
* Represents a measure of length and is capable of storing ±9.2 million kilometers at nanometer precision.
Expand Down Expand Up @@ -291,6 +295,22 @@ public value class Length internal constructor(internal val rawNanometers: Satur
return Length(rawNanometers * scale)
}

/**
* Returns a length whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this length is [infinite][isInfinite] and [scale] is 0.0 or when this length is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Length {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Length(rawNanometers * scale)
}
}

// endregion

// region Length to Scalar Conversions
Expand Down Expand Up @@ -412,7 +432,7 @@ public value class Length internal constructor(internal val rawNanometers: Satur
val largestUnit = LengthUnit.International.entries.asReversed().firstOrNull { unit ->
rawNanometers.absoluteValue / unit.nanometerScale > 0
}
return toString(largestUnit ?: LengthUnit.International.Nanometer, decimals = 2)
return toString(largestUnit ?: Nanometer, decimals = 2)
}

// endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.github.kevincianfarini.alchemist.internal.SaturatingLong
import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.unit.MassUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.text.Typography.nbsp

/**
Expand Down Expand Up @@ -84,6 +85,22 @@ public value class Mass internal constructor(internal val rawMicrograms: Saturat
*/
public operator fun times(scale: Long): Mass = Mass(rawMicrograms * scale)

/**
* Returns a mass whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this mass is [infinite][isInfinite] and [scale] is 0.0 or when this mass is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Mass {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Mass(rawMicrograms * scale)
}
}

// endregion

// region Mass to Scalar Conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.scalar.microwatts
import io.github.kevincianfarini.alchemist.unit.PowerUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.time.Duration

/**
Expand Down Expand Up @@ -127,6 +128,22 @@ public value class Power internal constructor(private val rawMicrowatts: Saturat
*/
public operator fun times(scale: Long): Power = Power(rawMicrowatts * scale)

/**
* Returns a power whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this power is [infinite][isInfinite] and [scale] is 0.0 or when this power is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Power {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Power(rawMicrowatts * scale)
}
}

// endregion

// region Power to Scalar Conversions
Expand Down Expand Up @@ -194,4 +211,4 @@ public value class Power internal constructor(private val rawMicrowatts: Saturat
}

// endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.github.kevincianfarini.alchemist.internal.toDecimalString
import io.github.kevincianfarini.alchemist.unit.TemperatureUnit
import io.github.kevincianfarini.alchemist.unit.convertNanokelvinsToThis
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.math.roundToLong

/**
Expand Down Expand Up @@ -74,6 +75,22 @@ public value class Temperature internal constructor(private val rawNanokelvin: S
*/
public operator fun times(scale: Long): Temperature = Temperature(rawNanokelvin * scale)

/**
* Returns a temperature whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this temperature is [infinite][isInfinite] and [scale] is 0.0 or when this temperature is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Temperature {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Temperature(rawNanokelvin * scale)
}
}

// endregion

// region Temperature to Scalar Conversions
Expand Down Expand Up @@ -155,4 +172,4 @@ public value class Temperature internal constructor(private val rawNanokelvin: S
}

// endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.github.kevincianfarini.alchemist.scalar.nanometers
import io.github.kevincianfarini.alchemist.scalar.nmPerSecond2
import io.github.kevincianfarini.alchemist.unit.LengthUnit
import kotlin.jvm.JvmInline
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import kotlin.text.Typography.nbsp
import kotlin.time.Duration
Expand Down Expand Up @@ -173,6 +174,22 @@ public value class Velocity internal constructor(
*/
public operator fun times(scale: Long): Velocity = Velocity(rawNanometersPerSecond * scale)

/**
* Returns a velocity whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this velocity is [infinite][isInfinite] and [scale] is 0.0 or when this velocity is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Velocity {
val intScale = scale.roundToInt()
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Velocity(rawNanometersPerSecond * scale)
}
}

// endregion

// region Velocity to Scalar Conversions
Expand Down Expand Up @@ -248,4 +265,4 @@ public value class Velocity internal constructor(
override fun compareTo(other: Velocity): Int = rawNanometersPerSecond.compareTo(other.rawNanometersPerSecond)

// endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.github.kevincianfarini.alchemist.unit.LengthUnit
import io.github.kevincianfarini.alchemist.unit.VolumeUnit
import kotlin.jvm.JvmInline
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.roundToLong

/**
Expand Down Expand Up @@ -107,6 +108,22 @@ public value class Volume internal constructor(private val rawCubicCentimeters:
*/
public operator fun times(scale: Long): Volume = Volume(rawCubicCentimeters * scale)

/**
* Returns a volume whose value is multiplied by the specified [scale]. This operation may be rounded when the result
* cannot be precisely represented with a [Double] number.
*
* @throws IllegalArgumentException when this volume is [infinite][isInfinite] and [scale] is 0.0 or when this volume is 0
* and scale is [infinite][Double.isInfinite].
*/
public operator fun times(scale: Double): Volume {
val intScale = scale.roundToInt()
sargunv marked this conversation as resolved.
Show resolved Hide resolved
if (intScale.toDouble() == scale) {
return times(intScale)
} else {
return Volume(rawCubicCentimeters * scale)
}
}

// endregion

// region Volume to Scalar Conversions
Expand Down
Loading