diff --git a/src/include/units/base_dimension.h b/src/include/units/base_dimension.h index 3e6b03a7..73ce92c2 100644 --- a/src/include/units/base_dimension.h +++ b/src/include/units/base_dimension.h @@ -31,14 +31,18 @@ namespace units { /** * @brief A dimension of a base quantity * - * Measurement unit that is adopted by convention for a base quantity (a quantity that can not be expressed in terms of - * the other quantities within that subset) in a specific system of units. + * Base quantity is a quantity in a conventionally chosen subset of a given system of quantities, where no quantity + * in the subset can be expressed in terms of the other quantities within that subset. They are referred to as + * being mutually independent since a base quantity cannot be expressed as a product of powers of the other base + * quantities. + * + * Base unit is a measurement unit that is adopted by convention for a base quantity in a specific system of units. * * Pair of Name and Unit template parameter forms an unique identifier of the base dimension. The same identifiers can - * be multiplied and divided which will result with an adjustment of its factor in an Exponent (in case of zero the - * dimension will be simplified and removed from further analysis of current expresion). In case the Name is the same - * but the Unit differs (i.e. mixing SI and CGS length), there is no automatic simplification but is possible to force - * it with a quantity_cast. + * be multiplied and divided which will result with an adjustment of its factor in an Exponent od a DerivedDimension + * (in case of zero the dimension will be simplified and removed from further analysis of current expresion). In case + * the Name is the same but the Unit differs (i.e. mixing SI and CGS length), there is no automatic simplification but + * is possible to force it with a quantity_cast. * * @tparam Name an unique identifier of the base dimension used to provide dimensional analysis support * @tparam U a base unit to be used for this base dimension @@ -47,7 +51,7 @@ template struct base_dimension { using base_type_workaround = base_dimension; // TODO Replace with is_derived_from_instantiation when fixed static constexpr auto name = Name; - using coherent_unit = U; + using base_unit = U; }; // BaseDimension diff --git a/src/include/units/derived_dimension.h b/src/include/units/derived_dimension.h index cf35b99d..42456975 100644 --- a/src/include/units/derived_dimension.h +++ b/src/include/units/derived_dimension.h @@ -77,7 +77,7 @@ struct derived_dimension<> : downcast_base> {}; * @tparam ERest zero or more following exponents of a derived dimension */ template -struct derived_dimension : downcast_base> {}; +struct derived_dimension : downcast_base> {}; // TODO rename to 'dimension'? // DerivedDimension template @@ -220,6 +220,35 @@ struct extract, Num, Den>, ERest...> { template using make_dimension = dim_consolidate::type, exp_less>>::type; +template + requires (E::den == 1 || E::den == 2) // TODO provide support for any den +struct exp_ratio { + using base_ratio = E::dimension::base_unit::ratio; + using positive_ratio = conditional, base_ratio>; + static constexpr std::int64_t N = E::num * E::den < 0 ? -E::num : E::num; + using pow = ratio_pow; + using type = conditional, pow>; +}; + +template +struct base_units_ratio_impl; + +template +struct base_units_ratio_impl> { + using type = ratio_multiply::type, typename base_units_ratio_impl>::type>; +}; + +template +struct base_units_ratio_impl> { + using type = exp_ratio::type; +}; + +/** + * @brief Calculates the common ratio of all the references of base units in the derived dimension + */ +template +using base_units_ratio = base_units_ratio_impl::type; + } // namespace detail /** @@ -247,16 +276,27 @@ template struct derived_dimension : downcast_child> { using recipe = derived_dimension; using coherent_unit = U; + using base_units_ratio = detail::base_units_ratio>::downcast_base_type>; }; -// same_dim -template -inline constexpr bool same_dim = false; +namespace detail { -template -inline constexpr bool same_dim = std::is_same_v; +template +struct dimension_unit_impl; -template -inline constexpr bool same_dim = std::is_same_v; +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/dimension_op.h b/src/include/units/dimension_op.h index 5a58c02f..e18649e8 100644 --- a/src/include/units/dimension_op.h +++ b/src/include/units/dimension_op.h @@ -27,6 +27,40 @@ namespace units { +// equivalent_dim +namespace detail { + +template +struct equivalent_dim_impl : std::false_type {}; + +template +struct equivalent_base_dim : std::conjunction, + same_unit_reference> {}; + +template +struct equivalent_dim_impl : std::disjunction, equivalent_base_dim> {}; + +template +struct equivalent_exp : std::false_type {}; + +template +struct equivalent_exp, exp> : equivalent_dim_impl {}; + +template +struct equivalent_derived_dim : std::false_type {}; + +template + requires (sizeof...(Es1) == sizeof...(Es2)) +struct equivalent_derived_dim, derived_dimension> : std::conjunction...> {}; + +template +struct equivalent_dim_impl : std::disjunction, equivalent_derived_dim, downcast_base_t>> {}; + +} // namespace detail + +template +inline constexpr bool equivalent_dim = detail::equivalent_dim_impl::value; + /** * @brief Unknown dimension * @@ -43,21 +77,34 @@ struct unknown_dimension : derived_dimension, scaled_un namespace detail { -template -struct downcast_dimension_impl { +template +struct check_unknown { using type = D; }; -// downcast did not find user predefined type +// downcast did not find a user predefined type template -struct downcast_dimension_impl> { +struct check_unknown> { using type = unknown_dimension; }; +template +struct downcast_dimension_impl; + +template +struct downcast_dimension_impl { + using type = D; +}; + +template +struct downcast_dimension_impl { + using type = check_unknown>::type; +}; + } // namespace detail template -using downcast_dimension = detail::downcast_dimension_impl>::type; +using downcast_dimension = detail::downcast_dimension_impl::type; // dim_invert namespace detail { diff --git a/src/include/units/physical/cgs/acceleration.h b/src/include/units/physical/cgs/acceleration.h new file mode 100644 index 00000000..0c2b488a --- /dev/null +++ b/src/include/units/physical/cgs/acceleration.h @@ -0,0 +1,45 @@ +// 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::cgs { + +struct gal : named_unit {}; +struct dim_acceleration : physical::dim_acceleration {}; + +template +using acceleration = quantity; + +inline namespace literals { + +// Gal +constexpr auto operator""Gal(unsigned long long l) { return acceleration(l); } +constexpr auto operator""Gal(long double l) { return acceleration(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/area.h b/src/include/units/physical/cgs/area.h new file mode 100644 index 00000000..4eac9f6a --- /dev/null +++ b/src/include/units/physical/cgs/area.h @@ -0,0 +1,39 @@ +// 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 +#include + +namespace units::cgs { + +using si::square_centimetre; + +struct dim_area : physical::dim_area {}; + +template +using area = quantity; + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/energy.h b/src/include/units/physical/cgs/energy.h new file mode 100644 index 00000000..413eb773 --- /dev/null +++ b/src/include/units/physical/cgs/energy.h @@ -0,0 +1,47 @@ +// 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 +#include + +namespace units::cgs { + +struct erg : named_unit {}; + +struct dim_energy : physical::dim_energy {}; + +template +using energy = quantity; + +inline namespace literals { + +// erg +constexpr auto operator""_erg(unsigned long long l) { return energy(l); } +constexpr auto operator""_erg(long double l) { return energy(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/force.h b/src/include/units/physical/cgs/force.h new file mode 100644 index 00000000..d9f9a1a7 --- /dev/null +++ b/src/include/units/physical/cgs/force.h @@ -0,0 +1,48 @@ +// 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 +#include +#include + +namespace units::cgs { + +struct dyne : named_unit {}; + +struct dim_force : physical::dim_force {}; + +template +using force = quantity; + +inline namespace literals { + +// dyn +constexpr auto operator""dyn(unsigned long long l) { return force(l); } +constexpr auto operator""dyn(long double l) { return force(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/length.h b/src/include/units/physical/cgs/length.h new file mode 100644 index 00000000..3b672ecd --- /dev/null +++ b/src/include/units/physical/cgs/length.h @@ -0,0 +1,44 @@ +// 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::cgs { + +using si::centimetre; + +struct dim_length : physical::dim_length {}; + +template +using length = quantity; + +inline namespace literals { + +using si::literals::operator"" cm; + +} + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/mass.h b/src/include/units/physical/cgs/mass.h new file mode 100644 index 00000000..c58d1ca1 --- /dev/null +++ b/src/include/units/physical/cgs/mass.h @@ -0,0 +1,44 @@ +// 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::cgs { + +using si::gram; + +struct dim_mass : physical::dim_mass {}; + +template +using mass = quantity; + +inline namespace literals { + +using si::literals::operator"" g; + +} + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/power.h b/src/include/units/physical/cgs/power.h new file mode 100644 index 00000000..5a813cb2 --- /dev/null +++ b/src/include/units/physical/cgs/power.h @@ -0,0 +1,47 @@ +// 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 +#include + +namespace units::cgs { + +struct erg_per_second : unit {}; + +struct dim_power : physical::dim_power {}; + +template +using power = quantity; + +inline namespace literals { + +// ergps +constexpr auto operator""_ergps(unsigned long long l) { return power(l); } +constexpr auto operator""_ergps(long double l) { return power(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/pressure.h b/src/include/units/physical/cgs/pressure.h new file mode 100644 index 00000000..0e3b98d4 --- /dev/null +++ b/src/include/units/physical/cgs/pressure.h @@ -0,0 +1,48 @@ +// 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 +#include +#include + +namespace units::cgs { + +struct barye : named_unit {}; + +struct dim_pressure : physical::dim_pressure {}; + +template +using pressure = quantity; + +inline namespace literals { + +// Ba +constexpr auto operator""Ba(unsigned long long l) { return pressure(l); } +constexpr auto operator""Ba(long double l) { return pressure(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/time.h b/src/include/units/physical/cgs/time.h new file mode 100644 index 00000000..c678bc79 --- /dev/null +++ b/src/include/units/physical/cgs/time.h @@ -0,0 +1,42 @@ +// 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::cgs { + +using si::second; + +using si::dim_time; +using si::time; + +inline namespace literals { + +using si::literals::operator"" s; + +} + +} // namespace units::cgs diff --git a/src/include/units/physical/cgs/velocity.h b/src/include/units/physical/cgs/velocity.h new file mode 100644 index 00000000..8adbaa58 --- /dev/null +++ b/src/include/units/physical/cgs/velocity.h @@ -0,0 +1,46 @@ +// 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 +#include + +namespace units::cgs { + +struct centimetre_per_second : unit {}; +struct dim_velocity : physical::dim_velocity {}; + +template +using velocity = quantity; + +inline namespace literals { + +// cmps +constexpr auto operator"" cmps(unsigned long long l) { return velocity(l); } +constexpr auto operator"" cmps(long double l) { return velocity(l); } + +} // namespace literals + +} // namespace units::cgs diff --git a/src/include/units/physical/si/mass.h b/src/include/units/physical/si/mass.h index cd3fc4e8..c6c59d15 100644 --- a/src/include/units/physical/si/mass.h +++ b/src/include/units/physical/si/mass.h @@ -24,6 +24,7 @@ #include #include +#include namespace units::si { diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 19796b57..7bfa7375 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -44,7 +44,7 @@ concept Quantity = detail::is_quantity; // QuantityOf template -concept QuantityOf = Quantity && Dimension && same_dim; +concept QuantityOf = Quantity && Dimension && equivalent_dim; // Scalar template @@ -76,9 +76,23 @@ struct common_quantity_impl, quantity, Rep> { using type = quantity>, Rep>; }; +template + requires same_unit_reference, dimension_unit>::value +struct common_quantity_impl, quantity, Rep> { + using type = quantity>, Rep>; +}; + +template +struct common_quantity_impl, quantity, Rep> { + using ratio1 = ratio_multiply; + using ratio2 = ratio_multiply; + using type = quantity>, Rep>; +}; + } // namespace detail template> + requires equivalent_dim using common_quantity = detail::common_quantity_impl::type; // quantity_cast @@ -130,6 +144,27 @@ struct quantity_cast_impl { } }; +template +struct cast_ratio; + +template +struct cast_ratio { + using type = ratio_divide; +}; + +template + requires same_unit_reference::value +struct cast_ratio { + using type = ratio_divide; +}; + +template +struct cast_ratio { + using from_ratio = ratio_multiply; + using to_ratio = ratio_multiply; + using type = ratio_divide; +}; + } // namespace detail /** @@ -150,7 +185,7 @@ template requires QuantityOf && detail::basic_arithmetic> { - using c_ratio = ratio_divide; + using c_ratio = detail::cast_ratio::type; using c_rep = std::common_type_t; using ret_unit = downcast_unit; using ret = quantity; @@ -172,7 +207,7 @@ template */ template [[nodiscard]] constexpr auto quantity_cast(const quantity& q) - requires same_dim + requires equivalent_dim { return quantity_cast>(q); } @@ -260,7 +295,7 @@ public: constexpr explicit quantity(const Value& v) : value_{static_cast(v)} {} template - requires same_dim && + requires equivalent_dim && detail::safe_convertible && detail::safe_divisible constexpr quantity(const Q2& q) : value_{quantity_cast(q).count()} {} @@ -446,7 +481,7 @@ template template [[nodiscard]] constexpr Scalar AUTO operator*(const quantity& lhs, const quantity& rhs) - requires same_dim>&& detail::basic_arithmetic + requires equivalent_dim> && detail::basic_arithmetic { using common_rep = decltype(lhs.count() * rhs.count()); using ratio = ratio_multiply; @@ -455,14 +490,14 @@ template [[nodiscard]] constexpr Quantity AUTO operator*(const quantity& lhs, const quantity& rhs) - requires (!same_dim>) && + requires (!equivalent_dim>) && // TODO equivalent_derived_dim? (treat_as_floating_point || (std::ratio_multiply::den == 1)) && detail::basic_arithmetic { using dim = dimension_multiply; - using ratio1 = ratio_divide; - using ratio2 = ratio_divide; + using ratio1 = ratio_divide::ratio>; + using ratio2 = ratio_divide::ratio>; using ratio = ratio_multiply; using unit = downcast_unit; using common_rep = decltype(lhs.count() * rhs.count()); @@ -495,29 +530,29 @@ template return ret(q.count() / v); } -template -[[nodiscard]] constexpr Scalar AUTO operator/(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic +template +[[nodiscard]] constexpr Scalar AUTO operator/(const quantity& lhs, const quantity& rhs) + requires detail::basic_arithmetic && equivalent_dim { Expects(rhs != std::remove_cvref_t(0)); using common_rep = decltype(lhs.count() / rhs.count()); - using cq = common_quantity, quantity, common_rep>; + using cq = common_quantity, quantity, common_rep>; return cq(lhs).count() / cq(rhs).count(); } template [[nodiscard]] constexpr Quantity AUTO operator/(const quantity& lhs, const quantity& rhs) - requires (treat_as_floating_point || - (ratio_divide::den == 1)) && - detail::basic_arithmetic + requires detail::basic_arithmetic && (!equivalent_dim) && // TODO equivalent_derived_dim? + (treat_as_floating_point || + (ratio_divide::den == 1)) { Expects(rhs != std::remove_cvref_t(0)); using common_rep = decltype(lhs.count() / rhs.count()); using dim = dimension_divide; - using ratio1 = ratio_divide; - using ratio2 = ratio_divide; + using ratio1 = ratio_divide::ratio>; + using ratio2 = ratio_divide::ratio>; using ratio = ratio_divide; using unit = downcast_unit; using ret = quantity; @@ -546,51 +581,57 @@ template return ret(ret(lhs).count() % ret(rhs).count()); } -template -[[nodiscard]] constexpr bool operator==(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator==(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::equality_comparable_with { - using cq = common_quantity, quantity>; + using cq = common_quantity, quantity>; return cq(lhs).count() == cq(rhs).count(); } -template -[[nodiscard]] constexpr bool operator!=(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator!=(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::equality_comparable_with { return !(lhs == rhs); } -template -[[nodiscard]] constexpr bool operator<(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator<(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::totally_ordered_with { - using cq = common_quantity, quantity>; + using cq = common_quantity, quantity>; return cq(lhs).count() < cq(rhs).count(); } -template -[[nodiscard]] constexpr bool operator<=(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator<=(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::totally_ordered_with { return !(rhs < lhs); } -template -[[nodiscard]] constexpr bool operator>(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator>(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::totally_ordered_with { return rhs < lhs; } -template -[[nodiscard]] constexpr bool operator>=(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && +template +[[nodiscard]] constexpr bool operator>=(const quantity& lhs, const quantity& rhs) + requires equivalent_dim && + detail::basic_arithmetic && std::totally_ordered_with { return !(lhs < rhs); diff --git a/src/include/units/unit.h b/src/include/units/unit.h index 20618c74..2f9a3254 100644 --- a/src/include/units/unit.h +++ b/src/include/units/unit.h @@ -54,7 +54,10 @@ struct scaled_unit : downcast_base> { }; template -using downcast_unit = downcast>; +using downcast_unit = downcast::reference, R>>; + +template +struct same_unit_reference : std::is_same {}; /** * @brief A starting point for a new hierarchy of units @@ -146,7 +149,7 @@ template concept UnitOf = Unit && Dimension && - std::same_as; + std::same_as::reference>; namespace detail { diff --git a/test/unit_test/static/CMakeLists.txt b/test/unit_test/static/CMakeLists.txt index 2447b832..4b39dc76 100644 --- a/test/unit_test/static/CMakeLists.txt +++ b/test/unit_test/static/CMakeLists.txt @@ -21,7 +21,7 @@ # SOFTWARE. add_library(unit_tests_static -# cgs_test.cpp + cgs_test.cpp custom_unit_test.cpp data_test.cpp dimension_op_test.cpp diff --git a/test/unit_test/static/cgs_test.cpp b/test/unit_test/static/cgs_test.cpp index 341126f2..07348f4e 100644 --- a/test/unit_test/static/cgs_test.cpp +++ b/test/unit_test/static/cgs_test.cpp @@ -20,56 +20,87 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include -#include -#include -#include -namespace cgs { - - using units::centimetre; - using units::gram; - using units::second; - struct centimetre_per_second : units::deduced_derived_unit {}; - struct gal : units::named_deduced_derived_unit {}; - struct dyne : units::named_deduced_derived_unit {}; - struct erg : units::named_deduced_derived_unit {}; - struct ergps : units::named_deduced_derived_unit {}; // TODO make it work for erg and non-named - struct barye : units::named_deduced_derived_unit {}; - - - inline namespace literals { - - using namespace units::literals; - - constexpr auto operator""cmps(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""cmps(long double l) { return units::quantity(l); } - constexpr auto operator""Gal(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""Gal(long double l) { return units::quantity(l); } - constexpr auto operator""dyn(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""dyn(long double l) { return units::quantity(l); } - constexpr auto operator""_erg(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""_erg(long double l) { return units::quantity(l); } - constexpr auto operator""_ergps(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""_ergps(long double l) { return units::quantity(l); } - constexpr auto operator""Ba(unsigned long long l) { return units::quantity(l); } - constexpr auto operator""Ba(long double l) { return units::quantity(l); } - - } // namespace literals - -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace { - using namespace cgs::literals; +using namespace units; - static_assert(100cm == 1m); - static_assert(1'000g == 1kg); - static_assert(100cmps == 1mps); - static_assert(100Gal == 1mps_sq); - static_assert(100'000dyn == 1N); - static_assert(10'000'000_erg == 1_J); - static_assert(10'000'000_ergps == 1W); - static_assert(10Ba == 1Pa); +static_assert(cgs::length(100) == si::length(1)); +static_assert(cgs::mass(1'000) == si::mass(1)); +static_assert(cgs::time(1) == si::time(1)); +static_assert(cgs::velocity(100) == si::velocity(1)); +static_assert(cgs::acceleration(100) == si::acceleration(1)); +static_assert(cgs::force(100'000) == si::force(1)); +static_assert(cgs::energy(10'000'000) == si::energy(1)); +static_assert(cgs::power(10'000'000) == si::power(1)); +static_assert(cgs::pressure(10) == si::pressure(1)); -} \ No newline at end of file +namespace si_test { + +using namespace units::si::literals; + +static_assert(cgs::length(100) == 1m); +static_assert(cgs::mass(1'000) == 1kg); +static_assert(cgs::time(1) == 1s); +static_assert(cgs::velocity(100) == 1mps); +static_assert(cgs::acceleration(100) == 1mps_sq); +static_assert(cgs::force(100'000) == 1N); +static_assert(cgs::energy(10'000'000) == 1_J); +static_assert(cgs::power(10'000'000) == 1W); +static_assert(cgs::pressure(10) == 1Pa); + +} + +namespace cgs_test { + +using namespace units::cgs::literals; + +static_assert(100cm == si::length(1)); +static_assert(1'000g == si::mass(1)); +static_assert(1s == si::time(1)); +static_assert(100cmps == si::velocity(1)); +static_assert(100Gal == si::acceleration(1)); +static_assert(100'000dyn == si::force(1)); +static_assert(10'000'000_erg == si::energy(1)); +static_assert(10'000'000_ergps == si::power(1)); +static_assert(10Ba == si::pressure(1)); + +} + +namespace both_test { + +using namespace units::si::literals; +using namespace units::cgs::literals; + +static_assert(100cm == 1m); +static_assert(1'000g == 1kg); +static_assert(1s == 1s); +static_assert(100cmps == 1mps); +static_assert(100Gal == 1mps_sq); +static_assert(100'000dyn == 1N); +static_assert(10'000'000_erg == 1_J); +static_assert(10'000'000_ergps == 1W); +static_assert(10Ba == quantity_cast(1Pa)); + +} + +}