Skip to content

Commit

Permalink
delta quantity unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
erikerlandson committed Apr 7, 2024
1 parent db6f0f8 commit bdcc7df
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 118 deletions.
9 changes: 4 additions & 5 deletions core/src/main/scala/coulomb/conversion/standard/scala.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ object scala:
): Conversion[Quantity[V, UF], Quantity[V, UT]] =
(q: Quantity[V, UF]) => uc(q.value).withUnit[UT]

given ctx_DeltaQuantity_conversion_2V2U[B, VF, UF, VT, UT](using
vc: ValueConversion[VF, VT],
uc: DeltaUnitConversion[VT, B, UF, UT]
): Conversion[DeltaQuantity[VF, UF, B], DeltaQuantity[VT, UT, B]] =
(q: DeltaQuantity[VF, UF, B]) => uc(vc(q.value)).withDeltaUnit[UT, B]
given ctx_DeltaQuantity_conversion_1V2U[B, V, UF, UT](using
uc: DeltaUnitConversion[V, B, UF, UT]
): Conversion[DeltaQuantity[V, UF, B], DeltaQuantity[V, UT, B]] =
(q: DeltaQuantity[V, UF, B]) => uc(q.value).withDeltaUnit[UT, B]

// also support implicit lift of values to unitless quantity
given ctx_Value_to_Unitless[V]: Conversion[V, Quantity[V, 1]] =
Expand Down
92 changes: 48 additions & 44 deletions core/src/main/scala/coulomb/deltaquantity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,7 @@ import coulomb.syntax.*
import coulomb.conversion.*

package syntax {
// this has to be in a separated namespace:
// https://github.com/lampepfl/dotty/issues/15255
extension [V](v: V)
/**
* Lift a raw value into a delta-unit quantity
* @tparam U
* the desired unit type
* @tparam B
* base unit to anchor with
* @return
* a DeltaQuantity with given value and unit type
* {{{
* val date = (1.0).withDeltaUnit[Day, Second]
* }}}
*/
inline def withDeltaUnit[U, B]: DeltaQuantity[V, U, B] =
DeltaQuantity[U, B](v)
export coulomb.DeltaQuantity.withDeltaUnit
}

/**
Expand Down Expand Up @@ -76,7 +60,22 @@ object DeltaQuantity:
class Applier[U, B]:
def apply[V](v: V): DeltaQuantity[V, U, B] = v
object Applier:
given [U, B]: Applier[U, B] = new Applier[U, B]
given g_Applier[U, B]: Applier[U, B] = new Applier[U, B]

extension [V](v: V)
/**
* Lift a raw value into a delta-unit quantity
* @tparam U
* the desired unit type
* @tparam B
* base unit to anchor with
* @return
* a DeltaQuantity with given value and unit type
* {{{
* val date = (1.0).withDeltaUnit[Day, Second]
* }}}
*/
inline def withDeltaUnit[U, B]: DeltaQuantity[V, U, B] = v

extension [VL, UL, B](ql: DeltaQuantity[VL, UL, B])
/**
Expand Down Expand Up @@ -127,10 +126,8 @@ object DeltaQuantity:
* t.toValue[Float] // => Temperature[Float, Celsius](37.0)
* }}}
*/
inline def toValue[V](using
conv: ValueConversion[VL, V]
): DeltaQuantity[V, UL, B] =
conv(ql.value).withDeltaUnit[UL, B]
inline def toValue[V]: DeltaQuantity[V, UL, B] =
ValueConversion[VL, V](ql)

/**
* convert a delta-quantity to a new unit type
Expand All @@ -147,10 +144,8 @@ object DeltaQuantity:
* t.toUnit[Fahrenheit] // => Temperature[Double, Fahrenheit](98.6)
* }}}
*/
inline def toUnit[U](using
conv: DeltaUnitConversion[VL, B, UL, U]
): DeltaQuantity[VL, U, B] =
conv(ql.value).withDeltaUnit[U, B]
inline def toUnit[U]: DeltaQuantity[VL, U, B] =
DeltaUnitConversion[VL, B, UL, U](ql)

