diff --git a/src/include/units/base_dimension.h b/src/include/units/base_dimension.h index 73ce92c2..2df37dc4 100644 --- a/src/include/units/base_dimension.h +++ b/src/include/units/base_dimension.h @@ -22,8 +22,8 @@ #pragma once -#include -#include +#include +#include #include namespace units { diff --git a/src/include/units/concepts.h b/src/include/units/bits/concepts.h similarity index 95% rename from src/include/units/concepts.h rename to src/include/units/bits/concepts.h index fcc16f35..b43d4524 100644 --- a/src/include/units/concepts.h +++ b/src/include/units/bits/concepts.h @@ -22,8 +22,8 @@ #pragma once -#include -#include +#include +#include #include #include diff --git a/src/include/units/bits/deduced_symbol_text.h b/src/include/units/bits/deduced_symbol_text.h new file mode 100644 index 00000000..04476b27 --- /dev/null +++ b/src/include/units/bits/deduced_symbol_text.h @@ -0,0 +1,82 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include +#include +#include + +namespace units::detail { + +template +constexpr auto operator_text() +{ + if constexpr(Idx == 0) { + if constexpr(Divide) { + return basic_fixed_string("1/"); + } + else { + return basic_fixed_string(""); + } + } + else { + if constexpr(Divide) { + return basic_fixed_string("/"); + } + else { + return basic_fixed_string("⋅"); + } + } +} + +template +constexpr auto exp_text() +{ + // get calculation operator + symbol + const auto txt = operator_text() + Symbol; + if constexpr(E::den != 1) { + // add root part + return txt + basic_fixed_string("^(") + regular() + basic_fixed_string("/") + regular() + basic_fixed_string(")"); + } + else if constexpr(abs(E::num) != 1) { + // add exponent part + return txt + superscript(); + } + else { + return txt; + } +} + +template +constexpr auto deduced_symbol_text(derived_dimension, std::index_sequence) +{ + return (exp_text() + ...); +} + +template +constexpr auto deduced_symbol_text() +{ + return deduced_symbol_text(Dim(), std::index_sequence_for()); +} + +} // namespace units::detail diff --git a/src/include/units/bits/deduced_unit.h b/src/include/units/bits/deduced_unit.h new file mode 100644 index 00000000..6f170aa5 --- /dev/null +++ b/src/include/units/bits/deduced_unit.h @@ -0,0 +1,72 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include +#include + +namespace units::detail { + +// same_scaled_units +template +inline constexpr bool same_scaled_units = false; + +template +inline constexpr bool same_scaled_units, Us...> = (UnitOf && ...); + +// deduced_unit +template +struct ratio_op; + +template +struct ratio_op { + using ratio = Result; +}; + +template +struct ratio_op { + using calc_ratio = + conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply, ratio_divide>; + static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen); + using ratio = ratio_op::ratio; +}; + +template +struct derived_ratio; + +template +struct derived_ratio, Us...> { + using ratio = ::units::ratio<1>; +}; + +template +struct derived_ratio, U, URest...> { + using rest_ratio = derived_ratio, URest...>::ratio; + using ratio = ratio_op::ratio; +}; + +template +using deduced_unit = + scaled_unit::ratio>; + +} // namespace units::detail diff --git a/src/include/units/dimension_op.h b/src/include/units/bits/dimension_op.h similarity index 98% rename from src/include/units/dimension_op.h rename to src/include/units/bits/dimension_op.h index e18649e8..520086c8 100644 --- a/src/include/units/dimension_op.h +++ b/src/include/units/bits/dimension_op.h @@ -200,7 +200,7 @@ struct dimension_sqrt_impl; template struct dimension_sqrt_impl { - using type = derived_dimension>; + using type = downcast_dimension>>; }; template @@ -210,7 +210,7 @@ struct dimension_sqrt_impl>> { template struct dimension_sqrt_impl { - using type = dimension_sqrt_impl; + using type = dimension_sqrt_impl::type; }; template @@ -221,7 +221,7 @@ struct dimension_sqrt_impl> { } // namespace detail template -using dimension_sqrt = detail::dimension_sqrt_impl::type; +using dimension_sqrt = detail::dimension_sqrt_impl::type; // dimension_pow namespace detail { diff --git a/src/include/units/bits/downcasting.h b/src/include/units/bits/external/downcasting.h similarity index 98% rename from src/include/units/bits/downcasting.h rename to src/include/units/bits/external/downcasting.h index 822bf909..535147e9 100644 --- a/src/include/units/bits/downcasting.h +++ b/src/include/units/bits/external/downcasting.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include namespace units { diff --git a/src/include/units/bits/fixed_string.h b/src/include/units/bits/external/fixed_string.h similarity index 100% rename from src/include/units/bits/fixed_string.h rename to src/include/units/bits/external/fixed_string.h diff --git a/src/include/units/bits/hacks.h b/src/include/units/bits/external/hacks.h similarity index 100% rename from src/include/units/bits/hacks.h rename to src/include/units/bits/external/hacks.h diff --git a/src/include/units/bits/numeric_concepts.h b/src/include/units/bits/external/numeric_concepts.h similarity index 99% rename from src/include/units/bits/numeric_concepts.h rename to src/include/units/bits/external/numeric_concepts.h index 5ccbe997..abbef656 100644 --- a/src/include/units/bits/numeric_concepts.h +++ b/src/include/units/bits/external/numeric_concepts.h @@ -22,7 +22,7 @@ #pragma once -#include +#include // P1813 - A Concept Design for the Numeric Algorithms diff --git a/src/include/units/bits/external/text_tools.h b/src/include/units/bits/external/text_tools.h new file mode 100644 index 00000000..7e102fe7 --- /dev/null +++ b/src/include/units/bits/external/text_tools.h @@ -0,0 +1,64 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +namespace units::detail { + +template + requires (0 <= Value) && (Value < 10) +inline constexpr basic_fixed_string superscript_number = ""; + +template<> inline constexpr basic_fixed_string superscript_number<0> = "\u2070"; +template<> inline constexpr basic_fixed_string superscript_number<1> = "\u00b9"; +template<> inline constexpr basic_fixed_string superscript_number<2> = "\u00b2"; +template<> inline constexpr basic_fixed_string superscript_number<3> = "\u00b3"; +template<> inline constexpr basic_fixed_string superscript_number<4> = "\u2074"; +template<> inline constexpr basic_fixed_string superscript_number<5> = "\u2075"; +template<> inline constexpr basic_fixed_string superscript_number<6> = "\u2076"; +template<> inline constexpr basic_fixed_string superscript_number<7> = "\u2077"; +template<> inline constexpr basic_fixed_string superscript_number<8> = "\u2078"; +template<> inline constexpr basic_fixed_string superscript_number<9> = "\u2079"; + +template + requires (Value >= 0) +constexpr auto superscript() +{ + if constexpr(Value < 10) + return superscript_number; + else + return superscript() + superscript(); +} + +template + requires (Value >= 0) +constexpr auto regular() +{ + if constexpr(Value < 10) + return basic_fixed_string(static_cast('0' + Value)); + else + return regular() + regular(); +} + +} // namespace units::detail diff --git a/src/include/units/bits/type_list.h b/src/include/units/bits/external/type_list.h similarity index 99% rename from src/include/units/bits/type_list.h rename to src/include/units/bits/external/type_list.h index a4b51d6e..422bb00f 100644 --- a/src/include/units/bits/type_list.h +++ b/src/include/units/bits/external/type_list.h @@ -22,7 +22,7 @@ #pragma once -#include +#include namespace units { diff --git a/src/include/units/bits/type_traits.h b/src/include/units/bits/external/type_traits.h similarity index 100% rename from src/include/units/bits/type_traits.h rename to src/include/units/bits/external/type_traits.h diff --git a/src/include/units/bits/unit_text.h b/src/include/units/bits/unit_text.h new file mode 100644 index 00000000..af95c30e --- /dev/null +++ b/src/include/units/bits/unit_text.h @@ -0,0 +1,129 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include +#include + +namespace units::detail { + +template +constexpr auto ratio_text() +{ + if constexpr(Ratio::num != 1 || Ratio::den != 1) { + auto txt = basic_fixed_string("[") + regular(); + if constexpr(Ratio::den == 1) { + return txt + basic_fixed_string("]"); + } + else { + return txt + basic_fixed_string("/") + regular() + basic_fixed_string("]"); + } + } + else { + return basic_fixed_string(""); + } +} + +template +constexpr auto prefix_or_ratio_text() +{ + if constexpr(Ratio::num == 1 && Ratio::den == 1) { + // no ratio/prefix + return basic_fixed_string(""); + } + else { + if constexpr (!std::same_as) { + // try to form a prefix + using prefix = downcast>; + + if constexpr(!std::same_as>) { + // print as a prefixed unit + return prefix::symbol; + } + else { + // print as a ratio of the coherent unit + return ratio_text(); + } + } + else { + // print as a ratio of the coherent unit + return ratio_text(); + } + } +} + +template +constexpr auto derived_dimension_unit_text(derived_dimension, std::index_sequence) +{ + return (exp_text::symbol, Idxs>() + ...); +} + +template +constexpr auto derived_dimension_unit_text(derived_dimension d) +{ + return derived_dimension_unit_text(d, std::index_sequence_for()); +} + +template +constexpr bool all_named(derived_dimension) +{ + return (dimension_unit::is_named && ...); +} + +template +constexpr auto derived_dimension_unit_text() +{ + using recipe = typename Dim::recipe; + if constexpr(all_named(recipe())) + return derived_dimension_unit_text(recipe()); + else + return derived_dimension_unit_text(Dim()); +} + +// TODO Inline below concept when switched to gcc-10 +template +concept has_symbol = requires{ T::symbol; }; + +template +constexpr auto unit_text() +{ + if constexpr(has_symbol) { + // already has a symbol so print it + return U::symbol; + } + else { + // print as a prefix or ratio of a reference unit + auto prefix_txt = prefix_or_ratio_text(); + + if constexpr(has_symbol) { + // use predefined reference unit symbol + return prefix_txt + U::reference::symbol; + } + else { + // use derived dimension ingredients to create a unit symbol + return prefix_txt + derived_dimension_unit_text(); + } + } +} + +} // namespace units::detail diff --git a/src/include/units/derived_dimension.h b/src/include/units/derived_dimension.h index 42456975..a0846a81 100644 --- a/src/include/units/derived_dimension.h +++ b/src/include/units/derived_dimension.h @@ -23,9 +23,9 @@ #pragma once #include -#include -#include -#include +#include +#include +#include #include #include @@ -264,7 +264,7 @@ using base_units_ratio = base_units_ratio_impl::type; * The implementation is responsible for unpacking all of the dimensions into a list containing only base dimensions * and their factors and putting them to the other (private) units::derived_dimension class template partial * specialization. - * + * * @note User should always use only this partial specialization to create derived dimensions. * * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) @@ -279,24 +279,4 @@ struct derived_dimension : downcast_child>::downcast_base_type>; }; -namespace detail { - -template -struct dimension_unit_impl; - -template -struct dimension_unit_impl { - using type = D::base_unit; -}; - -template -struct dimension_unit_impl { - using type = D::coherent_unit; -}; - -} - -template -using dimension_unit = detail::dimension_unit_impl::type; - } // namespace units diff --git a/src/include/units/format.h b/src/include/units/format.h index 1bbea90d..68c688cc 100644 --- a/src/include/units/format.h +++ b/src/include/units/format.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include #include @@ -116,20 +116,20 @@ namespace units { return format_to(out, treat_as_floating_point ? "{:" + sign_text + "g}" : "{:" + sign_text + "}", val); } - template + template inline static OutputIt format_units_quantity_unit(OutputIt out) { - return format_to(out, "{}", unit_text().c_str()); + return format_to(out, "{}", unit_text().c_str()); } - template + template struct units_formatter { OutputIt out; Rep val; fmt::sign_t sign; int precision; - explicit units_formatter(OutputIt o, quantity q, fmt::sign_t s, int prec): + explicit units_formatter(OutputIt o, quantity q, fmt::sign_t s, int prec): out(o), val(q.count()), sign(s), precision(prec) { } @@ -147,7 +147,7 @@ namespace units { void on_quantity_unit() { - out = format_units_quantity_unit(out); + out = format_units_quantity_unit(out); } }; @@ -155,10 +155,10 @@ namespace units { } // namespace units -template -struct fmt::formatter, CharT> { +template +struct fmt::formatter, CharT> { private: - using quantity = units::quantity; + using quantity = units::quantity; using iterator = fmt::basic_parse_context::iterator; using arg_ref_type = fmt::internal::arg_ref; @@ -293,7 +293,7 @@ public: } template - auto format(const units::quantity& q, FormatContext& ctx) + auto format(const units::quantity& q, FormatContext& ctx) { auto begin = format_str.begin(), end = format_str.end(); @@ -310,7 +310,7 @@ public: // default format should print value followed by the unit separeted with 1 space out = units::detail::format_units_quantity_value(out, q.count(), specs.sign, precision); *out++ = CharT(' '); - units::detail::format_units_quantity_unit(out); + units::detail::format_units_quantity_unit(out); } else { // user provided format diff --git a/src/include/units/physical/dimensions.h b/src/include/units/physical/dimensions.h index 86004125..66460480 100644 --- a/src/include/units/physical/dimensions.h +++ b/src/include/units/physical/dimensions.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include #include #include diff --git a/src/include/units/prefix.h b/src/include/units/prefix.h index 5f95b7e7..2117178d 100644 --- a/src/include/units/prefix.h +++ b/src/include/units/prefix.h @@ -22,8 +22,8 @@ #pragma once -#include -#include +#include +#include #include namespace units { diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 7bfa7375..0cf29bbf 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -22,8 +22,9 @@ #pragma once -#include -#include +#include +#include +#include #include #include @@ -441,7 +442,7 @@ public: template friend std::basic_ostream& operator<<(std::basic_ostream& os, const quantity& q) { - return os << q.count(); // << " " << detail::unit_text(); TODO add support + return os << q.count() << " " << detail::unit_text(); } }; diff --git a/src/include/units/ratio.h b/src/include/units/ratio.h index 1092ca35..80e964f9 100644 --- a/src/include/units/ratio.h +++ b/src/include/units/ratio.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include #include diff --git a/src/include/units/unit.h b/src/include/units/unit.h index 2f9a3254..f0875a95 100644 --- a/src/include/units/unit.h +++ b/src/include/units/unit.h @@ -22,10 +22,13 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -60,7 +63,7 @@ template struct same_unit_reference : std::is_same {}; /** - * @brief A starting point for a new hierarchy of units + * @brief An unnamed unit * * Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension * and it should be passed in this dimension's definition. @@ -76,7 +79,7 @@ struct unit : downcast_child>> { /** * @brief Unknown unit * - * Used as a reference unit of an unknown dimension. + * Used as a coherent unit of an unknown dimension. */ struct unknown_unit : unit {}; @@ -144,65 +147,13 @@ struct prefixed_unit : using prefix_type = P::prefix_type; }; -// UnitOf -template -concept UnitOf = - Unit && - Dimension && - std::same_as::reference>; - -namespace detail { - -// same_scaled_units -template -inline constexpr bool same_scaled_units = false; - -template -inline constexpr bool same_scaled_units, Us...> = (UnitOf && ...); - -// deduced_unit -template -struct ratio_op; - -template -struct ratio_op { - using ratio = Result; -}; - -template -struct ratio_op { - using calc_ratio = - conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply, ratio_divide>; - static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen); - using ratio = ratio_op::ratio; -}; - -template -struct derived_ratio; - -template -struct derived_ratio, Us...> { - using ratio = ::units::ratio<1>; -}; - -template -struct derived_ratio, U, URest...> { - using rest_ratio = derived_ratio, URest...>::ratio; - using ratio = ratio_op::ratio; -}; - -template -using deduced_unit = - scaled_unit::ratio>; - -} // namespace detail - /** * @brief A unit with a deduced ratio and symbol * * Defines a new unit with a deduced ratio and symbol based on the recipe from the provided - * derived dimension. The number and order of provided units should match the recipe of - * dimension. + * derived dimension. The number and order of provided units should match the recipe of the + * derived dimension. All of the units provided should also be a named ones so it is possible + * to create a deduced symbol text. * * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Dim a derived dimension recipe to use for deduction @@ -214,7 +165,7 @@ template (U::is_named && (URest::is_named && ... && true)) struct deduced_unit : downcast_child> { static constexpr bool is_named = false; - static constexpr auto symbol = basic_fixed_string{""}; // detail::deduced_symbol_text(); // TODO implement this + static constexpr auto symbol = detail::deduced_symbol_text(); using prefix_type = no_prefix; }; diff --git a/src/include/units/bits/unit_concept.h b/src/include/units/unit_concept.h similarity index 96% rename from src/include/units/bits/unit_concept.h rename to src/include/units/unit_concept.h index d8e675b3..9e250657 100644 --- a/src/include/units/bits/unit_concept.h +++ b/src/include/units/unit_concept.h @@ -22,11 +22,12 @@ #pragma once -#include +#include #include namespace units { +// UnitRatio template concept UnitRatio = Ratio && (R::num * R::den > 0); diff --git a/src/include/units/unit_of_concept.h b/src/include/units/unit_of_concept.h new file mode 100644 index 00000000..143d4678 --- /dev/null +++ b/src/include/units/unit_of_concept.h @@ -0,0 +1,57 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +namespace units { + +namespace detail { + +template +struct dimension_unit_impl; + +template +struct dimension_unit_impl { + using type = D::base_unit; +}; + +template +struct dimension_unit_impl { + using type = D::coherent_unit; +}; + +} // namespace detail + +template +using dimension_unit = detail::dimension_unit_impl::type; + +// UnitOf +template +concept UnitOf = + Unit && + Dimension && + std::same_as::reference>; + // same_unit_reference> // TODO check if this works + +} // namespace units diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1a5b1883..67a1d088 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -#add_subdirectory(unit_test/runtime) +add_subdirectory(unit_test/runtime) add_subdirectory(unit_test/static) #add_subdirectory(metabench) diff --git a/test/unit_test/runtime/digital_info_test.cpp b/test/unit_test/runtime/digital_info_test.cpp index 600c17e6..0b032a09 100644 --- a/test/unit_test/runtime/digital_info_test.cpp +++ b/test/unit_test/runtime/digital_info_test.cpp @@ -20,43 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include +#include #include #include -namespace data { +using namespace units::data; - struct base_dim_digital_information : units::base_dimension<"digital information", "b"> {}; - - struct digital_information : units::derived_dimension> {}; - - template - concept DigitalInformation = units::QuantityOf; - - struct data_prefix : units::prefix_type {}; - - struct kibi : units::prefix, "Ki"> {}; - struct mebi : units::prefix, "Mi"> {}; - - struct bit : units::named_coherent_derived_unit {}; - struct kilobit : units::prefixed_derived_unit {}; - struct byte : units::named_scaled_derived_unit, data_prefix> {}; - struct kilobyte : units::prefixed_derived_unit {}; - - inline namespace literals { - - constexpr auto operator""_b(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""_Kib(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""_B(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""_KiB(unsigned long long l) { return units::quantity(l); } - - } - -} - -using namespace data; - -TEST_CASE("operator<< on a custom quantity", "[text][ostream]") +TEST_CASE("operator<< on a data quantity", "[text][ostream]") { std::stringstream stream; @@ -64,25 +34,25 @@ TEST_CASE("operator<< on a custom quantity", "[text][ostream]") { SECTION("named unit") { - stream << 64_B; + stream << 64B; REQUIRE(stream.str() == "64 B"); } SECTION("prefixed coherent unit") { - stream << 256_Kib; + stream << 256Kib; REQUIRE(stream.str() == "256 Kib"); } SECTION("prefixed non-coherent unit") { - stream << 1024_KiB; + stream << 1024KiB; REQUIRE(stream.str() == "1024 KiB"); } SECTION("other unit matching prefix") { - stream << 8_Kib * 8_Kib / 2_b; + stream << 8Kib * 8Kib / 2b; REQUIRE(stream.str() == "32 Mib"); } } diff --git a/test/unit_test/runtime/fmt_test.cpp b/test/unit_test/runtime/fmt_test.cpp index a214bb6f..b3123215 100644 --- a/test/unit_test/runtime/fmt_test.cpp +++ b/test/unit_test/runtime/fmt_test.cpp @@ -20,18 +20,20 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "units/dimensions/area.h" -#include "units/dimensions/frequency.h" -#include "units/dimensions/power.h" -#include "units/dimensions/velocity.h" -#include "units/dimensions/volume.h" -#include "units/dimensions/surface_tension.h" +#include "units/physical/si/area.h" +#include "units/physical/si/frequency.h" +#include "units/physical/si/power.h" +#include "units/physical/si/pressure.h" +#include "units/physical/si/velocity.h" +#include "units/physical/si/volume.h" +#include "units/physical/si/surface_tension.h" #include "units/format.h" #include "units/math.h" #include #include using namespace units; +using namespace units::si; using namespace Catch::Matchers; TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") @@ -108,7 +110,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") { SECTION("in terms of base units") { - const quantity>> q(123); + const length>> q(123); stream << q; SECTION("iostream") @@ -129,7 +131,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("in terms of derived units") { - const quantity>> q(60); + const energy>> q(60); stream << q; SECTION("iostream") @@ -242,8 +244,8 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("surface tension") { - struct newton_per_centimetre : deduced_derived_unit {}; - const quantity q(123); + struct newton_per_centimetre : deduced_unit {}; + const surface_tension q(123); stream << q; SECTION("iostream") @@ -636,17 +638,17 @@ TEST_CASE("format string with only %Q should print quantity value only", "[text] SECTION("nan") { - CHECK(fmt::format("{:%Q}", quantity(std::numeric_limits::quiet_NaN())) == "nan"); + CHECK(fmt::format("{:%Q}", length(std::numeric_limits::quiet_NaN())) == "nan"); } SECTION("inf") { - CHECK(fmt::format("{:%Q}", quantity(std::numeric_limits::infinity())) == "inf"); + CHECK(fmt::format("{:%Q}", length(std::numeric_limits::infinity())) == "inf"); } SECTION("-inf") { - CHECK(fmt::format("{:%Q}", quantity(-std::numeric_limits::infinity())) == "-inf"); + CHECK(fmt::format("{:%Q}", length(-std::numeric_limits::infinity())) == "-inf"); } } } @@ -742,8 +744,8 @@ TEST_CASE("fill and align specification", "[text][fmt]") TEST_CASE("sign specification", "[text][fmt]") { - quantity inf(std::numeric_limits::infinity()); - quantity nan(std::numeric_limits::quiet_NaN()); + length inf(std::numeric_limits::infinity()); + length nan(std::numeric_limits::quiet_NaN()); SECTION("default format {} on a quantity") { diff --git a/test/unit_test/runtime/fmt_units_test.cpp b/test/unit_test/runtime/fmt_units_test.cpp index 390f8cb7..1e721528 100644 --- a/test/unit_test/runtime/fmt_units_test.cpp +++ b/test/unit_test/runtime/fmt_units_test.cpp @@ -20,16 +20,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "units/dimensions/area.h" -#include "units/dimensions/frequency.h" -#include "units/dimensions/power.h" -#include "units/dimensions/velocity.h" -#include "units/dimensions/volume.h" -#include "units/dimensions/surface_tension.h" +#include "units/physical/si/area.h" +#include "units/physical/si/frequency.h" +#include "units/physical/si/power.h" +#include "units/physical/si/velocity.h" +#include "units/physical/si/volume.h" +#include "units/physical/si/surface_tension.h" #include "units/format.h" #include -using namespace units; +using namespace units::si; TEST_CASE("fmt::format on synthesized unit symbols", "[text][fmt]") { diff --git a/test/unit_test/runtime/math_test.cpp b/test/unit_test/runtime/math_test.cpp index 4e72e26b..b147e839 100644 --- a/test/unit_test/runtime/math_test.cpp +++ b/test/unit_test/runtime/math_test.cpp @@ -21,73 +21,35 @@ // SOFTWARE. #include "units/math.h" -#include "units/dimensions/area.h" -#include "units/dimensions/volume.h" +#include "units/physical/si/area.h" +#include "units/physical/si/volume.h" #include using namespace units; +using namespace units::si; // classical -TEST_CASE("pow() on quantity changes the value and the dimension accordingly", "[math][pow]") +TEST_CASE("'pow()' on quantity changes the value and the dimension accordingly", "[math][pow]") { - CHECK(pow<0>(2m) == 1); - CHECK(pow<1>(2m) == 2m); - CHECK(pow<2>(2m) == 4sq_m); - CHECK(pow<3>(2m) == 8cub_m); + SECTION ("'pow<0>(q)' returns '1'") { + CHECK(pow<0>(2m) == 1); + } + + SECTION ("'pow<1>(q)' returns 'q'") { + CHECK(pow<1>(2m) == 2m); + } + + SECTION ("'pow<2>(q)' squares both the value and a dimension") { + CHECK(pow<2>(2m) == 4sq_m); + } + + SECTION ("'pow<3>(q)' cubes both the value and a dimension") { + CHECK(pow<3>(2m) == 8cub_m); + } } -TEST_CASE("sqrt() on quantity changes the value and the dimension accordingly", "[math][sqrt]") +TEST_CASE("'sqrt()' on quantity changes the value and the dimension accordingly", "[math][sqrt]") { REQUIRE(sqrt(4sq_m) == 2m); } - -// BDD style - -SCENARIO("quantities should work with pow()", "[math][pow]") -{ - GIVEN("A quantity q") { - auto q = 2m; - - REQUIRE(q.count() == 2); - - WHEN("pow<1>(q) is called") { - auto res = pow<1>(q); - - THEN("the same quantity is received") { - REQUIRE(res == q); - } - } - WHEN("pow<2>(q) is called") { - auto res = pow<2>(q); - - THEN("both the value and dimension is raised to the exponent 2") { - REQUIRE(res == 4sq_m); - } - } - WHEN("pow<3>(q) is called") { - auto res = pow<3>(q); - - THEN("both the value and dimension is raised to the exponent 3") { - REQUIRE(res == 8cub_m); - } - } - } -} - -SCENARIO("quantities should work with sqrt()", "[math][sqrt]") -{ - GIVEN("A quantity q") { - auto q = 4sq_m; - - REQUIRE(q.count() == 4); - - WHEN("sqrt(q) is called") { - auto res = sqrt(q); - - THEN("both the value and dimension are square rooted") { - REQUIRE(res == 2m); - } - } - } -} diff --git a/test/unit_test/static/dimension_op_test.cpp b/test/unit_test/static/dimension_op_test.cpp index 6f94c6b5..900a8b02 100644 --- a/test/unit_test/static/dimension_op_test.cpp +++ b/test/unit_test/static/dimension_op_test.cpp @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "units/dimension_op.h" +#include "units/bits/dimension_op.h" #include "units/unit.h" #include diff --git a/test/unit_test/static/type_list_test.cpp b/test/unit_test/static/type_list_test.cpp index 6ee9688f..9c5bec90 100644 --- a/test/unit_test/static/type_list_test.cpp +++ b/test/unit_test/static/type_list_test.cpp @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "units/bits/type_list.h" +#include "units/bits/external/type_list.h" #include "units/derived_dimension.h" #include "units/unit.h" #include diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index a23bee55..84dc5e10 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -53,6 +53,6 @@ static_assert(std::is_same_v