From 9d847c51a440579ee4012bc106bb277598c5c57d Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Sun, 2 Mar 2025 15:07:34 -0500 Subject: [PATCH 1/9] Template for the Unit.hpp Implemented the Unit.hpp and then add the base in the Real.hpp/Real.cpp Added a function ConvertTo for the future when we have to convert between Units Signed-off-by: Jary Chen --- include/Oasis/Real.hpp | 7 ++++++- include/Oasis/Unit.hpp | 20 ++++++++++++++++++++ src/Real.cpp | 19 +++++++++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 include/Oasis/Unit.hpp diff --git a/include/Oasis/Real.hpp b/include/Oasis/Real.hpp index be8e3e36..f06e6b3a 100644 --- a/include/Oasis/Real.hpp +++ b/include/Oasis/Real.hpp @@ -6,6 +6,7 @@ #define OASIS_REAL_HPP #include "LeafExpression.hpp" +#include "Unit.hpp" namespace Oasis { @@ -17,19 +18,22 @@ class Real : public LeafExpression { Real() = default; Real(const Real& other) = default; - explicit Real(double value); + explicit Real(double value, Unit unit = Unit::None); [[nodiscard]] auto Equals(const Expression& other) const -> bool final; EXPRESSION_TYPE(Real) EXPRESSION_CATEGORY(UnExp) + auto ConvertTo(Unit TargetUnit) const -> Real; /** * Gets the value of the real number. * @return The value of the real number. */ [[nodiscard]] auto GetValue() const -> double; + [[nodiscard]] auto GetUnit() const -> Unit; + [[nodiscard]] auto Integrate(const Expression& integrationVariable) const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression&) const -> std::unique_ptr final; @@ -38,6 +42,7 @@ class Real : public LeafExpression { private: double value {}; + Unit unit = Unit::None; }; } // Oasis diff --git a/include/Oasis/Unit.hpp b/include/Oasis/Unit.hpp new file mode 100644 index 00000000..98f3a8bf --- /dev/null +++ b/include/Oasis/Unit.hpp @@ -0,0 +1,20 @@ +// Unit.hpp +#ifndef OASIS_UNIT_HPP +#define OASIS_UNIT_HPP + +namespace Oasis { + +enum class Unit { + None, + Meter, + Kilogram, + Second, + Ampere, + Kelvin, + Mole, + Candela +}; + +} // Oasis + +#endif // OASIS_UNIT_HPP diff --git a/src/Real.cpp b/src/Real.cpp index 8eff8f56..57de8455 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -13,8 +13,8 @@ namespace Oasis { -Real::Real(double value) - : value(value) +Real::Real(double value, Unit unit) + : value(value), unit(unit) { } @@ -28,11 +28,26 @@ auto Real::Equals(const Expression& other) const -> bool return other.Is() && value == dynamic_cast(other).value; } +auto Real::ConvertTo(Unit TargetUnit) const -> Real +{ //template of the ConvertTo AS OF NOW + if (TargetUnit == unit) { + return *this; + } + + double factor = 1.00; + return Real(value * factor, TargetUnit); +} + auto Real::GetValue() const -> double { return value; } +auto Real::GetUnit() const -> Unit +{ + return unit; +} + auto Real::Integrate(const Expression& integrationVariable) const -> std::unique_ptr { if (auto variable = RecursiveCast(integrationVariable); variable != nullptr) { From dd4ba7389f002aaeaabb59e468bf0cb070dcb3a4 Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Sun, 2 Mar 2025 15:32:33 -0500 Subject: [PATCH 2/9] Unit.hpp base in Variable Implemented the Unit.hpp and then add the base in the Variable.hpp/Variable.cpp Signed-off-by: Jary Chen --- include/Oasis/Variable.hpp | 6 +++++- src/Variable.cpp | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/Oasis/Variable.hpp b/include/Oasis/Variable.hpp index 580268ae..b43f2ccf 100644 --- a/include/Oasis/Variable.hpp +++ b/include/Oasis/Variable.hpp @@ -9,6 +9,7 @@ #include #include "LeafExpression.hpp" +#include "Unit.hpp" namespace Oasis { @@ -23,7 +24,7 @@ class Variable : public LeafExpression { Variable() = default; Variable(const Variable& other) = default; - explicit Variable(std::string name); + explicit Variable(std::string name, Unit unit = Unit::None); [[nodiscard]] virtual auto Equals(const Expression& other) const -> bool final; @@ -37,6 +38,8 @@ class Variable : public LeafExpression { */ [[nodiscard]] auto GetName() const -> std::string; + [[nodiscard]] auto GetUnit() const -> Unit; + [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; [[nodiscard]] auto Integrate(const Expression& integrationVariable) const -> std::unique_ptr final; @@ -47,6 +50,7 @@ class Variable : public LeafExpression { private: std::string name {}; + Unit unit = Unit::None; }; } // Oasis diff --git a/src/Variable.cpp b/src/Variable.cpp index b68981ab..49ae6a6c 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -13,8 +13,8 @@ namespace Oasis { -Variable::Variable(std::string name) - : name(std::move(name)) +Variable::Variable(std::string name, Unit unit) + : name(std::move(name)), unit(unit) { } @@ -28,6 +28,11 @@ auto Variable::GetName() const -> std::string return name; } +auto Variable::GetUnit() const -> Unit +{ + return unit; +} + auto Variable::Integrate(const Expression& integrationVariable) const -> std::unique_ptr { if (auto variable = RecursiveCast(integrationVariable); variable != nullptr) { From 70167e19fd29f0d70b0217e81b42f076ab9b3e1a Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Sun, 2 Mar 2025 18:34:47 -0500 Subject: [PATCH 3/9] Introduction of Boost Installed boost and introduced boost into Real.cpp. Basic Implementation of ConvertTo function and added a private GetFactor function. Still needs unit testing for this! Signed-off-by: Jary Chen --- include/CMakeLists.txt | 6 +++++- include/Oasis/Real.hpp | 11 ++++++++++- src/Real.cpp | 26 ++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index c36fb2e4..2c155783 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -33,6 +33,10 @@ add_library(Oasis::Headers ALIAS OasisHeaders) target_compile_features(OasisHeaders INTERFACE cxx_std_20) target_include_directories( OasisHeaders INTERFACE $ - $) + $ + /opt/homebrew/include +) + +target_compile_options(OasisHeaders INTERFACE -Wno-error=language-extension-token) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Oasis_HEADERS}) diff --git a/include/Oasis/Real.hpp b/include/Oasis/Real.hpp index f06e6b3a..fa465a8e 100644 --- a/include/Oasis/Real.hpp +++ b/include/Oasis/Real.hpp @@ -7,6 +7,13 @@ #include "LeafExpression.hpp" #include "Unit.hpp" +#include +#include +#include +#include +#include +#include + namespace Oasis { @@ -25,7 +32,7 @@ class Real : public LeafExpression { EXPRESSION_TYPE(Real) EXPRESSION_CATEGORY(UnExp) - auto ConvertTo(Unit TargetUnit) const -> Real; + auto ConvertTo(Unit targetUnit) const -> Real; /** * Gets the value of the real number. * @return The value of the real number. @@ -43,6 +50,8 @@ class Real : public LeafExpression { private: double value {}; Unit unit = Unit::None; + + auto GetFactor(Unit from, Unit to) const -> double; }; } // Oasis diff --git a/src/Real.cpp b/src/Real.cpp index 57de8455..db3341e3 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -28,14 +28,32 @@ auto Real::Equals(const Expression& other) const -> bool return other.Is() && value == dynamic_cast(other).value; } -auto Real::ConvertTo(Unit TargetUnit) const -> Real +auto Real::GetFactor(Unit from, Unit to) const -> double +{ + using namespace boost::units; + using namespace boost::units::si; + + quantity one_meter(1.0 * meter); + quantity one_kilometer(1000 * meter); + if (from == Unit::Meter && to == Unit::Kilogram) { + return one_meter.value() / one_kilometer.value(); + } + if (from == Unit::Kilogram && to == Unit::Meter) { + return one_kilometer.value() / one_meter.value(); + } + + //Other Cases + return 1.0; +} + +auto Real::ConvertTo(Unit targetUnit) const -> Real { //template of the ConvertTo AS OF NOW - if (TargetUnit == unit) { + if (unit == targetUnit) { return *this; } - double factor = 1.00; - return Real(value * factor, TargetUnit); + double factor = GetFactor(unit, targetUnit); + return Real(value * factor, targetUnit); } auto Real::GetValue() const -> double From 9f406f8a945e08acde03777e52b067883f1504d2 Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Sun, 2 Mar 2025 21:53:28 -0500 Subject: [PATCH 4/9] Edit Unit, Test Cases For Basic Unit Added some minor Units, adjusted some minor if condition issues in Real.cpp. Added some basic TestCases in AddTests.cpp Signed-off-by: Jary Chen --- include/Oasis/Unit.hpp | 2 ++ src/Real.cpp | 4 ++-- tests/AddTests.cpp | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/Oasis/Unit.hpp b/include/Oasis/Unit.hpp index 98f3a8bf..af15b810 100644 --- a/include/Oasis/Unit.hpp +++ b/include/Oasis/Unit.hpp @@ -7,6 +7,8 @@ namespace Oasis { enum class Unit { None, Meter, + Kilometer, + Gram, Kilogram, Second, Ampere, diff --git a/src/Real.cpp b/src/Real.cpp index db3341e3..a8a5eed0 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -35,10 +35,10 @@ auto Real::GetFactor(Unit from, Unit to) const -> double quantity one_meter(1.0 * meter); quantity one_kilometer(1000 * meter); - if (from == Unit::Meter && to == Unit::Kilogram) { + if (from == Unit::Meter && to == Unit::Kilometer) { return one_meter.value() / one_kilometer.value(); } - if (from == Unit::Kilogram && to == Unit::Meter) { + if (from == Unit::Kilometer && to == Unit::Meter) { return one_kilometer.value() / one_meter.value(); } diff --git a/tests/AddTests.cpp b/tests/AddTests.cpp index 9e805911..ce876955 100644 --- a/tests/AddTests.cpp +++ b/tests/AddTests.cpp @@ -11,8 +11,31 @@ #include "Oasis/RecursiveCast.hpp" #include "Oasis/Variable.hpp" +#include #include +TEST_CASE("Real Unit Conversion: Meter to Kilometer", "[Real][UnitConversion]") +{ + Oasis::Real meterValue{1000.0, Oasis::Unit::Meter}; + auto kmValue = meterValue.ConvertTo(Oasis::Unit::Kilometer); + REQUIRE(kmValue.GetValue() == Catch::Approx(1.0)); + REQUIRE(kmValue.GetUnit() == Oasis::Unit::Kilometer); +} + +TEST_CASE("Real Unit Conversion: Kilometer to Meter", "[Real][UnitConversion]") { + Oasis::Real kmValue{2.0, Oasis::Unit::Kilometer}; + auto meterValue = kmValue.ConvertTo(Oasis::Unit::Meter); + REQUIRE(meterValue.GetValue() == Catch::Approx(2000.0)); + REQUIRE(meterValue.GetUnit() == Oasis::Unit::Meter); +} + +TEST_CASE("Real Unit Conversion: No Conversion Needed", "[Real][UnitConversion]") { + Oasis::Real value{123.45, Oasis::Unit::Meter}; + auto converted = value.ConvertTo(Oasis::Unit::Meter); + REQUIRE(converted.GetValue() == Catch::Approx(123.45)); + REQUIRE(converted.GetUnit() == Oasis::Unit::Meter); +} + TEST_CASE("Addition", "[Add]") { Oasis::Add add { From a1e817db4a13c4ad5d20363998e85c10f289269c Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Tue, 4 Mar 2025 00:56:02 -0500 Subject: [PATCH 5/9] Introduction of UnitGraph Introduce the UnitGraph.hpp for more robust and complex conversion instead of the manual conversion conditions. This will be the template hpp. Building the chain of equation conversion using Graph Algo. Signed-off-by: Jary Chen --- include/CMakeLists.txt | 3 ++- include/Oasis/UnitGraph.hpp | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 include/Oasis/UnitGraph.hpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 2c155783..8e760d20 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -27,7 +27,8 @@ set(Oasis_HEADERS Oasis/Variable.hpp) # Adds a header-only library target called "OasisHeaders" -add_library(OasisHeaders INTERFACE) +add_library(OasisHeaders INTERFACE + Oasis/UnitGraph.hpp) add_library(Oasis::Headers ALIAS OasisHeaders) target_compile_features(OasisHeaders INTERFACE cxx_std_20) diff --git a/include/Oasis/UnitGraph.hpp b/include/Oasis/UnitGraph.hpp new file mode 100644 index 00000000..f399f3e0 --- /dev/null +++ b/include/Oasis/UnitGraph.hpp @@ -0,0 +1,41 @@ +// +// Created by Jary Chen on 3/4/25. +// + +#ifndef OASIS_UNIT_GRAPH_HPP +#define OASIS_UNIT_GRAPH_HPP + +#include "Unit.hpp" +#include +#include +#include + +namespace Oasis { + +struct EdgeProperties { + double factor; +}; + +using Graph = boost::adjacency_list; + +class UnitGraph { +public: + UnitGraph(); + + void addConversion(Unit from, Unit to, double factor); + + std::optional findConversionFactor(Unit from, Unit to) const; + +private: + Graph graph_; + std::unordered_map unitToVertex_; + int nextVertex_; + + int getOrAddVertex(Unit unit); +}; + +} // namespace Oasis + +#endif // OASIS_UNIT_GRAPH_HPP + From db101b03a6d69d05af8b89aacfe6963e329329ac Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Mon, 10 Mar 2025 15:27:03 -0400 Subject: [PATCH 6/9] Implementation of UnitGraph.cpp Implemented the UnitGraph.cpp. Every Vertex represents the unit with a given index and edge represents the factor of conversion. Initializing standard BFS Graph Algorthim to search the graph. Signed-off-by: Jary Chen --- include/Oasis/UnitGraph.hpp | 3 ++ src/CMakeLists.txt | 3 +- src/UnitGraph.cpp | 73 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/UnitGraph.cpp diff --git a/include/Oasis/UnitGraph.hpp b/include/Oasis/UnitGraph.hpp index f399f3e0..f70201e9 100644 --- a/include/Oasis/UnitGraph.hpp +++ b/include/Oasis/UnitGraph.hpp @@ -6,9 +6,12 @@ #define OASIS_UNIT_GRAPH_HPP #include "Unit.hpp" +#include #include #include #include +#include +#include namespace Oasis { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa6add6b..02be8f78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,7 +27,8 @@ set(Oasis_SOURCES Subtract.cpp # Summation.cpp Undefined.cpp - Variable.cpp) + Variable.cpp + UnitGraph.cpp) # Adds a library target called "Oasis" to be built from source files. add_library(Oasis ${Oasis_SOURCES}) diff --git a/src/UnitGraph.cpp b/src/UnitGraph.cpp new file mode 100644 index 00000000..a58d0ed4 --- /dev/null +++ b/src/UnitGraph.cpp @@ -0,0 +1,73 @@ +// +// Created by Jary Chen on 3/4/25. +// + +#include "../include/Oasis/UnitGraph.hpp" + +namespace Oasis { + +UnitGraph::UnitGraph() : nextVertex_(0) {} + +int UnitGraph::getOrAddVertex(Unit unit) { + auto it = unitToVertex_.find(unit); + if (it != unitToVertex_.end()) + return it->second; + int vertex = nextVertex_; + unitToVertex_[unit] = vertex; + ++nextVertex_; + + // Check if the graph has enough vertices + if (boost::num_vertices(graph_) <= vertex) + boost::add_vertex(graph_); + return vertex; +} + +void UnitGraph::addConversion(Unit from, Unit to, double factor) { + //Build Adj Edges + int vFrom = getOrAddVertex(from); + int vTo = getOrAddVertex(to); + boost::add_edge(vFrom, vTo, EdgeProperties{factor}, graph_); + boost::add_edge(vTo, vFrom, EdgeProperties{1.0 / factor}, graph_); +} + +std::optional UnitGraph::findConversionFactor(Unit from, Unit to) const { + if (from == to) + return 1.0; + auto itFrom = unitToVertex_.find(from); + auto itTo = unitToVertex_.find(to); + if (itFrom == unitToVertex_.end() || itTo == unitToVertex_.end()) + return std::nullopt; + + int start = itFrom->second; + int target = itTo->second; + + //Standard BFS + std::queue queue; + std::unordered_map cumulative; + cumulative[start] = 1.0; + queue.push(start); + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + + if (current == target) + return cumulative[current]; + + auto edges = boost::out_edges(current, graph_); + for (auto edgeIter = edges.first; edgeIter != edges.second; ++edgeIter) { + int neighbor = boost::target(*edgeIter, graph_); + double factor = graph_[*edgeIter].factor; + double newFactor = cumulative[current] * factor; + + //cycle detection + if (cumulative.find(neighbor) == cumulative.end()) { + cumulative[neighbor] = newFactor; + queue.push(neighbor); + } + } + } + return std::nullopt; +} + +} // namespace Oasis From 93b2080a1ad7e5b75444b6f84cf38eaebd09f0f2 Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Mon, 10 Mar 2025 15:44:28 -0400 Subject: [PATCH 7/9] HPP for Singleton UnitGraph Reference to the Global static Instance of the UnitGraph so we can reuse the conversion Algorthim without creating an instance each time. Signed-off-by: Jary Chen --- include/CMakeLists.txt | 3 ++- include/Oasis/GlobalUnitGraph.hpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 include/Oasis/GlobalUnitGraph.hpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 8e760d20..b9d699b2 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -28,7 +28,8 @@ set(Oasis_HEADERS # Adds a header-only library target called "OasisHeaders" add_library(OasisHeaders INTERFACE - Oasis/UnitGraph.hpp) + Oasis/UnitGraph.hpp + Oasis/GlobalUnitGraph.hpp) add_library(Oasis::Headers ALIAS OasisHeaders) target_compile_features(OasisHeaders INTERFACE cxx_std_20) diff --git a/include/Oasis/GlobalUnitGraph.hpp b/include/Oasis/GlobalUnitGraph.hpp new file mode 100644 index 00000000..056fcee0 --- /dev/null +++ b/include/Oasis/GlobalUnitGraph.hpp @@ -0,0 +1,14 @@ +// +// Created by Jary Chen on 3/10/25. +// + +#ifndef GLOBALUNITGRAPH_HPP +#define GLOBALUNITGRAPH_HPP +#include "UnitGraph.hpp" + +namespace Oasis { + // Reference to singleton UnitGraph + UnitGraph& getGlobalUnitGraph(); +} + +#endif //GLOBALUNITGRAPH_HPP From 3201db9ee0796dd16ac8dc2747fdf237d3864a79 Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Mon, 10 Mar 2025 15:55:10 -0400 Subject: [PATCH 8/9] CPP for Singleton UnitGraph Made a static globalGraph and a central place for all the conversion to be added and initialized only once Signed-off-by: Jary Chen --- src/CMakeLists.txt | 3 ++- src/GlobalUnitGraph.cpp | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/GlobalUnitGraph.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 02be8f78..176084cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,7 +28,8 @@ set(Oasis_SOURCES # Summation.cpp Undefined.cpp Variable.cpp - UnitGraph.cpp) + UnitGraph.cpp + GlobalUnitGraph.cpp) # Adds a library target called "Oasis" to be built from source files. add_library(Oasis ${Oasis_SOURCES}) diff --git a/src/GlobalUnitGraph.cpp b/src/GlobalUnitGraph.cpp new file mode 100644 index 00000000..af7e0864 --- /dev/null +++ b/src/GlobalUnitGraph.cpp @@ -0,0 +1,21 @@ +// +// Created by Jary Chen on 3/10/25. +// + +#include "../include/Oasis/GlobalUnitGraph.hpp" + +namespace Oasis { + +UnitGraph& getGlobalUnitGraph() { + static UnitGraph globalGraph; + static bool initialized = false; + if (!initialized) { + initialized = true; + + // Mapping Here + globalGraph.addConversion(Unit::Meter, Unit::Kilometer, 0.001); + } + return globalGraph; +} + +} // namespace Oasis From 409f67d429ce5b0bee848d3e15f5c085d3525711 Mon Sep 17 00:00:00 2001 From: Jary Chen Date: Tue, 11 Mar 2025 15:13:21 -0400 Subject: [PATCH 9/9] Implemented UnitGraph Into Real Revised the Real.hpp/cpp to use UnitGraph and replace the original template of convertTo. Edit Some Test Cases. Signed-off-by: Jary Chen --- include/Oasis/Real.hpp | 2 +- src/Real.cpp | 29 ++++++++--------------------- tests/AddTests.cpp | 10 ++++++---- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/include/Oasis/Real.hpp b/include/Oasis/Real.hpp index fa465a8e..4b28feb6 100644 --- a/include/Oasis/Real.hpp +++ b/include/Oasis/Real.hpp @@ -7,6 +7,7 @@ #include "LeafExpression.hpp" #include "Unit.hpp" +#include "GlobalUnitGraph.hpp" #include #include #include @@ -51,7 +52,6 @@ class Real : public LeafExpression { double value {}; Unit unit = Unit::None; - auto GetFactor(Unit from, Unit to) const -> double; }; } // Oasis diff --git a/src/Real.cpp b/src/Real.cpp index a8a5eed0..71703d09 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -28,32 +28,19 @@ auto Real::Equals(const Expression& other) const -> bool return other.Is() && value == dynamic_cast(other).value; } -auto Real::GetFactor(Unit from, Unit to) const -> double -{ - using namespace boost::units; - using namespace boost::units::si; - - quantity one_meter(1.0 * meter); - quantity one_kilometer(1000 * meter); - if (from == Unit::Meter && to == Unit::Kilometer) { - return one_meter.value() / one_kilometer.value(); - } - if (from == Unit::Kilometer && to == Unit::Meter) { - return one_kilometer.value() / one_meter.value(); - } - - //Other Cases - return 1.0; -} - auto Real::ConvertTo(Unit targetUnit) const -> Real -{ //template of the ConvertTo AS OF NOW +{ if (unit == targetUnit) { return *this; } - double factor = GetFactor(unit, targetUnit); - return Real(value * factor, targetUnit); + const auto& globalGraph = getGlobalUnitGraph(); + auto factorOpt = globalGraph.findConversionFactor(unit, targetUnit); + if (!factorOpt.has_value()) { + throw std::runtime_error("Real::ConvertTo: Conversion to unit not found"); + } + + return Real(value * factorOpt.value(), targetUnit); } auto Real::GetValue() const -> double diff --git a/tests/AddTests.cpp b/tests/AddTests.cpp index ce876955..7f8e7404 100644 --- a/tests/AddTests.cpp +++ b/tests/AddTests.cpp @@ -14,24 +14,26 @@ #include #include -TEST_CASE("Real Unit Conversion: Meter to Kilometer", "[Real][UnitConversion]") -{ +TEST_CASE("Conversion: Meter to Kilometer", "[Real][UnitConversion]") { Oasis::Real meterValue{1000.0, Oasis::Unit::Meter}; auto kmValue = meterValue.ConvertTo(Oasis::Unit::Kilometer); + REQUIRE(kmValue.GetValue() == Catch::Approx(1.0)); REQUIRE(kmValue.GetUnit() == Oasis::Unit::Kilometer); } -TEST_CASE("Real Unit Conversion: Kilometer to Meter", "[Real][UnitConversion]") { +TEST_CASE("Conversion: Kilometer to Meter", "[Real][UnitConversion]") { Oasis::Real kmValue{2.0, Oasis::Unit::Kilometer}; auto meterValue = kmValue.ConvertTo(Oasis::Unit::Meter); + REQUIRE(meterValue.GetValue() == Catch::Approx(2000.0)); REQUIRE(meterValue.GetUnit() == Oasis::Unit::Meter); } -TEST_CASE("Real Unit Conversion: No Conversion Needed", "[Real][UnitConversion]") { +TEST_CASE("Conversion: No Conversion Needed", "[Real][UnitConversion]") { Oasis::Real value{123.45, Oasis::Unit::Meter}; auto converted = value.ConvertTo(Oasis::Unit::Meter); + REQUIRE(converted.GetValue() == Catch::Approx(123.45)); REQUIRE(converted.GetUnit() == Oasis::Unit::Meter); }