/**
* subtract another delta-quantity from this one
Expand All @@ -168,10 +163,11 @@ object DeltaQuantity:
* result may depend on what algebras, policies, and other typeclasses
* are in scope
*/
inline def -(qr: DeltaQuantity[VL, UL, B])(using
inline def -[UR](qr: DeltaQuantity[VL, UR, B])(using
alg: AdditiveGroup[VL]
): Quantity[VL, UL] =
alg.minus(ql.value, qr.value).withUnit[UL]
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
alg.minus(ql, qrv).withUnit[UL]

/**
* subtract quantity from this delta-quantity
Expand All @@ -192,10 +188,11 @@ object DeltaQuantity:
// work around a weird type erasure problem,
// spcifically with '-' operator overloadings
@scala.annotation.targetName("dqMinusQ")
inline def -(qr: Quantity[VL, UL])(using
inline def -[UR](qr: Quantity[VL, UR])(using
alg: AdditiveGroup[VL]
): DeltaQuantity[VL, UL, B] =
alg.minus(ql.value, qr.value).withDeltaUnit[UL, B]
val qrv: VL = ops.alignU[VL, UR, UL](qr.value)
alg.minus(ql, qrv)

/**
* add a quantity to this delta-quantity
Expand All @@ -210,10 +207,11 @@ object DeltaQuantity:
* t1 + q // => EpochTime[Double, Day](21.0)
* }}}
*/
inline def +(qr: Quantity[VL, UL])(using
inline def +[UR](qr: Quantity[VL, UR])(using
alg: AdditiveSemigroup[VL]
): DeltaQuantity[VL, UL, B] =
alg.plus(ql.value, qr.value).withDeltaUnit[UL, B]
val qrv: VL = ops.alignU[VL, UR, UL](qr.value)
alg.plus(ql, qrv)

/**
* test this delta-quantity for equality with another
Expand All @@ -228,10 +226,11 @@ object DeltaQuantity:
* t1 === t2 // => true
* }}}
*/
inline def ===(qr: DeltaQuantity[VL, UL, B])(using
inline def ===[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) == 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) == 0

/**
* test this delta-quantity for inequality with another
Expand All @@ -246,10 +245,11 @@ object DeltaQuantity:
* t1 =!= t2 // => false
* }}}
*/
inline def =!=(qr: DeltaQuantity[VL, UL, B])(using
inline def =!=[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) != 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) != 0

/**
* test if this delta-quantity is less than another
Expand All @@ -265,10 +265,11 @@ object DeltaQuantity:
* t1 < t2 // => true
* }}}
*/
inline def <(qr: DeltaQuantity[VL, UL, B])(using
inline def <[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) < 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) < 0

/**
* test if this delta-quantity is less than or equal to than another
Expand All @@ -284,17 +285,20 @@ object DeltaQuantity:
* t1 <= t2 // => true
* }}}
*/
inline def <=(qr: DeltaQuantity[VL, UL, B])(using
inline def <=[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) <= 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) <= 0

inline def >(qr: DeltaQuantity[VL, UL, B])(using
inline def >[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) > 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) > 0

inline def >=(qr: DeltaQuantity[VL, UL, B])(using
inline def >=[UR](qr: DeltaQuantity[VL, UR, B])(using
ord: Order[VL]
): Boolean =
ord.compare(ql.value, qr.value) >= 0
val qrv: VL = ops.alignDU[VL, B, UR, UL](qr)
ord.compare(ql, qrv) >= 0
2 changes: 1 addition & 1 deletion core/src/main/scala/coulomb/policy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ package coulomb.policy
* }}}
*/
object standard:
export coulomb.conversion.standard.scala.given
//export coulomb.conversion.standard.scala.given
export coulomb.cats.all.given
export coulomb.conversion.ops.policy.given

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/coulomb/quantity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ object Quantity:
final class Applier[U]:
def apply[V](v: V): Quantity[V, U] = v
object Applier:
given ctx_Applier[U]: Applier[U] = new Applier[U]
given g_Applier[U]: Applier[U] = new Applier[U]

