// 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 { /** * @brief Computes the value of a quantity raised to the power `N` * * Both the quantity value and its dimension are the base of the operation. * * @tparam Num Exponent numerator * @tparam Den Exponent denominator * @param q Quantity being the base of the operation * @return Quantity The result of computation */ template requires detail::non_zero [[nodiscard]] inline auto pow(const Q& q) noexcept requires requires { std::pow(q.number(), 1.0); } { using rep = TYPENAME Q::rep; if constexpr (Num == 0) { return rep(1); } else { using dim = dimension_pow; using unit = downcast_unit(Q::unit::ratio)>; return quantity( static_cast(std::pow(q.number(), static_cast(Num) / static_cast(Den)))); } } /** * @brief Computes the square root of a quantity * * Both the quantity value and its dimension are the base of the operation. * * @param q Quantity being the base of the operation * @return Quantity The result of computation */ template [[nodiscard]] inline Quantity auto sqrt(const Q& q) noexcept requires requires { std::sqrt(q.number()); } { using dim = dimension_pow; using unit = downcast_unit; using rep = TYPENAME Q::rep; return quantity(static_cast(std::sqrt(q.number()))); } /** * @brief Computes the cubic root of a quantity * * Both the quantity value and its dimension are the base of the operation. * * @param q Quantity being the base of the operation * @return Quantity The result of computation */ template [[nodiscard]] inline Quantity auto cbrt(const Q& q) noexcept requires requires { std::cbrt(q.number()); } { using dim = dimension_pow; using unit = downcast_unit; using rep = TYPENAME Q::rep; return quantity(static_cast(std::cbrt(q.number()))); } /** * @brief Computes Euler's raised to the given power * * @note Such an operation has sense only for a dimensionless quantity. * * @param q Quantity being the base of the operation * @return Quantity The value of the same quantity type */ template [[nodiscard]] inline dimensionless exp(const dimensionless& q) { return quantity_cast(dimensionless(std::exp(quantity_cast(q).number()))); } /** * @brief Computes the absolute value of a quantity * * @param q Quantity being the base of the operation * @return Quantity The absolute value of a provided quantity */ template [[nodiscard]] inline quantity abs(const quantity& q) noexcept requires requires { std::abs(q.number()); } { return quantity(std::abs(q.number())); } /** * @brief Returns the epsilon of the quantity * * The returned value is defined by a std::numeric_limits::epsilon(). * * @tparam Q Quantity type being the base of the operation * @return Quantity The epsilon value for quantity's representation type */ template requires requires { std::numeric_limits::epsilon(); } [[nodiscard]] constexpr Quantity auto epsilon() noexcept { return Q(std::numeric_limits::epsilon()); } } // namespace units