mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 20:34:26 +02:00
Merge branch 'master' into chiphogg/mod#509
This commit is contained in:
@@ -24,13 +24,14 @@ find_package(Catch2 3 REQUIRED)
|
||||
|
||||
add_executable(
|
||||
unit_tests_runtime
|
||||
atomic_test.cpp
|
||||
cartesian_vector_test.cpp
|
||||
distribution_test.cpp
|
||||
fixed_string_test.cpp
|
||||
fmt_test.cpp
|
||||
math_test.cpp
|
||||
atomic_test.cpp
|
||||
truncation_test.cpp
|
||||
quantity_test.cpp
|
||||
truncation_test.cpp
|
||||
)
|
||||
if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
target_compile_definitions(unit_tests_runtime PUBLIC ${projectPrefix}MODULES)
|
||||
|
381
test/runtime/cartesian_vector_test.cpp
Normal file
381
test/runtime/cartesian_vector_test.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
// 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 "almost_equals.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#ifdef MP_UNITS_IMPORT_STD
|
||||
import std;
|
||||
#else
|
||||
#include <sstream>
|
||||
#endif
|
||||
#ifdef MP_UNITS_MODULES
|
||||
import mp_units;
|
||||
#else
|
||||
#include <mp-units/cartesian_vector.h>
|
||||
#endif
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
TEST_CASE("cartesian_vector operations", "[vector]")
|
||||
{
|
||||
SECTION("cartesian_vector initialization and access")
|
||||
{
|
||||
SECTION("one argument")
|
||||
{
|
||||
cartesian_vector v{1.0};
|
||||
REQUIRE(v[0] == 1.0);
|
||||
REQUIRE(v[1] == 0);
|
||||
REQUIRE(v[2] == 0);
|
||||
}
|
||||
|
||||
SECTION("two arguments")
|
||||
{
|
||||
cartesian_vector v{1.0, 2.0};
|
||||
REQUIRE(v[0] == 1.0);
|
||||
REQUIRE(v[1] == 2.0);
|
||||
REQUIRE(v[2] == 0);
|
||||
}
|
||||
|
||||
SECTION("all arguments")
|
||||
{
|
||||
cartesian_vector v{1.0, 2.0, 3.0};
|
||||
REQUIRE(v[0] == 1.0);
|
||||
REQUIRE(v[1] == 2.0);
|
||||
REQUIRE(v[2] == 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("convertibility")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
|
||||
SECTION("construction")
|
||||
{
|
||||
cartesian_vector v2 = v1;
|
||||
REQUIRE(v2[0] == 1.0);
|
||||
REQUIRE(v2[1] == 2.0);
|
||||
REQUIRE(v2[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("assignment")
|
||||
{
|
||||
cartesian_vector v2{3.0, 2.0, 1.0};
|
||||
v2 = v1;
|
||||
REQUIRE(v2[0] == 1.0);
|
||||
REQUIRE(v2[1] == 2.0);
|
||||
REQUIRE(v2[2] == 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector addition")
|
||||
{
|
||||
SECTION("double + double")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
cartesian_vector result = v1 + v2;
|
||||
REQUIRE(result[0] == 5.0);
|
||||
REQUIRE(result[1] == 7.0);
|
||||
REQUIRE(result[2] == 9.0);
|
||||
}
|
||||
|
||||
SECTION("double + int")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
cartesian_vector result = v1 + v2;
|
||||
REQUIRE(result[0] == 5.0);
|
||||
REQUIRE(result[1] == 7.0);
|
||||
REQUIRE(result[2] == 9.0);
|
||||
}
|
||||
|
||||
SECTION("int + double")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
cartesian_vector result = v1 + v2;
|
||||
REQUIRE(result[0] == 5.0);
|
||||
REQUIRE(result[1] == 7.0);
|
||||
REQUIRE(result[2] == 9.0);
|
||||
}
|
||||
|
||||
SECTION("int + int")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
cartesian_vector result = v1 + v2;
|
||||
REQUIRE(result[0] == 5);
|
||||
REQUIRE(result[1] == 7);
|
||||
REQUIRE(result[2] == 9);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector subtraction")
|
||||
{
|
||||
SECTION("double - double")
|
||||
{
|
||||
cartesian_vector v1{4.0, 5.0, 6.0};
|
||||
cartesian_vector v2{1.0, 2.0, 3.0};
|
||||
cartesian_vector result = v1 - v2;
|
||||
REQUIRE(result[0] == 3.0);
|
||||
REQUIRE(result[1] == 3.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("double - int")
|
||||
{
|
||||
cartesian_vector v1{4.0, 5.0, 6.0};
|
||||
cartesian_vector v2{1, 2, 3};
|
||||
cartesian_vector result = v1 - v2;
|
||||
REQUIRE(result[0] == 3.0);
|
||||
REQUIRE(result[1] == 3.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("int - double")
|
||||
{
|
||||
cartesian_vector v1{4, 5, 6};
|
||||
cartesian_vector v2{1.0, 2.0, 3.0};
|
||||
cartesian_vector result = v1 - v2;
|
||||
REQUIRE(result[0] == 3.0);
|
||||
REQUIRE(result[1] == 3.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("int - int")
|
||||
{
|
||||
cartesian_vector v1{4, 5, 6};
|
||||
cartesian_vector v2{1, 2, 3};
|
||||
cartesian_vector result = v1 - v2;
|
||||
REQUIRE(result[0] == 3);
|
||||
REQUIRE(result[1] == 3);
|
||||
REQUIRE(result[2] == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector scalar multiplication")
|
||||
{
|
||||
SECTION("double * double")
|
||||
{
|
||||
cartesian_vector v{1.0, 2.0, 3.0};
|
||||
cartesian_vector result = v * 2.0;
|
||||
REQUIRE(result[0] == 2.0);
|
||||
REQUIRE(result[1] == 4.0);
|
||||
REQUIRE(result[2] == 6.0);
|
||||
}
|
||||
|
||||
SECTION("double * int")
|
||||
{
|
||||
cartesian_vector v{1.0, 2.0, 3.0};
|
||||
cartesian_vector result = v * 2;
|
||||
REQUIRE(result[0] == 2.0);
|
||||
REQUIRE(result[1] == 4.0);
|
||||
REQUIRE(result[2] == 6.0);
|
||||
}
|
||||
|
||||
SECTION("int * double")
|
||||
{
|
||||
cartesian_vector v{1, 2, 3};
|
||||
cartesian_vector result = v * 2.0;
|
||||
REQUIRE(result[0] == 2.0);
|
||||
REQUIRE(result[1] == 4.0);
|
||||
REQUIRE(result[2] == 6.0);
|
||||
}
|
||||
|
||||
SECTION("int * int")
|
||||
{
|
||||
cartesian_vector v{1, 2, 3};
|
||||
cartesian_vector result = v * 2;
|
||||
REQUIRE(result[0] == 2);
|
||||
REQUIRE(result[1] == 4);
|
||||
REQUIRE(result[2] == 6);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector scalar division")
|
||||
{
|
||||
SECTION("double / double")
|
||||
{
|
||||
cartesian_vector v{2.0, 4.0, 6.0};
|
||||
cartesian_vector result = v / 2.0;
|
||||
REQUIRE(result[0] == 1.0);
|
||||
REQUIRE(result[1] == 2.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("double / int")
|
||||
{
|
||||
cartesian_vector v{2.0, 4.0, 6.0};
|
||||
cartesian_vector result = v / 2;
|
||||
REQUIRE(result[0] == 1.0);
|
||||
REQUIRE(result[1] == 2.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("int / double")
|
||||
{
|
||||
cartesian_vector v{2, 4, 6};
|
||||
cartesian_vector result = v / 2.0;
|
||||
REQUIRE(result[0] == 1.0);
|
||||
REQUIRE(result[1] == 2.0);
|
||||
REQUIRE(result[2] == 3.0);
|
||||
}
|
||||
|
||||
SECTION("int / int")
|
||||
{
|
||||
cartesian_vector v{2, 4, 6};
|
||||
cartesian_vector result = v / 2;
|
||||
REQUIRE(result[0] == 1);
|
||||
REQUIRE(result[1] == 2);
|
||||
REQUIRE(result[2] == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector magnitude")
|
||||
{
|
||||
cartesian_vector v1{3.0, 4.0, 0.0};
|
||||
cartesian_vector v2{2.0, 3.0, 6.0};
|
||||
REQUIRE(v1.magnitude() == 5.0);
|
||||
REQUIRE(v2.magnitude() == 7.0);
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector unit vector")
|
||||
{
|
||||
cartesian_vector v{3.0, 4.0, 0.0};
|
||||
cartesian_vector unit_v = v.unit();
|
||||
REQUIRE_THAT(unit_v.magnitude(), WithinULP(1.0, 1));
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector equality")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{1, 2, 3};
|
||||
cartesian_vector v3{1.1, 2.0, 3.0};
|
||||
cartesian_vector v4{1.0, 2.1, 3.0};
|
||||
cartesian_vector v5{1.0, 2.0, 3.1};
|
||||
REQUIRE(v1 == v2);
|
||||
REQUIRE(v1 != v3);
|
||||
REQUIRE(v1 != v4);
|
||||
REQUIRE(v1 != v5);
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector scalar product")
|
||||
{
|
||||
SECTION("double * double")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
REQUIRE(scalar_product(v1, v2) == 32.0);
|
||||
}
|
||||
|
||||
SECTION("double * int")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
REQUIRE(scalar_product(v1, v2) == 32.0);
|
||||
}
|
||||
|
||||
SECTION("int * double")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
REQUIRE(scalar_product(v1, v2) == 32.0);
|
||||
}
|
||||
|
||||
SECTION("int * int")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
REQUIRE(scalar_product(v1, v2) == 32);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("cartesian_vector vector product")
|
||||
{
|
||||
SECTION("double * double")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
cartesian_vector result = vector_product(v1, v2);
|
||||
REQUIRE(result[0] == -3.0);
|
||||
REQUIRE(result[1] == 6.0);
|
||||
REQUIRE(result[2] == -3.0);
|
||||
}
|
||||
|
||||
SECTION("double * int")
|
||||
{
|
||||
cartesian_vector v1{1.0, 2.0, 3.0};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
cartesian_vector result = vector_product(v1, v2);
|
||||
REQUIRE(result[0] == -3.0);
|
||||
REQUIRE(result[1] == 6.0);
|
||||
REQUIRE(result[2] == -3.0);
|
||||
}
|
||||
|
||||
SECTION("int * double")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4.0, 5.0, 6.0};
|
||||
cartesian_vector result = vector_product(v1, v2);
|
||||
REQUIRE(result[0] == -3.0);
|
||||
REQUIRE(result[1] == 6.0);
|
||||
REQUIRE(result[2] == -3.0);
|
||||
}
|
||||
|
||||
SECTION("int * int")
|
||||
{
|
||||
cartesian_vector v1{1, 2, 3};
|
||||
cartesian_vector v2{4, 5, 6};
|
||||
cartesian_vector result = vector_product(v1, v2);
|
||||
REQUIRE(result[0] == -3);
|
||||
REQUIRE(result[1] == 6);
|
||||
REQUIRE(result[2] == -3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cartesian_vector text output", "[vector][fmt][ostream]")
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
SECTION("integral representation")
|
||||
{
|
||||
cartesian_vector v{1, 2, 3};
|
||||
os << v;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "[1, 2, 3]"); }
|
||||
SECTION("fmt with default format {}") { CHECK(MP_UNITS_STD_FMT::format("{}", v) == os.str()); }
|
||||
}
|
||||
|
||||
SECTION("floating-point representation")
|
||||
{
|
||||
cartesian_vector v{1.2, 2.3, 3.4};
|
||||
os << v;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "[1.2, 2.3, 3.4]"); }
|
||||
SECTION("fmt with default format {}") { CHECK(MP_UNITS_STD_FMT::format("{}", v) == os.str()); }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -38,19 +38,22 @@ import mp_units;
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
TEST_CASE("fixed_string::at", "[fixed_string]")
|
||||
TEST_CASE("fixed_string operations", "[fixed_string]")
|
||||
{
|
||||
basic_fixed_string txt = "abc";
|
||||
SECTION("in range")
|
||||
SECTION("fixed_string::at")
|
||||
{
|
||||
CHECK(txt.at(0) == 'a');
|
||||
CHECK(txt.at(1) == 'b');
|
||||
CHECK(txt.at(2) == 'c');
|
||||
}
|
||||
SECTION("out of range")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(txt.at(3), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
|
||||
REQUIRE_THROWS_MATCHES(txt.at(1024), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
|
||||
basic_fixed_string txt = "abc";
|
||||
SECTION("in range")
|
||||
{
|
||||
CHECK(txt.at(0) == 'a');
|
||||
CHECK(txt.at(1) == 'b');
|
||||
CHECK(txt.at(2) == 'c');
|
||||
}
|
||||
SECTION("out of range")
|
||||
{
|
||||
REQUIRE_THROWS_MATCHES(txt.at(3), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
|
||||
REQUIRE_THROWS_MATCHES(txt.at(1024), std::out_of_range, Catch::Matchers::Message("basic_fixed_string::at"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -43,486 +43,488 @@ using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// classical
|
||||
|
||||
TEST_CASE("'pow<N>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
|
||||
TEST_CASE("math operations", "[math]")
|
||||
{
|
||||
SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2 * isq::length[m]) == 1 * one); }
|
||||
|
||||
SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2 * isq::length[m]) == 2 * isq::length[m]); }
|
||||
|
||||
SECTION("'pow<2>(q)' squares both the value and a dimension")
|
||||
SECTION("'pow<N>()' on quantity changes the value and the dimension accordingly")
|
||||
{
|
||||
CHECK(pow<2>(2 * isq::length[m]) == 4 * isq::area[m2]);
|
||||
SECTION("'pow<0>(q)' returns '1'") { CHECK(pow<0>(2 * isq::length[m]) == 1 * one); }
|
||||
|
||||
SECTION("'pow<1>(q)' returns 'q'") { CHECK(pow<1>(2 * isq::length[m]) == 2 * isq::length[m]); }
|
||||
|
||||
SECTION("'pow<2>(q)' squares both the value and a dimension")
|
||||
{
|
||||
CHECK(pow<2>(2 * isq::length[m]) == 4 * isq::area[m2]);
|
||||
}
|
||||
|
||||
SECTION("'pow<3>(q)' cubes both the value and a dimension")
|
||||
{
|
||||
CHECK(pow<3>(2 * isq::length[m]) == 8 * isq::volume[m3]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("'pow<3>(q)' cubes both the value and a dimension")
|
||||
SECTION("'sqrt()' on quantity changes the value and the dimension accordingly")
|
||||
{
|
||||
CHECK(pow<3>(2 * isq::length[m]) == 8 * isq::volume[m3]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("'sqrt()' on quantity changes the value and the dimension accordingly", "[math][sqrt]")
|
||||
{
|
||||
REQUIRE(sqrt(4 * isq::area[m2]) == 2 * isq::length[m]);
|
||||
}
|
||||
|
||||
TEST_CASE("'cbrt()' on quantity changes the value and the dimension accordingly", "[math][cbrt]")
|
||||
{
|
||||
REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]);
|
||||
}
|
||||
|
||||
TEST_CASE("'fma()' on quantity changes the value and the dimension accordingly", "[math][fma]")
|
||||
{
|
||||
REQUIRE(fma(1.0 * isq::length[m], 2.0 * one, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
|
||||
REQUIRE(fma(isq::speed(10.0 * m / s), isq::time(2.0 * s), isq::height(42.0 * m)) == isq::length(62.0 * m));
|
||||
}
|
||||
|
||||
TEST_CASE("fmod functions", "[math][fmod]")
|
||||
{
|
||||
SECTION("fmod should work on the same quantities")
|
||||
{
|
||||
REQUIRE(fmod(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
|
||||
REQUIRE(fmod(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
|
||||
REQUIRE(fmod(3 * isq::length[km], 2 * isq::length[km]) == 1 * isq::length[km]);
|
||||
REQUIRE(fmod(4 * isq::length[km], 2.5f * isq::length[km]) == 1.5 * isq::length[km]);
|
||||
}
|
||||
SECTION("fmod should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(fmod(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
|
||||
REQUIRE(fmod(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
|
||||
REQUIRE(fmod(3. * isq::length[km], 2000. * isq::length[m]) == 1000 * isq::length[m]);
|
||||
REQUIRE(fmod(4 * isq::length[km], 2500 * isq::length[m]) == 1500 * isq::length[m]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("remainder functions", "[math][remainder]")
|
||||
{
|
||||
SECTION("remainder should work on the same quantities")
|
||||
{
|
||||
REQUIRE(remainder(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
|
||||
REQUIRE(remainder(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
|
||||
REQUIRE(remainder(3 * isq::length[km], 2 * isq::length[km]) == -1 * isq::length[km]);
|
||||
REQUIRE(remainder(4 * isq::length[km], 2.75f * isq::length[km]) == 1.25 * isq::length[km]);
|
||||
}
|
||||
SECTION("remainder should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(remainder(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
|
||||
REQUIRE(remainder(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
|
||||
REQUIRE(remainder(3. * isq::length[km], 2000. * isq::length[m]) == -1000 * isq::length[m]);
|
||||
REQUIRE(remainder(4 * isq::length[km], 2750 * isq::length[m]) == 1250 * isq::length[m]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("'isfinite()' accepts dimensioned arguments", "[math][isfinite]") { REQUIRE(isfinite(4.0 * isq::length[m])); }
|
||||
|
||||
TEST_CASE("'isinf()' accepts dimensioned arguments", "[math][isinf]") { REQUIRE(!isinf(4.0 * isq::length[m])); }
|
||||
|
||||
TEST_CASE("'isnan()' accepts dimensioned arguments", "[math][isnan]") { REQUIRE(!isnan(4.0 * isq::length[m])); }
|
||||
|
||||
|
||||
TEST_CASE("'pow<Num, Den>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
|
||||
{
|
||||
REQUIRE(pow<1, 4>(16 * isq::area[m2]) == sqrt(4 * isq::length[m]));
|
||||
}
|
||||
|
||||
// TODO add tests for exp()
|
||||
|
||||
TEST_CASE("absolute functions on quantity returns the absolute value", "[math][abs][fabs]")
|
||||
{
|
||||
SECTION("'abs()' on a negative quantity returns the abs")
|
||||
{
|
||||
SECTION("integral representation") { REQUIRE(abs(-1 * isq::length[m]) == 1 * isq::length[m]); }
|
||||
|
||||
SECTION("floating-point representation") { REQUIRE(abs(-1. * isq::length[m]) == 1 * isq::length[m]); }
|
||||
}
|
||||
|
||||
SECTION("'abs()' on a positive quantity returns the abs")
|
||||
{
|
||||
SECTION("integral representation") { REQUIRE(abs(1 * isq::length[m]) == 1 * isq::length[m]); }
|
||||
|
||||
SECTION("floating-point representation") { REQUIRE(abs(1. * isq::length[m]) == 1 * isq::length[m]); }
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("numeric_limits functions", "[limits]")
|
||||
{
|
||||
SECTION("'epsilon' works as expected using default floating type")
|
||||
{
|
||||
REQUIRE(epsilon<double>(isq::length[m]).numerical_value_in(m) ==
|
||||
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
|
||||
}
|
||||
SECTION("'epsilon' works as expected using integers")
|
||||
{
|
||||
REQUIRE(epsilon<int>(isq::length[m]).numerical_value_in(m) ==
|
||||
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("floor functions", "[floor]")
|
||||
{
|
||||
SECTION("floor 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1001 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1999 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1999 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -999 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-999 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1.3 seconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1.3 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1.3 seconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1.3 * isq::time[s]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1001. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1999. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1999. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -999. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-999. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
|
||||
// TODO Add tests for `N`, `kN` and `kg * m / s2` i `kg * km / s2`
|
||||
}
|
||||
|
||||
TEST_CASE("ceil functions", "[ceil]")
|
||||
{
|
||||
SECTION("ceil 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1001 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -999 milliseconds with target unit second should be 0 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-999 * isq::time[ms]) == 0 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1.3 seconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1.3 * isq::time[s]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1.3 seconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1.3 * isq::time[s]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1001. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -999. milliseconds with target unit second should be 0 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-999. * isq::time[ms]) == 0 * isq::time[s]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("round functions", "[round]")
|
||||
{
|
||||
SECTION("round 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1001 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1499 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1499 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1500 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1500 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1999 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1001 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1001 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1499 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1499 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1500 milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1500 * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1999 milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1999 * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1000. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1000. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1001. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1499. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1499. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1500. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1500. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1999. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1001. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1001. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1499. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1499. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1500. milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1500. * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1999. milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1999. * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("hypot functions", "[hypot]")
|
||||
{
|
||||
SECTION("hypot should work on the same quantities")
|
||||
{
|
||||
REQUIRE(hypot(3. * isq::length[km], 4. * isq::length[km]) == 5. * isq::length[km]);
|
||||
REQUIRE(hypot(2. * isq::length[km], 3. * isq::length[km], 6. * isq::length[km]) == 7. * isq::length[km]);
|
||||
}
|
||||
SECTION("hypot should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(hypot(3. * isq::length[km], 4000. * isq::length[m]) == 5. * isq::length[km]);
|
||||
REQUIRE(hypot(2. * isq::length[km], 3000. * isq::length[m], 6. * isq::length[km]) == 7. * isq::length[km]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SI trigonometric functions", "[trig][si]")
|
||||
{
|
||||
SECTION("sin")
|
||||
{
|
||||
REQUIRE_THAT(si::sin(0 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::sin(90 * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::sin(180 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::sin(270 * deg), AlmostEquals(-1. * one));
|
||||
}
|
||||
|
||||
SECTION("cos")
|
||||
{
|
||||
REQUIRE_THAT(si::cos(0 * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::cos(90 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::cos(180 * deg), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(si::cos(270 * deg), AlmostEquals(0. * one));
|
||||
}
|
||||
|
||||
SECTION("tan")
|
||||
{
|
||||
REQUIRE_THAT(si::tan(0 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::tan(45. * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::tan(135. * deg), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(si::tan(180. * deg), AlmostEquals(0. * one));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SI inverse trigonometric functions", "[inv trig][si]")
|
||||
{
|
||||
SECTION("asin")
|
||||
{
|
||||
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
|
||||
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
|
||||
}
|
||||
|
||||
SECTION("acos")
|
||||
{
|
||||
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
|
||||
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
|
||||
}
|
||||
|
||||
SECTION("atan")
|
||||
{
|
||||
REQUIRE_THAT(si::atan(-1 * one), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan(1 * one), AlmostEquals(45. * deg));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SI atan2 functions", "[atan2][si]")
|
||||
{
|
||||
SECTION("atan2 should work on the same quantities")
|
||||
{
|
||||
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * deg));
|
||||
}
|
||||
SECTION("atan2 should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * deg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Angle trigonometric functions", "[trig][angle]")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("sin")
|
||||
{
|
||||
REQUIRE_THAT(sin(0 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(90 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(sin(180 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(270 * angle[deg]), AlmostEquals(-1. * one));
|
||||
|
||||
REQUIRE_THAT(sin(0 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(100 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(sin(200 * angle[grad]), AlmostEquals(0. * one, 2));
|
||||
REQUIRE_THAT(sin(300 * angle[grad]), AlmostEquals(-1. * one));
|
||||
}
|
||||
|
||||
SECTION("cos")
|
||||
{
|
||||
REQUIRE_THAT(cos(0 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(cos(90 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(cos(180 * angle[deg]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(cos(270 * angle[deg]), AlmostEquals(0. * one));
|
||||
|
||||
REQUIRE_THAT(cos(0 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(cos(100 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(cos(200 * angle[grad]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(cos(300 * angle[grad]), AlmostEquals(0. * one));
|
||||
}
|
||||
|
||||
SECTION("tan")
|
||||
{
|
||||
REQUIRE_THAT(tan(0 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(tan(45 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(tan(135 * angle[deg]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(tan(180 * angle[deg]), AlmostEquals(0. * one));
|
||||
|
||||
REQUIRE_THAT(tan(0 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(tan(50 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(tan(150 * angle[grad]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(tan(200 * angle[grad]), AlmostEquals(0. * one, 2));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Angle inverse trigonometric functions", "[inv trig][angle]")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("asin")
|
||||
{
|
||||
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
|
||||
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
|
||||
}
|
||||
|
||||
SECTION("acos")
|
||||
{
|
||||
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
|
||||
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
|
||||
}
|
||||
|
||||
SECTION("atan")
|
||||
{
|
||||
REQUIRE_THAT(atan(-1 * one), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan(1 * one), AlmostEquals(45. * angle[deg]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Angle atan2 functions", "[atan2][angle]")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("atan2 should work on the same quantities")
|
||||
{
|
||||
REQUIRE_THAT(atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * angle[deg]));
|
||||
}
|
||||
SECTION("atan2 should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE_THAT(atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * angle[deg]));
|
||||
REQUIRE(sqrt(4 * isq::area[m2]) == 2 * isq::length[m]);
|
||||
}
|
||||
|
||||
SECTION("'cbrt()' on quantity changes the value and the dimension accordingly")
|
||||
{
|
||||
REQUIRE(cbrt(8 * isq::volume[m3]) == 2 * isq::length[m]);
|
||||
}
|
||||
|
||||
SECTION("'fma()' on quantity changes the value and the dimension accordingly")
|
||||
{
|
||||
REQUIRE(fma(1.0 * isq::length[m], 2.0 * one, 2.0 * isq::length[m]) == 4.0 * isq::length[m]);
|
||||
REQUIRE(fma(isq::speed(10.0 * m / s), isq::time(2.0 * s), isq::height(42.0 * m)) == isq::length(62.0 * m));
|
||||
}
|
||||
|
||||
SECTION("fmod functions")
|
||||
{
|
||||
SECTION("fmod should work on the same quantities")
|
||||
{
|
||||
REQUIRE(fmod(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
|
||||
REQUIRE(fmod(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
|
||||
REQUIRE(fmod(3 * isq::length[km], 2 * isq::length[km]) == 1 * isq::length[km]);
|
||||
REQUIRE(fmod(4 * isq::length[km], 2.5f * isq::length[km]) == 1.5 * isq::length[km]);
|
||||
}
|
||||
SECTION("fmod should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(fmod(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
|
||||
REQUIRE(fmod(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
|
||||
REQUIRE(fmod(3. * isq::length[km], 2000. * isq::length[m]) == 1000 * isq::length[m]);
|
||||
REQUIRE(fmod(4 * isq::length[km], 2500 * isq::length[m]) == 1500 * isq::length[m]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remainder functions")
|
||||
{
|
||||
SECTION("remainder should work on the same quantities")
|
||||
{
|
||||
REQUIRE(remainder(4. * isq::length[km], 3. * isq::length[km]) == 1. * isq::length[km]);
|
||||
REQUIRE(remainder(-9. * isq::length[km], 3. * isq::length[km]) == -0. * isq::length[km]);
|
||||
REQUIRE(remainder(3 * isq::length[km], 2 * isq::length[km]) == -1 * isq::length[km]);
|
||||
REQUIRE(remainder(4 * isq::length[km], 2.75f * isq::length[km]) == 1.25 * isq::length[km]);
|
||||
}
|
||||
SECTION("remainder should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(remainder(4. * isq::length[km], 3000. * isq::length[m]) == 1000. * isq::length[m]);
|
||||
REQUIRE(remainder(-9. * isq::length[km], 3000. * isq::length[m]) == -0. * isq::length[m]);
|
||||
REQUIRE(remainder(3. * isq::length[km], 2000. * isq::length[m]) == -1000 * isq::length[m]);
|
||||
REQUIRE(remainder(4 * isq::length[km], 2750 * isq::length[m]) == 1250 * isq::length[m]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("'isfinite()' accepts dimensioned arguments") { REQUIRE(isfinite(4.0 * isq::length[m])); }
|
||||
|
||||
SECTION("'isinf()' accepts dimensioned arguments") { REQUIRE(!isinf(4.0 * isq::length[m])); }
|
||||
|
||||
SECTION("'isnan()' accepts dimensioned arguments") { REQUIRE(!isnan(4.0 * isq::length[m])); }
|
||||
|
||||
|
||||
SECTION("'pow<Num, Den>()' on quantity changes the value and the dimension accordingly")
|
||||
{
|
||||
REQUIRE(pow<1, 4>(16 * isq::area[m2]) == sqrt(4 * isq::length[m]));
|
||||
}
|
||||
|
||||
// TODO add tests for exp()
|
||||
|
||||
SECTION("absolute functions on quantity returns the absolute value")
|
||||
{
|
||||
SECTION("'abs()' on a negative quantity returns the abs")
|
||||
{
|
||||
SECTION("integral representation") { REQUIRE(abs(-1 * isq::length[m]) == 1 * isq::length[m]); }
|
||||
|
||||
SECTION("floating-point representation") { REQUIRE(abs(-1. * isq::length[m]) == 1 * isq::length[m]); }
|
||||
}
|
||||
|
||||
SECTION("'abs()' on a positive quantity returns the abs")
|
||||
{
|
||||
SECTION("integral representation") { REQUIRE(abs(1 * isq::length[m]) == 1 * isq::length[m]); }
|
||||
|
||||
SECTION("floating-point representation") { REQUIRE(abs(1. * isq::length[m]) == 1 * isq::length[m]); }
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("numeric_limits functions")
|
||||
{
|
||||
SECTION("'epsilon' works as expected using default floating type")
|
||||
{
|
||||
REQUIRE(epsilon<double>(isq::length[m]).numerical_value_in(m) ==
|
||||
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
|
||||
}
|
||||
SECTION("'epsilon' works as expected using integers")
|
||||
{
|
||||
REQUIRE(epsilon<int>(isq::length[m]).numerical_value_in(m) ==
|
||||
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("floor functions")
|
||||
{
|
||||
SECTION("floor 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1001 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1999 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1999 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -999 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-999 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1.3 seconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1.3 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1.3 seconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1.3 * isq::time[s]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1001. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor 1999. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(1999. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("floor -999. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(floor<si::second>(-999. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
|
||||
// TODO Add tests for `N`, `kN` and `kg * m / s2` i `kg * km / s2`
|
||||
}
|
||||
|
||||
SECTION("ceil functions")
|
||||
{
|
||||
SECTION("ceil 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1001 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1001 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1999 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -999 milliseconds with target unit second should be 0 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-999 * isq::time[ms]) == 0 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1.3 seconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1.3 * isq::time[s]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1.3 seconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1.3 * isq::time[s]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1001. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1001. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil 1999. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("ceil -999. milliseconds with target unit second should be 0 seconds")
|
||||
{
|
||||
REQUIRE(ceil<si::second>(-999. * isq::time[ms]) == 0 * isq::time[s]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("round functions")
|
||||
{
|
||||
SECTION("round 1 second with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1 * isq::time[s]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1000 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1000 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1001 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1001 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1499 milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1499 * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1500 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1500 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1999 milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1999 * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1000 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1000 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1001 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1001 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1499 milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1499 * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1500 milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1500 * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1999 milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1999 * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1000. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1000. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1001. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1001. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1499. milliseconds with target unit second should be 1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(1499. * isq::time[ms]) == 1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1500. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1500. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round 1999. milliseconds with target unit second should be 2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(1999. * isq::time[ms]) == 2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1000. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1000. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1001. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1001. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1499. milliseconds with target unit second should be -1 second")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1499. * isq::time[ms]) == -1 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1500. milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1500. * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
SECTION("round -1999. milliseconds with target unit second should be -2 seconds")
|
||||
{
|
||||
REQUIRE(round<si::second>(-1999. * isq::time[ms]) == -2 * isq::time[s]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("hypot functions")
|
||||
{
|
||||
SECTION("hypot should work on the same quantities")
|
||||
{
|
||||
REQUIRE(hypot(3. * isq::length[km], 4. * isq::length[km]) == 5. * isq::length[km]);
|
||||
REQUIRE(hypot(2. * isq::length[km], 3. * isq::length[km], 6. * isq::length[km]) == 7. * isq::length[km]);
|
||||
}
|
||||
SECTION("hypot should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE(hypot(3. * isq::length[km], 4000. * isq::length[m]) == 5. * isq::length[km]);
|
||||
REQUIRE(hypot(2. * isq::length[km], 3000. * isq::length[m], 6. * isq::length[km]) == 7. * isq::length[km]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("SI trigonometric functions")
|
||||
{
|
||||
SECTION("sin")
|
||||
{
|
||||
REQUIRE_THAT(si::sin(0 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::sin(90 * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::sin(180 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::sin(270 * deg), AlmostEquals(-1. * one));
|
||||
}
|
||||
|
||||
SECTION("cos")
|
||||
{
|
||||
REQUIRE_THAT(si::cos(0 * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::cos(90 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::cos(180 * deg), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(si::cos(270 * deg), AlmostEquals(0. * one));
|
||||
}
|
||||
|
||||
SECTION("tan")
|
||||
{
|
||||
REQUIRE_THAT(si::tan(0 * deg), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(si::tan(45. * deg), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(si::tan(135. * deg), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(si::tan(180. * deg), AlmostEquals(0. * one));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("SI inverse trigonometric functions")
|
||||
{
|
||||
SECTION("asin")
|
||||
{
|
||||
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
|
||||
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
|
||||
}
|
||||
|
||||
SECTION("acos")
|
||||
{
|
||||
REQUIRE_THAT(si::asin(-1 * one), AlmostEquals(-90. * deg));
|
||||
REQUIRE_THAT(si::asin(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::asin(1 * one), AlmostEquals(90. * deg));
|
||||
}
|
||||
|
||||
SECTION("atan")
|
||||
{
|
||||
REQUIRE_THAT(si::atan(-1 * one), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan(0 * one), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan(1 * one), AlmostEquals(45. * deg));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("SI atan2 functions")
|
||||
{
|
||||
SECTION("atan2 should work on the same quantities")
|
||||
{
|
||||
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * deg));
|
||||
}
|
||||
SECTION("atan2 should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE_THAT(si::atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * deg));
|
||||
REQUIRE_THAT(si::atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * deg));
|
||||
REQUIRE_THAT(si::atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * deg));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Angle trigonometric functions")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("sin")
|
||||
{
|
||||
REQUIRE_THAT(sin(0 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(90 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(sin(180 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(270 * angle[deg]), AlmostEquals(-1. * one));
|
||||
|
||||
REQUIRE_THAT(sin(0 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(sin(100 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(sin(200 * angle[grad]), AlmostEquals(0. * one, 2));
|
||||
REQUIRE_THAT(sin(300 * angle[grad]), AlmostEquals(-1. * one));
|
||||
}
|
||||
|
||||
SECTION("cos")
|
||||
{
|
||||
REQUIRE_THAT(cos(0 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(cos(90 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(cos(180 * angle[deg]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(cos(270 * angle[deg]), AlmostEquals(0. * one));
|
||||
|
||||
REQUIRE_THAT(cos(0 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(cos(100 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(cos(200 * angle[grad]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(cos(300 * angle[grad]), AlmostEquals(0. * one));
|
||||
}
|
||||
|
||||
SECTION("tan")
|
||||
{
|
||||
REQUIRE_THAT(tan(0 * angle[deg]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(tan(45 * angle[deg]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(tan(135 * angle[deg]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(tan(180 * angle[deg]), AlmostEquals(0. * one));
|
||||
|
||||
REQUIRE_THAT(tan(0 * angle[grad]), AlmostEquals(0. * one));
|
||||
REQUIRE_THAT(tan(50 * angle[grad]), AlmostEquals(1. * one));
|
||||
REQUIRE_THAT(tan(150 * angle[grad]), AlmostEquals(-1. * one));
|
||||
REQUIRE_THAT(tan(200 * angle[grad]), AlmostEquals(0. * one, 2));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Angle inverse trigonometric functions")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("asin")
|
||||
{
|
||||
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
|
||||
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
|
||||
}
|
||||
|
||||
SECTION("acos")
|
||||
{
|
||||
REQUIRE_THAT(asin(-1 * one), AlmostEquals(-90. * angle[deg]));
|
||||
REQUIRE_THAT(asin(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(asin(1 * one), AlmostEquals(90. * angle[deg]));
|
||||
}
|
||||
|
||||
SECTION("atan")
|
||||
{
|
||||
REQUIRE_THAT(atan(-1 * one), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan(0 * one), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan(1 * one), AlmostEquals(45. * angle[deg]));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Angle atan2 functions")
|
||||
{
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
using mp_units::angular::unit_symbols::deg;
|
||||
|
||||
SECTION("atan2 should work on the same quantities")
|
||||
{
|
||||
REQUIRE_THAT(atan2(-1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(0. * isq::length[km], 1. * isq::length[km]), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(1. * isq::length[km], 1. * isq::length[km]), AlmostEquals(45. * angle[deg]));
|
||||
}
|
||||
SECTION("atan2 should work with different units of the same dimension")
|
||||
{
|
||||
REQUIRE_THAT(atan2(-1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(-45. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(0. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(0. * angle[deg]));
|
||||
REQUIRE_THAT(atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * angle[deg]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -60,22 +60,25 @@ constexpr bool within_4_ulps(T a, T b)
|
||||
|
||||
} // namespace
|
||||
|
||||
// conversion requiring radical magnitudes
|
||||
TEST_CASE("unit conversions support radical magnitudes", "[conversion][radical]")
|
||||
TEST_CASE("quantity operations", "[quantity]")
|
||||
{
|
||||
REQUIRE(within_4_ulps(sqrt((1.0 * m) * (1.0 * km)).numerical_value_in(m), sqrt(1000.0)));
|
||||
}
|
||||
// conversion requiring radical magnitudes
|
||||
SECTION("unit conversions support radical magnitudes")
|
||||
{
|
||||
REQUIRE(within_4_ulps(sqrt((1.0 * m) * (1.0 * km)).numerical_value_in(m), sqrt(1000.0)));
|
||||
}
|
||||
|
||||
// Reproducing issue #474 exactly:
|
||||
TEST_CASE("Issue 474 is fixed", "[conversion][radical]")
|
||||
{
|
||||
constexpr auto val_issue_474 = 8.0 * si::si2019::boltzmann_constant * 1000.0 * K / (std::numbers::pi * 10 * Da);
|
||||
REQUIRE(within_4_ulps(sqrt(val_issue_474).numerical_value_in(m / s),
|
||||
sqrt(val_issue_474.numerical_value_in(m * m / s / s))));
|
||||
}
|
||||
// Reproducing issue #474 exactly:
|
||||
SECTION("Issue 474 is fixed")
|
||||
{
|
||||
constexpr auto val_issue_474 = 8.0 * si::si2019::boltzmann_constant * 1000.0 * K / (std::numbers::pi * 10 * Da);
|
||||
REQUIRE(within_4_ulps(sqrt(val_issue_474).numerical_value_in(m / s),
|
||||
sqrt(val_issue_474.numerical_value_in(m * m / s / s))));
|
||||
}
|
||||
|
||||
TEST_CASE("Volatile representation type", "[volatile]")
|
||||
{
|
||||
volatile std::int16_t vint = 123;
|
||||
REQUIRE(quantity(vint * m).numerical_value_in(m) == 123);
|
||||
SECTION("Volatile representation type")
|
||||
{
|
||||
volatile std::int16_t vint = 123;
|
||||
REQUIRE(quantity(vint * m).numerical_value_in(m) == 123);
|
||||
}
|
||||
}
|
||||
|
@@ -25,24 +25,28 @@
|
||||
#include <mp-units/systems/isq/mechanics.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si/units.h>
|
||||
|
||||
template<class T>
|
||||
requires mp_units::is_scalar<T>
|
||||
constexpr bool mp_units::is_vector<T> = true;
|
||||
#if MP_UNITS_HOSTED
|
||||
#include <mp-units/cartesian_vector.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::cgs;
|
||||
using namespace mp_units::cgs::unit_symbols;
|
||||
#if MP_UNITS_HOSTED
|
||||
using v = cartesian_vector<double>;
|
||||
#endif
|
||||
|
||||
// https://en.wikipedia.org/wiki/Centimetre%E2%80%93gram%E2%80%93second_system_of_units#Definitions_and_conversion_factors_of_CGS_units_in_mechanics
|
||||
static_assert(isq::length(100 * cm) == isq::length(1 * si::metre));
|
||||
static_assert(isq::mass(1000 * g) == isq::mass(1 * si::kilogram));
|
||||
static_assert(isq::time(1 * s) == isq::time(1 * si::second));
|
||||
static_assert(isq::speed(100 * cm / s) == isq::speed(1 * si::metre / si::second));
|
||||
static_assert(isq::acceleration(100 * Gal) == isq::acceleration(1 * si::metre / square(si::second)));
|
||||
static_assert(isq::force(100'000 * dyn) == isq::force(1 * si::newton));
|
||||
#if MP_UNITS_HOSTED
|
||||
static_assert(isq::acceleration(v{100} * Gal) == isq::acceleration(v{1} * si::metre / square(si::second)));
|
||||
static_assert(isq::force(v{100'000} * dyn) == isq::force(v{1} * si::newton));
|
||||
#endif
|
||||
static_assert(isq::energy(10'000'000 * erg) == isq::energy(1 * si::joule));
|
||||
static_assert(isq::power(10'000'000 * erg / s) == isq::power(1 * si::watt));
|
||||
static_assert(isq::pressure(10 * Ba) == isq::pressure(1 * si::pascal));
|
||||
|
@@ -237,17 +237,17 @@ static_assert(compare(round<si::second>(-1999. * isq::time[ms]), -2. * isq::time
|
||||
#endif
|
||||
|
||||
// non-truncating
|
||||
static_assert(compare(inverse<us>(250 * Hz), 4000 * us));
|
||||
static_assert(compare(inverse<us>(250 * kHz), 4 * us));
|
||||
static_assert(compare(inverse<ks>(250 * uHz), 4 * ks));
|
||||
static_assert(compare(kind_of<isq::time>(inverse<us>(250 * Hz)), 4000 * us));
|
||||
static_assert(compare(kind_of<isq::time>(inverse<us>(250 * kHz)), 4 * us));
|
||||
static_assert(compare(kind_of<isq::time>(inverse<ks>(250 * uHz)), 4 * ks));
|
||||
|
||||
// truncating
|
||||
static_assert(compare(inverse<s>(1 * kHz), 0 * s));
|
||||
static_assert(compare(kind_of<isq::time>(inverse<s>(1 * kHz)), 0 * s));
|
||||
|
||||
// floating-point representation does not truncate
|
||||
static_assert(compare(inverse<s>(1. * kHz), 0.001 * s));
|
||||
static_assert(compare(kind_of<isq::time>(inverse<s>(1. * kHz)), 0.001 * s));
|
||||
|
||||
// check if constraints work properly for a derived unit of a narrowed kind
|
||||
static_assert(compare(inverse<Hz>(1 * s), 1 * Hz));
|
||||
static_assert(compare(kind_of<isq::frequency>(inverse<Hz>(1 * s)), 1 * Hz));
|
||||
|
||||
} // namespace
|
||||
|
@@ -378,4 +378,14 @@ static_assert(invalid_comparison<frequency(1 * hertz), activity(1 * becquerel)>)
|
||||
static_assert(invalid_comparison<angular_measure(1 * radian), solid_angular_measure(1 * steradian)>);
|
||||
static_assert(invalid_comparison<angular_measure(1 * radian), storage_capacity(1 * bit)>);
|
||||
|
||||
// make_reference
|
||||
static_assert(is_of_type<make_reference(length, metre), reference<length_, metre_>>);
|
||||
static_assert(is_of_type<make_reference(width, metre), reference<width_, metre_>>);
|
||||
static_assert(is_of_type<make_reference(kind_of<length>, metre), metre_>);
|
||||
static_assert(is_of_type<make_reference(get_quantity_spec(metre), metre), metre_>);
|
||||
static_assert(is_of_type<make_reference(get_quantity_spec(hertz), hertz), hertz_>);
|
||||
static_assert(is_of_type<make_reference(kind_of<frequency>, hertz), hertz_>);
|
||||
static_assert(is_of_type<make_reference(get_quantity_spec(watt), watt), watt_>);
|
||||
static_assert(is_of_type<make_reference(kind_of<power>, watt), reference<kind_of_<power_>, watt_>>);
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user