diff --git a/quantity/volume.odin b/quantity/volume.odin index 62873be..2cc2f2a 100644 --- a/quantity/volume.odin +++ b/quantity/volume.odin @@ -3,6 +3,7 @@ package quantity import "base:intrinsics" LITERS_PER_GALLON :: 3.785411784 +MICRO_LITERS_PER_GALLON :: 473176473.0 / 125.0 //----- Liters ---------------------------------- Liters :: struct($V: typeid) where intrinsics.type_is_numeric(V) { @@ -16,25 +17,65 @@ liters_to_milli_liters :: #force_inline proc "contextless" ( return Milli_Liters(V){liters.v * MILLI} } -@(private = "file") +@(private = "file", fast_math = {.Allow_Reciprocal}) liters_to_gallons :: #force_inline proc "contextless" ( liters: Liters($V), ) -> Gallons(V) where intrinsics.type_is_float(V) { return Gallons(V){liters.v / LITERS_PER_GALLON} } +@(private = "file") +liters_to_micro_liters :: #force_inline proc "contextless" ( + liters: Liters($V), +) -> Micro_Liters(V) where intrinsics.type_is_numeric(V) { + return Micro_Liters(V){liters.v * MICRO} +} + //----- Milliliters ---------------------------------- Milli_Liters :: struct($V: typeid) where intrinsics.type_is_numeric(V) { v: V, } -@(private = "file") +@(private = "file", fast_math = {.Allow_Reciprocal}) milli_liters_to_liters :: #force_inline proc "contextless" ( milli_liters: Milli_Liters($V), ) -> Liters(V) where intrinsics.type_is_numeric(V) { return Liters(V){milli_liters.v / MILLI} } +@(private = "file") +milli_liters_to_micro_liters :: #force_inline proc "contextless" ( + milli_liters: Milli_Liters($V), +) -> Micro_Liters(V) where intrinsics.type_is_numeric(V) { + return Micro_Liters(V){milli_liters.v * (MICRO / MILLI)} +} + +//----- Microliters ---------------------------------- +Micro_Liters :: struct($V: typeid) where intrinsics.type_is_numeric(V) { + v: V, +} + +@(private = "file", fast_math = {.Allow_Reciprocal}) +micro_liters_to_liters :: #force_inline proc "contextless" ( + micro_liters: Micro_Liters($V), +) -> Liters(V) where intrinsics.type_is_numeric(V) { + return Liters(V){micro_liters.v / MICRO} +} + +@(private = "file", fast_math = {.Allow_Reciprocal}) +micro_liters_to_milli_liters :: #force_inline proc "contextless" ( + micro_liters: Micro_Liters($V), +) -> Milli_Liters(V) where intrinsics.type_is_numeric(V) { + return Milli_Liters(V){micro_liters.v / (MICRO / MILLI)} +} + +@(private = "file", fast_math = {.Allow_Reciprocal}) +micro_liters_to_gallons :: #force_inline proc "contextless" ( + micro_liters: Micro_Liters($V), +) -> Gallons(V) where intrinsics.type_is_float(V) { + return Gallons(V){micro_liters.v / MICRO_LITERS_PER_GALLON} +} + //----- Gallons ---------------------------------- Gallons :: struct($V: typeid) where intrinsics.type_is_numeric(V) { v: V, @@ -47,20 +88,36 @@ gallons_to_liters :: #force_inline proc "contextless" ( return Liters(V){gallons.v * LITERS_PER_GALLON} } +@(private = "file") +gallons_to_micro_liters :: #force_inline proc "contextless" ( + gallons: Gallons($V), +) -> Micro_Liters(V) where intrinsics.type_is_float(V) { + return Micro_Liters(V){gallons.v * MICRO_LITERS_PER_GALLON} +} + // --------------------------------------------------------------------------------------------------------------------- // ----- Conversion Overloads ------------------------ // --------------------------------------------------------------------------------------------------------------------- to_liters :: proc { milli_liters_to_liters, + micro_liters_to_liters, gallons_to_liters, } to_milli_liters :: proc { liters_to_milli_liters, + micro_liters_to_milli_liters, +} + +to_micro_liters :: proc { + liters_to_micro_liters, + milli_liters_to_micro_liters, + gallons_to_micro_liters, } to_gallons :: proc { liters_to_gallons, + micro_liters_to_gallons, } // --------------------------------------------------------------------------------------------------------------------- @@ -99,3 +156,51 @@ test_liters_to_gallons :: proc(t: ^testing.T) { testing.expect(t, gallons.v > 0.99 && gallons.v < 1.01) } + +@(test) +test_liters_to_micro_liters :: proc(t: ^testing.T) { + liters := Liters(int){12} + micro_liters := to_micro_liters(liters) + + testing.expect_value(t, micro_liters, Micro_Liters(int){12_000_000}) +} + +@(test) +test_micro_liters_to_liters :: proc(t: ^testing.T) { + micro_liters := Micro_Liters(int){12_000_000} + liters := to_liters(micro_liters) + + testing.expect_value(t, liters, Liters(int){12}) +} + +@(test) +test_milli_liters_to_micro_liters :: proc(t: ^testing.T) { + milli_liters := Milli_Liters(int){5} + micro_liters := to_micro_liters(milli_liters) + + testing.expect_value(t, micro_liters, Micro_Liters(int){5_000}) +} + +@(test) +test_micro_liters_to_milli_liters :: proc(t: ^testing.T) { + micro_liters := Micro_Liters(int){5_000} + milli_liters := to_milli_liters(micro_liters) + + testing.expect_value(t, milli_liters, Milli_Liters(int){5}) +} + +@(test) +test_gallons_to_micro_liters :: proc(t: ^testing.T) { + gallons := Gallons(f64){1} + micro_liters := to_micro_liters(gallons) + + testing.expect(t, micro_liters.v > 3_785_411.783 && micro_liters.v < 3_785_411.785) +} + +@(test) +test_micro_liters_to_gallons :: proc(t: ^testing.T) { + micro_liters := Micro_Liters(f64){3_785_411.784} + gallons := to_gallons(micro_liters) + + testing.expect(t, gallons.v > 0.9999999 && gallons.v < 1.0000001) +}