From 2acbf516372a467e355d2bd5b2c86e4d28efcb1f Mon Sep 17 00:00:00 2001 From: Zachary Levy Date: Wed, 17 Jun 2026 17:45:02 +0000 Subject: [PATCH] Added gallons and gallons per minute (#35) Co-authored-by: Zachary Levy Reviewed-on: https://git.bfpower.io/BFPOWER/levlib/pulls/35 --- quantity/volume.odin | 62 ++++++++++++++++++++++++++++++++------- quantity/volume_rate.odin | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 10 deletions(-) diff --git a/quantity/volume.odin b/quantity/volume.odin index de01d2a..62873be 100644 --- a/quantity/volume.odin +++ b/quantity/volume.odin @@ -2,6 +2,8 @@ package quantity import "base:intrinsics" +LITERS_PER_GALLON :: 3.785411784 + //----- Liters ---------------------------------- Liters :: struct($V: typeid) where intrinsics.type_is_numeric(V) { v: V, @@ -9,9 +11,16 @@ Liters :: struct($V: typeid) where intrinsics.type_is_numeric(V) { @(private = "file") liters_to_milli_liters :: #force_inline proc "contextless" ( - liters: Liters($V), + liters: Liters($V), ) -> Milli_Liters(V) where intrinsics.type_is_numeric(V) { - return Milli_Liters(V){liters.v * MILLI} + return Milli_Liters(V){liters.v * MILLI} +} + +@(private = "file") +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} } //----- Milliliters ---------------------------------- @@ -26,15 +35,32 @@ milli_liters_to_liters :: #force_inline proc "contextless" ( return Liters(V){milli_liters.v / MILLI} } +//----- Gallons ---------------------------------- +Gallons :: struct($V: typeid) where intrinsics.type_is_numeric(V) { + v: V, +} + +@(private = "file") +gallons_to_liters :: #force_inline proc "contextless" ( + gallons: Gallons($V), +) -> Liters(V) where intrinsics.type_is_float(V) { + return Liters(V){gallons.v * LITERS_PER_GALLON} +} + // --------------------------------------------------------------------------------------------------------------------- // ----- Conversion Overloads ------------------------ // --------------------------------------------------------------------------------------------------------------------- to_liters :: proc { - milli_liters_to_liters, + milli_liters_to_liters, + gallons_to_liters, } to_milli_liters :: proc { - liters_to_milli_liters, + liters_to_milli_liters, +} + +to_gallons :: proc { + liters_to_gallons, } // --------------------------------------------------------------------------------------------------------------------- @@ -44,16 +70,32 @@ import "core:testing" @(test) test_liters_to_milli_liters :: proc(t: ^testing.T) { - liters := Liters(int){12} - milli_liters := to_milli_liters(liters) + liters := Liters(int){12} + milli_liters := to_milli_liters(liters) - testing.expect_value(t, milli_liters, Milli_Liters(int){12_000}) + testing.expect_value(t, milli_liters, Milli_Liters(int){12_000}) } @(test) test_milli_liters_to_liters :: proc(t: ^testing.T) { - milli_liters := Milli_Liters(int){12_000} - liters := to_liters(milli_liters) + milli_liters := Milli_Liters(int){12_000} + liters := to_liters(milli_liters) - testing.expect_value(t, liters, Liters(int){12}) + testing.expect_value(t, liters, Liters(int){12}) +} + +@(test) +test_gallons_to_liters :: proc(t: ^testing.T) { + gallons := Gallons(f32){1} + liters := to_liters(gallons) + + testing.expect(t, liters.v > 3.78 && liters.v < 3.79) +} + +@(test) +test_liters_to_gallons :: proc(t: ^testing.T) { + liters := Liters(f32){3.785411784} + gallons := to_gallons(liters) + + testing.expect(t, gallons.v > 0.99 && gallons.v < 1.01) } diff --git a/quantity/volume_rate.odin b/quantity/volume_rate.odin index 89de0fb..f5ed50b 100644 --- a/quantity/volume_rate.odin +++ b/quantity/volume_rate.odin @@ -2,6 +2,58 @@ package quantity import "base:intrinsics" +//----- Liters Per Minute ---------------------------------- Liters_Per_Minute :: struct($V: typeid) where intrinsics.type_is_numeric(V) { v: V, } + +@(private = "file") +liters_per_minute_to_gallons_per_minute :: #force_inline proc "contextless" ( + liters_per_minute: Liters_Per_Minute($V), +) -> Gallons_Per_Minute(V) where intrinsics.type_is_float(V) { + return Gallons_Per_Minute(V){liters_per_minute.v / LITERS_PER_GALLON} +} + +//----- Gallons Per Minute ---------------------------------- +Gallons_Per_Minute :: struct($V: typeid) where intrinsics.type_is_numeric(V) { + v: V, +} + +@(private = "file") +gallons_per_minute_to_liters_per_minute :: #force_inline proc "contextless" ( + gallons_per_minute: Gallons_Per_Minute($V), +) -> Liters_Per_Minute(V) where intrinsics.type_is_float(V) { + return Liters_Per_Minute(V){gallons_per_minute.v * LITERS_PER_GALLON} +} + +// --------------------------------------------------------------------------------------------------------------------- +// ----- Conversion Overloads ------------------------ +// --------------------------------------------------------------------------------------------------------------------- +to_liters_per_minute :: proc { + gallons_per_minute_to_liters_per_minute, +} + +to_gallons_per_minute :: proc { + liters_per_minute_to_gallons_per_minute, +} + +// --------------------------------------------------------------------------------------------------------------------- +// ----- Tests ------------------------ +// --------------------------------------------------------------------------------------------------------------------- +import "core:testing" + +@(test) +test_gallons_per_minute_to_liters_per_minute :: proc(t: ^testing.T) { + gallons_per_minute := Gallons_Per_Minute(f32){1} + liters_per_minute := to_liters_per_minute(gallons_per_minute) + + testing.expect(t, liters_per_minute.v > 3.78 && liters_per_minute.v < 3.79) +} + +@(test) +test_liters_per_minute_to_gallons_per_minute :: proc(t: ^testing.T) { + liters_per_minute := Liters_Per_Minute(f32){3.785411784} + gallons_per_minute := to_gallons_per_minute(liters_per_minute) + + testing.expect(t, gallons_per_minute.v > 0.99 && gallons_per_minute.v < 1.01) +}