extension [V](v: V)
/**
Expand Down
80 changes: 13 additions & 67 deletions core/src/test/scala/coulomb/deltaquantity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class DeltaQuantitySuite extends CoulombSuite:
assertEquals(1.withDeltaUnit[Second, Second].showFull, "1 second")
}

/*
test("toValue") {
import coulomb.policy.strict.given

Expand Down Expand Up @@ -85,41 +84,19 @@ class DeltaQuantitySuite extends CoulombSuite:
.toValue[Double]
.assertDQ[Double, Celsius](100)

assertCE("100f.withDeltaUnit[Celsius, Kelvin].toValue[Int]")
assertCE("100f.withDeltaUnit[Celsius, Kelvin].toValue[Long]")
100f.withDeltaUnit[Celsius, Kelvin]
.toValue[Float]
.assertDQ[Float, Celsius](100)
100f.withDeltaUnit[Celsius, Kelvin]
.toValue[Double]
.assertDQ[Double, Celsius](100)

assertCE("100d.withDeltaUnit[Celsius, Kelvin].toValue[Int]")
assertCE("100d.withDeltaUnit[Celsius, Kelvin].toValue[Long]")
100d.withDeltaUnit[Celsius, Kelvin]
.toValue[Float]
.assertDQ[Float, Celsius](100)
100d.withDeltaUnit[Celsius, Kelvin]
.toValue[Double]
.assertDQ[Double, Celsius](100)
1.999f
.withDeltaUnit[Minute, Second]
.tToValue[Int]
.assertDQ[Int, Minute](1)
0.999f
.withDeltaUnit[Minute, Second]
.tToValue[Long]
.assertDQ[Long, Minute](0)
1.999d
.withDeltaUnit[Minute, Second]
.tToValue[Int]
.assertDQ[Int, Minute](1)
0.999d
.withDeltaUnit[Minute, Second]
.tToValue[Long]
.assertDQ[Long, Minute](0)
}

test("toUnit") {
Expand All @@ -134,13 +111,6 @@ class DeltaQuantitySuite extends CoulombSuite:

assertCE("37L.withDeltaUnit[Celsius, Kelvin].toUnit[Fahrenheit]")
assertCE("37.withDeltaUnit[Celsius, Kelvin].toUnit[Fahrenheit]")
37L.withDeltaUnit[Celsius, Kelvin]
.tToUnit[Fahrenheit]
.assertDQ[Long, Fahrenheit](98)
37.withDeltaUnit[Celsius, Kelvin]
.tToUnit[Fahrenheit]
.assertDQ[Int, Fahrenheit](98)
}

test("subtraction strict") {
Expand All @@ -161,24 +131,17 @@ class DeltaQuantitySuite extends CoulombSuite:
test("subtraction standard") {
import coulomb.policy.standard.given

// 2V1U
(100d.withDeltaUnit[Celsius, Kelvin] - 50f
(100d.withDeltaUnit[Celsius, Kelvin] - 50d
.withDeltaUnit[Celsius, Kelvin])
.assertQ[Double, Celsius](50)
// 1V2U
(100d.withDeltaUnit[Celsius, Kelvin] - 122d
(100f.withDeltaUnit[Celsius, Kelvin] - 122f
.withDeltaUnit[Fahrenheit, Kelvin])
.assertQD[Double, Celsius](50)
// 2V2U
(100f.withDeltaUnit[Celsius, Kelvin] - 122d
.withDeltaUnit[Fahrenheit, Kelvin])
.assertQD[Double, Celsius](50)
.assertQD[Float, Celsius](50)
}

test("quantity subtraction strict") {
import coulomb.policy.strict.given

// 1V1U
(100d.withDeltaUnit[Celsius, Kelvin] - 50d.withUnit[Celsius])
.assertDQ[Double, Celsius](50)
(10f.withDeltaUnit[Minute, Second] - 5f.withUnit[Minute])
Expand All @@ -192,15 +155,10 @@ class DeltaQuantitySuite extends CoulombSuite:
test("quantity subtraction standard") {
import coulomb.policy.standard.given

// 2V1U
(100d.withDeltaUnit[Celsius, Kelvin] - 50f.withUnit[Celsius])
(100d.withDeltaUnit[Celsius, Kelvin] - 50d.withUnit[Celsius])
.assertDQ[Double, Celsius](50)
// 1V2U
(100d.withDeltaUnit[Celsius, Kelvin] - 90d.withUnit[Fahrenheit])
.assertDQD[Double, Celsius](50)
// 2V2U
(100f.withDeltaUnit[Celsius, Kelvin] - 90d.withUnit[Fahrenheit])
.assertDQD[Double, Celsius](50)
(100f.withDeltaUnit[Celsius, Kelvin] - 90f.withUnit[Fahrenheit])
.assertDQD[Float, Celsius](50)
}

test("quantity addition strict") {
Expand All @@ -220,15 +178,10 @@ class DeltaQuantitySuite extends CoulombSuite:
test("quantity addition standard") {
import coulomb.policy.standard.given

// 2V1U
(100d.withDeltaUnit[Celsius, Kelvin] + 50f.withUnit[Celsius])
(100d.withDeltaUnit[Celsius, Kelvin] + 50d.withUnit[Celsius])
.assertDQ[Double, Celsius](150)
// 1V2U
(100d.withDeltaUnit[Celsius, Kelvin] + 90d.withUnit[Fahrenheit])
.assertDQD[Double, Celsius](150)
// 2V2U
(100f.withDeltaUnit[Celsius, Kelvin] + 90d.withUnit[Fahrenheit])
.assertDQD[Double, Celsius](150)
(100f.withDeltaUnit[Celsius, Kelvin] + 90f.withUnit[Fahrenheit])
.assertDQD[Float, Celsius](150)
}

test("less-than strict") {
Expand All @@ -255,28 +208,22 @@ class DeltaQuantitySuite extends CoulombSuite:
test("less-than standard") {
import coulomb.policy.standard.given

// 1V2U
/*
assertEquals(
36d.withDeltaUnit[Celsius, Kelvin] < 98.6d
.withDeltaUnit[Fahrenheit, Kelvin],
true
)
// 2V1U
*/
assertEquals(
36f.withDeltaUnit[Celsius, Kelvin] < 36d
36f.withDeltaUnit[Celsius, Kelvin] < 36f
.withDeltaUnit[Celsius, Kelvin],
false
)
// 2V2U
assertEquals(
38d.withDeltaUnit[Celsius, Kelvin] < 98.6f
.withDeltaUnit[Fahrenheit, Kelvin],
false
)
}

test("cats Eq, Ord, Hash") {
import cats.kernel.{Eq, Hash, Order}
import _root_.cats.kernel.{Eq, Hash, Order}
import coulomb.policy.strict.given

val q1 = 1.withDeltaUnit[Meter, Meter]
Expand All @@ -296,4 +243,3 @@ class DeltaQuantitySuite extends CoulombSuite:
assertEquals(hash.hash(q1), hash.hash(q2))
assertNotEquals(hash.hash(q1), hash.hash(q3))
}
*/

0 comments on commit bdcc7df

Please sign in to comment.