From 17e6b0d75dd00bf7ca127157f9c28979c4182fbf Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Sat, 28 Dec 2019 18:59:53 +0100 Subject: [PATCH] Small refactoring of new ratio (resolves #14) --- README.md | 1 + doc/DESIGN.md | 15 ++++++++++++--- src/include/units/bits/unit_text.h | 14 ++++++++------ src/include/units/data/prefixes.h | 1 - src/include/units/ratio.h | 3 ++- test/unit_test/runtime/fmt_test.cpp | 16 ++++++++-------- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index f121f459..34542080 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,7 @@ NOTE: This library as of now compiles correctly only with gcc-9.1 and newer. - Added official CGS system support - Added official data information system support - Repository file tree cleanup + - `ratio` refactored to contain `Exp` template parameter - 0.4.0 Nov 17, 2019 - Support for derived dimensions in `exp` added diff --git a/doc/DESIGN.md b/doc/DESIGN.md index 9dd42c69..be700423 100644 --- a/doc/DESIGN.md +++ b/doc/DESIGN.md @@ -74,7 +74,16 @@ struct scaled_unit : downcast_base> { }; ``` -The above type is a framework's private type and the user should never instantiate it directly. +where: + +```cpp +template +concept UnitRatio = Ratio && (R::num * R::den > 0); +``` + +and `Ratio` is satisfied by any instantiation of `units::ratio`. + +The `scaled_unit` type is a framework's private type and the user should never instantiate it directly. The public user interface to create units consists of: ![Units UML](units.png) @@ -143,8 +152,8 @@ namespace units::si { // prefixes struct prefix : prefix_type {}; -struct centi : units::prefix> {}; -struct kilo : units::prefix> {}; +struct centi : units::prefix> {}; +struct kilo : units::prefix> {}; // length struct metre : named_unit {}; diff --git a/src/include/units/bits/unit_text.h b/src/include/units/bits/unit_text.h index f9629c89..c3118fac 100644 --- a/src/include/units/bits/unit_text.h +++ b/src/include/units/bits/unit_text.h @@ -31,12 +31,14 @@ constexpr auto ratio_text() { if constexpr(Ratio::num != 1 || Ratio::den != 1 || Ratio::exp != 0) { auto txt = basic_fixed_string("[") + regular(); - if constexpr(Ratio::den == 1 && Ratio::exp == 0) { - return txt + basic_fixed_string("]"); - } - else if constexpr (Ratio::den == 1) { - return txt + basic_fixed_string(" \u00D7 10") + superscript() + - basic_fixed_string("]"); + if constexpr(Ratio::den == 1) { + if constexpr(Ratio::exp == 0) { + return txt + basic_fixed_string("]"); + } + else { + return txt + basic_fixed_string(" \u00D7 10") + superscript() + + basic_fixed_string("]"); + } } else { return txt + basic_fixed_string("/") + regular() + diff --git a/src/include/units/data/prefixes.h b/src/include/units/data/prefixes.h index c03ecf83..5cdd3e21 100644 --- a/src/include/units/data/prefixes.h +++ b/src/include/units/data/prefixes.h @@ -23,7 +23,6 @@ #pragma once #include -#include namespace units::data { diff --git a/src/include/units/ratio.h b/src/include/units/ratio.h index f7dc4da6..fd244f7e 100644 --- a/src/include/units/ratio.h +++ b/src/include/units/ratio.h @@ -40,7 +40,8 @@ template return v < 0 ? -v : v; } -constexpr std::tuple normalize(std::intmax_t num, std::intmax_t den, std::intmax_t exp) { +constexpr std::tuple normalize(std::intmax_t num, std::intmax_t den, std::intmax_t exp) +{ std::intmax_t gcd = std::gcd(num, den); num = num * (den < 0 ? -1 : 1) / gcd; den = detail::abs(den) / gcd; diff --git a/test/unit_test/runtime/fmt_test.cpp b/test/unit_test/runtime/fmt_test.cpp index 979866eb..1bae34a9 100644 --- a/test/unit_test/runtime/fmt_test.cpp +++ b/test/unit_test/runtime/fmt_test.cpp @@ -296,7 +296,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "8 [1 \u00D7 10⁻²]m³"); + CHECK(stream.str() == "8 [1 × 10⁻²]m³"); } SECTION("fmt with default format {} on a quantity") @@ -317,7 +317,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "2 [6 \u00D7 10¹]Hz"); + CHECK(stream.str() == "2 [6 × 10¹]Hz"); } SECTION("fmt with default format {} on a quantity") @@ -338,7 +338,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "10 [1/6 \u00D7 10⁻¹]W"); + CHECK(stream.str() == "10 [1/6 × 10⁻¹]W"); } SECTION("fmt with default format {} on a quantity") @@ -359,7 +359,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "30 [1/6 \u00D7 10²]W"); + CHECK(stream.str() == "30 [1/6 × 10²]W"); } SECTION("fmt with default format {} on a quantity") @@ -404,7 +404,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "8 [1 \u00D7 10³]m⋅s"); + CHECK(stream.str() == "8 [1 × 10³]m⋅s"); } SECTION("fmt with default format {} on a quantity") @@ -425,7 +425,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "2 [6 \u00D7 10¹]kg/s"); + CHECK(stream.str() == "2 [6 × 10¹]kg/s"); } SECTION("fmt with default format {} on a quantity") @@ -446,7 +446,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "10 [1/6 \u00D7 10⁻¹]kg/s"); + CHECK(stream.str() == "10 [1/6 × 10⁻¹]kg/s"); } SECTION("fmt with default format {} on a quantity") @@ -467,7 +467,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("iostream") { - CHECK(stream.str() == "30 [6 \u00D7 10⁻²]1/m⋅s"); + CHECK(stream.str() == "30 [6 × 10⁻²]1/m⋅s"); } SECTION("fmt with default format {} on a quantity")