Skip to content

Instantly share code, notes, and snippets.

@LouisCAD
Created September 14, 2021 10:25
Show Gist options
  • Save LouisCAD/946f2261682ca09ed081fd1e2accbdd9 to your computer and use it in GitHub Desktop.
Save LouisCAD/946f2261682ca09ed081fd1e2accbdd9 to your computer and use it in GitHub Desktop.
A partial double precision floating point based implementation of the Système International of Units.
@file:Suppress("experimental_is_not_enabled")
@file:OptIn(ExperimentalTime::class)
import kotlin.math.sqrt
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime
//// Metrics
@JvmInline
value class Distance(val meters: Double) {
operator fun plus(other: Distance): Distance {
return Distance(meters = meters + other.meters)
}
@ExperimentalTime
operator fun div(time: Duration): Speed {
val seconds = time.toDouble(DurationUnit.SECONDS)
return Speed(metersPerSecond = meters / seconds)
}
companion object {
fun meters(value: Double): Distance = Distance(meters = value)
}
}
@JvmInline
value class Speed(val metersPerSecond: Double) {
@ExperimentalTime
operator fun div(time: Duration): Acceleration {
val seconds = time.toDouble(DurationUnit.SECONDS)
return Acceleration(metersPerSecondPerSecond = metersPerSecond / seconds)
}
@ExperimentalTime
operator fun times(time: Duration): Distance {
val seconds = time.toDouble(DurationUnit.SECONDS)
return Distance(meters = metersPerSecond * seconds)
}
@ExperimentalTime
operator fun div(acceleration: Acceleration): Duration {
return Duration.seconds(metersPerSecond / acceleration.metersPerSecondPerSecond)
}
companion object {
val None = Speed(metersPerSecond = 0.0)
fun metersPerSecond(value: Double): Speed {
return Speed(metersPerSecond = value)
}
}
}
@JvmInline
value class Acceleration(val metersPerSecondPerSecond: Double) {
@ExperimentalTime
operator fun times(time: Duration): Speed {
val seconds = time.toDouble(DurationUnit.SECONDS)
return Speed(metersPerSecond = metersPerSecondPerSecond * seconds)
}
companion object {
val GravityEarth = metersPerSecondPerSecond(9.80665)
fun metersPerSecondPerSecond(value: Double): Acceleration {
return Acceleration(metersPerSecondPerSecond = value)
}
}
}
//// Operators
operator fun Double.times(acceleration: Acceleration): Acceleration {
return Acceleration(
metersPerSecondPerSecond = acceleration.metersPerSecondPerSecond * this
)
}
//// Formulas
@ExperimentalTime
fun distanceTravelled(
initialVelocity: Speed,
acceleration: Acceleration,
time: Duration
): Distance {
return initialVelocity * time + (1.0 / 2.0) * acceleration * time * time
}
@ExperimentalTime
fun timeToTravel(
initialVelocity: Speed,
acceleration: Acceleration,
distance: Distance
): Duration {
val a = acceleration.metersPerSecondPerSecond
val d = distance.meters
val vi = initialVelocity.metersPerSecond
return Duration.seconds((sqrt((2.0 * a * d + vi * vi)) - vi) / a)
}
@ExperimentalTime
fun timeToFallOnEarth(distance: Distance): Duration {
return timeToTravel(
initialVelocity = Speed.None,
acceleration = Acceleration.GravityEarth,
distance = distance
)
}
//// Tests
@OptIn(ExperimentalTime::class)
println(Speed(metersPerSecond = 100.0) * Duration.seconds(2))
@OptIn(ExperimentalTime::class)
val distance = distanceTravelled(
initialVelocity = Speed.None,
acceleration = Acceleration.GravityEarth,
time = Duration.milliseconds(770)
)
println(distance)
@OptIn(ExperimentalTime::class)
val time = timeToTravel(
initialVelocity = Speed.None,
acceleration = Acceleration.GravityEarth,
distance = distance
).inWholeMilliseconds
println(time)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment