// 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. #include // IWYU pragma: keep #include #include namespace { using namespace mp_units; using namespace mp_units::si::unit_symbols; using namespace mp_units::international::unit_symbols; template [[nodiscard]] consteval bool compare(T1 v1, T2 v2, Ts... vs) { return is_same_v && v1 == v2 && (... && (v1 == vs)); } #if __cpp_lib_constexpr_cmath || MP_UNITS_COMP_GCC template concept invalid_fma = requires { requires !requires { fma(2 * m, One, 2 * s); }; requires !requires { fma(2 * m, One, 2 * cm); }; }; static_assert(invalid_fma<1 * one>); static_assert(compare(fma(2.0 * s, 3.0 * Hz, 1.0 * one), 7.0 * one)); static_assert(compare(fma(2.0 * one, 3.0 * m, 1.0 * m), 7.0 * m)); static_assert(compare(fma(2.0 * m, 3.0 * one, 1.0 * m), 7.0 * m)); static_assert(compare(fma(2 * m, 3.0f * m, 1.0 * m2), 7.0 * m2)); static_assert(compare(fma(isq::width(2.0 * m), 2.0 * one, isq::height(3.0 * m)), isq::length(7.0 * m))); static_assert(compare(fmod(4.0 * km, 3.0 * km), 1.0 * km)); static_assert(compare(fmod(-4.0 * km, 3.0 * km), -1.0 * km)); static_assert(compare(fmod(9.0 * km, -3.0 * km), 0.0 * km)); static_assert(compare(fmod(9.5 * km, -2000 * m), 1500.0 * m)); static_assert(compare(fmod(3 * km, 2 * km), 1.0 * km)); static_assert(compare(fmod(4 * km, 2.5f * km), 1.5 * km)); static_assert(compare(remainder(4.0 * km, 3.0 * km), 1.0 * km)); static_assert(compare(remainder(-4.0 * km, 3.0 * km), -1.0 * km)); static_assert(compare(remainder(9.0 * km, -3.0 * km), 0.0 * km)); static_assert(compare(remainder(9.5 * km, -2000 * m), -500.0 * m)); static_assert(compare(remainder(3 * km, 2 * km), -1.0 * km)); static_assert(compare(remainder(4 * km, 2.75f * km), 1.25 * km)); static_assert(compare(pow<0>(2 * m), 1 * one)); static_assert(compare(pow<1>(2 * m), 2 * m)); static_assert(compare(pow<2>(2 * m), 4 * pow<2>(m), 4 * m2)); static_assert(compare(pow<2>(2 * km), 4 * pow<2>(km), 4 * square(km))); static_assert(compare(pow<2>(2 * ft), 4 * pow<2>(ft), 4 * square(ft))); static_assert(isfinite(2 * m)); static_assert(isfinite(2.0 * one)); static_assert(!isfinite(std::numeric_limits::quiet_NaN() * one)); static_assert(!isfinite(std::numeric_limits::infinity() * km)); static_assert(!isinf(2 * m)); static_assert(!isinf(2.0 * one)); static_assert(isinf(std::numeric_limits::infinity() * one)); static_assert(!isnan(2 * m)); static_assert(!isnan(std::numeric_limits::infinity() * one)); static_assert(isnan(std::numeric_limits::quiet_NaN() * m)); static_assert(compare(sqrt(4 * m2), 2 * m)); static_assert(compare(sqrt(4 * square(km)), 2 * km)); static_assert(compare(sqrt(4 * square(ft)), 2 * ft)); static_assert(compare(cbrt(8 * m3), 2 * m)); static_assert(compare(cbrt(8 * cubic(km)), 2 * km)); static_assert(compare(cbrt(8 * cubic(ft)), 2 * ft)); static_assert(compare(pow<1, 4>(4 * m2 * (4 * m2)), 2 * m)); static_assert(compare(pow<1, 4>(4 * square(km) * (4 * square(km))), 2 * km)); static_assert(compare(pow<1, 4>(4 * square(ft) * (4 * square(ft))), 2 * ft)); static_assert(compare(pow<1, 4>(4. * m2), std::sqrt(2.) * sqrt(m))); static_assert(compare(pow<1, 4>(4. * square(km)), std::sqrt(2.) * sqrt(km))); static_assert(compare(pow<1, 4>(4. * square(ft)), std::sqrt(2.) * sqrt(ft))); static_assert(compare(pow<0>(2 * isq::length[m]), 1 * dimensionless[one])); static_assert(compare(pow<1>(2 * isq::length[m]), 2 * isq::length[m])); static_assert(compare(pow<2>(2 * isq::length[m]), 4 * pow<2>(isq::length)[pow<2>(m)], 4 * isq::area[m2])); static_assert(compare(pow<2>(2 * isq::length[km]), 4 * pow<2>(isq::length)[pow<2>(km)], 4 * isq::area[square(km)])); static_assert(compare(pow<2>(2 * isq::length[ft]), 4 * pow<2>(isq::length)[pow<2>(ft)], 4 * isq::area[square(ft)])); static_assert(compare(sqrt(4 * isq::area[m2]), 2 * pow<1, 2>(isq::area)[m], 2 * isq::length[m])); static_assert(compare(sqrt(4 * isq::area[square(km)]), 2 * pow<1, 2>(isq::area)[km], 2 * isq::length[km])); static_assert(compare(sqrt(4 * isq::area[square(ft)]), 2 * pow<1, 2>(isq::area)[ft], 2 * isq::length[ft])); static_assert(compare(cbrt(8 * isq::volume[m3]), 2 * pow<1, 3>(isq::volume)[m], 2 * isq::length[m])); static_assert(compare(cbrt(8 * isq::volume[cubic(km)]), 2 * pow<1, 3>(isq::volume)[km], 2 * isq::length[km])); static_assert(compare(cbrt(8 * isq::volume[cubic(ft)]), 2 * pow<1, 3>(isq::volume)[ft], 2 * isq::length[ft])); static_assert(compare(pow<1, 4>(4 * isq::area[m2] * (4 * isq::area[m2])), 2 * pow<1, 2>(isq::area)[m], 2 * isq::length[m])); static_assert(compare(pow<1, 4>(4 * isq::area[square(km)] * (4 * isq::area[square(km)])), 2 * pow<1, 2>(isq::area)[km], 2 * isq::length[km])); static_assert(compare(pow<1, 4>(4 * isq::area[square(ft)] * (4 * isq::area[square(ft)])), 2 * pow<1, 2>(isq::area)[ft], 2 * isq::length[ft])); static_assert(compare(pow<1, 4>(4. * isq::area[m2]), sqrt(2.) * pow<1, 4>(isq::area)[sqrt(m)], std::sqrt(2.) * sqrt(isq::length[m]))); static_assert(compare(pow<1, 4>(4. * isq::area[square(km)]), sqrt(2.) * pow<1, 4>(isq::area)[sqrt(km)], std::sqrt(2.) * sqrt(isq::length[km]))); static_assert(compare(pow<1, 4>(4. * isq::area[square(ft)]), sqrt(2.) * pow<1, 4>(isq::area)[sqrt(ft)], std::sqrt(2.) * sqrt(isq::length[ft]))); // floor // integral types static_assert(compare(floor(1 * s), 1 * s)); static_assert(compare(floor(1000 * ms), 1 * s)); static_assert(compare(floor(1001 * ms), 1 * s)); static_assert(compare(floor(1999 * ms), 1 * s)); static_assert(compare(floor(-1000 * ms), -1 * s)); static_assert(compare(floor(-999 * ms), -1 * s)); static_assert(compare(floor(1 * isq::time[s]), 1 * isq::time[s])); static_assert(compare(floor(1000 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(floor(1001 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(floor(1999 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(floor(-1000 * isq::time[ms]), -1 * isq::time[s])); static_assert(compare(floor(-999 * isq::time[ms]), -1 * isq::time[s])); // floating-point static_assert(compare(floor(1.3 * s), 1. * s)); static_assert(compare(floor(-1.3 * s), -2. * s)); static_assert(compare(floor(1000. * ms), 1. * s)); static_assert(compare(floor(1001. * ms), 1. * s)); static_assert(compare(floor(1999. * ms), 1. * s)); static_assert(compare(floor(-1000. * ms), -1. * s)); static_assert(compare(floor(-999. * ms), -1. * s)); static_assert(compare(floor(1.3 * isq::time[s]), 1. * isq::time[s])); static_assert(compare(floor(-1.3 * isq::time[s]), -2. * isq::time[s])); static_assert(compare(floor(1000. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(floor(1001. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(floor(1999. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(floor(-1000. * isq::time[ms]), -1. * isq::time[s])); static_assert(compare(floor(-999. * isq::time[ms]), -1. * isq::time[s])); // ceil // integral types static_assert(compare(ceil(1 * s), 1 * s)); static_assert(compare(ceil(1000 * ms), 1 * s)); static_assert(compare(ceil(1001 * ms), 2 * s)); static_assert(compare(ceil(1999 * ms), 2 * s)); static_assert(compare(ceil(-1000 * ms), -1 * s)); static_assert(compare(ceil(-999 * ms), 0 * s)); static_assert(compare(ceil(1 * isq::time[s]), 1 * isq::time[s])); static_assert(compare(ceil(1000 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(ceil(1001 * isq::time[ms]), 2 * isq::time[s])); static_assert(compare(ceil(1999 * isq::time[ms]), 2 * isq::time[s])); static_assert(compare(ceil(-1000 * isq::time[ms]), -1 * isq::time[s])); static_assert(compare(ceil(-999 * isq::time[ms]), 0 * isq::time[s])); // floating-point static_assert(compare(ceil(1.3 * s), 2. * s)); static_assert(compare(ceil(-1.3 * s), -1. * s)); static_assert(compare(ceil(1000. * ms), 1. * s)); static_assert(compare(ceil(1001. * ms), 2. * s)); static_assert(compare(ceil(1999. * ms), 2. * s)); static_assert(compare(ceil(-1000. * ms), -1. * s)); static_assert(compare(ceil(-999. * ms), 0. * s)); static_assert(compare(ceil(1.3 * isq::time[s]), 2. * isq::time[s])); static_assert(compare(ceil(-1.3 * isq::time[s]), -1. * isq::time[s])); static_assert(compare(ceil(1000. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(ceil(1001. * isq::time[ms]), 2. * isq::time[s])); static_assert(compare(ceil(1999. * isq::time[ms]), 2. * isq::time[s])); static_assert(compare(ceil(-1000. * isq::time[ms]), -1. * isq::time[s])); static_assert(compare(ceil(-999. * isq::time[ms]), 0. * isq::time[s])); // round // integral types static_assert(compare(round(1 * s), 1 * s)); static_assert(compare(round(1000 * ms), 1 * s)); static_assert(compare(round(1001 * ms), 1 * s)); static_assert(compare(round(1499 * ms), 1 * s)); static_assert(compare(round(1500 * ms), 2 * s)); static_assert(compare(round(1999 * ms), 2 * s)); static_assert(compare(round(-1000 * ms), -1 * s)); static_assert(compare(round(-1001 * ms), -1 * s)); static_assert(compare(round(-1499 * ms), -1 * s)); static_assert(compare(round(-1500 * ms), -2 * s)); static_assert(compare(round(-1999 * ms), -2 * s)); static_assert(compare(round(1 * isq::time[s]), 1 * isq::time[s])); static_assert(compare(round(1000 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(round(1001 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(round(1499 * isq::time[ms]), 1 * isq::time[s])); static_assert(compare(round(1500 * isq::time[ms]), 2 * isq::time[s])); static_assert(compare(round(1999 * isq::time[ms]), 2 * isq::time[s])); static_assert(compare(round(-1000 * isq::time[ms]), -1 * isq::time[s])); static_assert(compare(round(-1001 * isq::time[ms]), -1 * isq::time[s])); static_assert(compare(round(-1499 * isq::time[ms]), -1 * isq::time[s])); static_assert(compare(round(-1500 * isq::time[ms]), -2 * isq::time[s])); static_assert(compare(round(-1999 * isq::time[ms]), -2 * isq::time[s])); // floating-point static_assert(compare(round(1.3 * s), 1. * s)); static_assert(compare(round(-1.3 * s), -1. * s)); static_assert(compare(round(1000. * ms), 1. * s)); static_assert(compare(round(1001. * ms), 1. * s)); static_assert(compare(round(1499. * ms), 1. * s)); static_assert(compare(round(1500. * ms), 2. * s)); static_assert(compare(round(1999. * ms), 2. * s)); static_assert(compare(round(-1000. * ms), -1. * s)); static_assert(compare(round(-1001. * ms), -1. * s)); static_assert(compare(round(-1499. * ms), -1. * s)); static_assert(compare(round(-1500. * ms), -2. * s)); static_assert(compare(round(-1999. * ms), -2. * s)); static_assert(compare(round(1.3 * isq::time[s]), 1. * isq::time[s])); static_assert(compare(round(-1.3 * isq::time[s]), -1. * isq::time[s])); static_assert(compare(round(1000. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(round(1001. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(round(1499. * isq::time[ms]), 1. * isq::time[s])); static_assert(compare(round(1500. * isq::time[ms]), 2. * isq::time[s])); static_assert(compare(round(1999. * isq::time[ms]), 2. * isq::time[s])); static_assert(compare(round(-1000. * isq::time[ms]), -1. * isq::time[s])); static_assert(compare(round(-1001. * isq::time[ms]), -1. * isq::time[s])); static_assert(compare(round(-1499. * isq::time[ms]), -1. * isq::time[s])); static_assert(compare(round(-1500. * isq::time[ms]), -2. * isq::time[s])); static_assert(compare(round(-1999. * isq::time[ms]), -2. * isq::time[s])); #endif // non-truncating static_assert(compare(inverse(250 * Hz), 4000 * us)); static_assert(compare(inverse(250 * kHz), 4 * us)); static_assert(compare(inverse(250 * uHz), 4 * ks)); // truncating static_assert(compare(inverse(1 * kHz), 0 * s)); // floating-point representation does not truncate static_assert(compare(inverse(1. * kHz), 0.001 * s)); // check if constraints work properly for a derived unit of a narrowed kind static_assert(compare(inverse(1 * s), 1 * Hz)); } // namespace