// 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 { /** * @brief Unknown dimension * * Sometimes a temporary partial result of a complex calculation may not result in a predefined * dimension. In such a case an `unknown_dimension` is created with a coherent unit of `unknown_coherent_unit` * and ratio(1). * * @tparam Es the list of exponents of ingredient dimensions */ template struct unknown_dimension : derived_dimension, unknown_coherent_unit, Es...> {}; namespace detail { template struct check_unknown { using type = D; }; // downcast did not find a user predefined type template 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 = TYPENAME check_unknown>::type; }; } // namespace detail template using downcast_dimension = TYPENAME detail::downcast_dimension_impl::type; // dim_invert namespace detail { template struct dim_invert_impl; template struct dim_invert_impl { using type = downcast_dimension>>; }; template struct dim_invert_impl>> { using type = D; }; template struct dim_invert_impl> { using type = downcast_dimension...>>; }; template struct dim_invert_impl : dim_invert_impl> { }; } // namespace detail template using dim_invert = TYPENAME detail::dim_invert_impl::type; // dimension_multiply namespace detail { template struct to_dimension; template struct to_dimension> { using type = derived_dimension_base; }; template struct to_dimension>> { using type = D; }; /** * @brief Merges 2 sorted derived dimensions into one units::derived_dimension_base * * A result of a dimensional calculation may result with many exponents of the same base dimension orginated * from different parts of the equation. As the exponents lists of both operands it is enough to merge them * into one list and consolidate duplicates. Also it is possible that final exponents list will contain only * one element being a base dimension with exponent 1. In such a case the final dimension should be the base * dimension itself. */ template using merge_dimension = TYPENAME to_dimension>::type>::type; template struct dimension_multiply_impl; template struct dimension_multiply_impl { using type = downcast_dimension>, derived_dimension_base>>>; }; template struct dimension_multiply_impl { using type = downcast_dimension>, typename D2::downcast_base_type>>; }; template struct dimension_multiply_impl { using type = TYPENAME dimension_multiply_impl::type; }; template struct dimension_multiply_impl { using type = downcast_dimension>; }; } // namespace detail template using dimension_multiply = TYPENAME detail::dimension_multiply_impl::type; template using dimension_divide = TYPENAME detail::dimension_multiply_impl>::type; // dimension_sqrt namespace detail { template struct dimension_sqrt_impl; template struct dimension_sqrt_impl { using type = downcast_dimension>>; }; template struct dimension_sqrt_impl>> { using type = D; }; template struct dimension_sqrt_impl { using type = TYPENAME dimension_sqrt_impl::type; }; template struct dimension_sqrt_impl> { using type = downcast_dimension...>>; }; } // namespace detail template using dimension_sqrt = TYPENAME detail::dimension_sqrt_impl::type; // dimension_pow namespace detail { template struct dimension_pow_impl; template struct dimension_pow_impl { using type = downcast_dimension>>; }; template struct dimension_pow_impl { using type = D; }; template struct dimension_pow_impl>, N> { using type = D; }; template struct dimension_pow_impl { using type = TYPENAME dimension_pow_impl, N>::type; }; template struct dimension_pow_impl, N> { using type = downcast_dimension...>>; }; } // namespace detail template using dimension_pow = TYPENAME detail::dimension_pow_impl::type; } // namespace units