Table of Contents

Benefits Setup Usage

100% Customizable

units-of-measure takes a novel, metaprogramming approach to the problem of type-safe dimensional analysis. Because the DSL is auto-generated, units-of-measure works great for all engineering and scientific applications.

With just the tweak of a config file, units-of-measure can represent any unit or quantity.

Type-safe Math Library

For even greater safety and ease of use, units-of-measure ships with a type-safe superset of the kotlin.math library.
This means, for example, that units-of-measure can track units & dimensions even across complex trigonometric expressions.

Lets write a function that uses the law of cosines to solve for m∠C.

fun lawOfCosines(a: Length, b: Length, c: Length): Angle {
    val asq = a * a // `L²` type
    val bsq = b * b
    val csq = c * c

    return acos(
            (asq + bsq - csq) / (a * b * 2) // Dimensionless type
    ) // `∠` type
}

Strong Support for Generic Programming

units-of-measure allows you to define relationships between quantities at the type level. All you have to do is pass a “proof” (::p).

Technical Note: “Proof passing” is a novel technique which leverages Kotlin’s type inference and method overloading capabilities. It allows dimensional relationships to be used as bounds for UOM type parameters.

This means, for example, that we can write generic integration, differentiation, & stdev utilities.

Generic Integrator

fun <Q, SQDT> integrator(
        p: (Q, times, Time) -> SQDT,
        x1: Time, y1: Q
): (Time, Q) -> SQDT

        where SQDT : Quan<SQDT>,
              Q : Quan<Q> {
    ...
}
val i = integrator(::p, 0.Second, 0.Foot / Second)
var position = i(1.Second, 1.Foot / Second)
position = i(2.Second, 4.Foot / Second)
position = i(4.Second, 4.Foot / Second)
position = i(5.Second, 1.Foot / Second)

view complete implementation

Generic Differentiator

fun <Q, DQDT> differentiator(
        p: (Q, div, T) -> DQDT,
        x1: Time, y1: Q
): (Time, Q) -> DQDT

        where Q : Quan<Q>,
              DQDT : Quan<DQDT> {
    ...
}
val d = differentiator(::p, 0.Second, 0.Foot)
var velocity = d(2.Second, 3.Foot)
velocity = d(5.Second, 9.Foot)
velocity = d(9.Second, 21.Foot)
velocity = d(14.Second, 36.Foot)

view complete implementation

Generic Standard Deviation Calculator

fun <Q, Q2> stdev(
        p: (Q, times, Q) -> Q2,
        init: Q
): (Q) -> Q

        where Q : Quan<Q>,
              Q2 : Quan<Q2> {
    ...
}
val s = stdev(::p, 0.Mole / Litre)
var stdev = s(0.20.Mole / Litre)
stdev = s(0.17.Mole / Litre)
stdev = s(0.22.Mole / Litre)
stdev = s(0.19.Mole / Litre)

view complete implementation


‹ Benefit: Cleaner Code Install ›