mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
Merge branch 'master' of github.com:mpusz/mp-units
This commit is contained in:
4
.github/workflows/ci-conan.yml
vendored
4
.github/workflows/ci-conan.yml
vendored
@ -47,7 +47,7 @@ jobs:
|
||||
# name: "MSVC 14.2",
|
||||
# os: windows-2019,
|
||||
# compiler: { type: VISUAL, version: 16, cc: "", cxx: "" },
|
||||
# conan-config: "-c user.build:skip_la=True",
|
||||
# conan-config: "-c user.mp-units.build:skip_la=True",
|
||||
# }
|
||||
# - {
|
||||
# name: "MSVC 14.3",
|
||||
@ -212,7 +212,7 @@ jobs:
|
||||
run: |
|
||||
conan create . --user mpusz --channel ${CHANNEL} --lockfile-out=package.lock \
|
||||
-b mp-units/* -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" \
|
||||
-c user.build:all=True -o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }} ${{ matrix.config.conan-config }}
|
||||
-c user.mp-units.build:all=True -o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }} ${{ matrix.config.conan-config }}
|
||||
- name: Obtain package reference
|
||||
id: get-package-ref
|
||||
shell: bash
|
||||
|
2
.github/workflows/ci-test-package-cmake.yml
vendored
2
.github/workflows/ci-test-package-cmake.yml
vendored
@ -205,7 +205,7 @@ jobs:
|
||||
- name: Install Conan dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
conan install . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -c user.build:all=False \
|
||||
conan install . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -c user.mp-units.build:all=False \
|
||||
-o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }}
|
||||
mv CMakeUserPresets.json src
|
||||
- name: Configure mp-units CMake
|
||||
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@ -105,7 +105,7 @@ jobs:
|
||||
conan profile detect --force
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
mkdir _lgtm_build_dir && cd _lgtm_build_dir
|
||||
conan build .. -s compiler.cppstd=20 -c user.build:all=True -o use_fmtlib=True -b missing
|
||||
conan build .. -s compiler.cppstd=20 -c user.mp-units.build:all=True -o use_fmtlib=True -b missing
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
32
.gitpod.yml
32
.gitpod.yml
@ -70,17 +70,17 @@ tasks:
|
||||
gp sync-await python-init
|
||||
conan profile detect
|
||||
conan config install $PWD/.gitpod/conan
|
||||
conan install . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -b missing
|
||||
conan install . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -b missing -s build_type=Debug
|
||||
conan install . -pr gcc12 -o use_fmtlib=True -b missing
|
||||
conan install . -pr gcc12 -o use_fmtlib=True -b missing -s build_type=Debug
|
||||
gp sync-done conan-gcc12-20
|
||||
conan install . -pr gcc13 -c user.build:all=True -b missing
|
||||
conan install . -pr gcc13 -c user.build:all=True -b missing -s build_type=Debug
|
||||
conan install . -pr gcc13 -b missing
|
||||
conan install . -pr gcc13 -b missing -s build_type=Debug
|
||||
gp sync-done conan-gcc13-20
|
||||
conan install . -pr clang16 -c user.build:all=True -o use_fmtlib=True -b missing
|
||||
conan install . -pr clang16 -c user.build:all=True -o use_fmtlib=True -b missing -s build_type=Debug
|
||||
conan install . -pr clang16 -o use_fmtlib=True -b missing
|
||||
conan install . -pr clang16 -o use_fmtlib=True -b missing -s build_type=Debug
|
||||
gp sync-done conan-clang16-20
|
||||
conan install . -pr clang17 -c user.build:all=True -o cxx_modules=True -b missing
|
||||
conan install . -pr clang17 -c user.build:all=True -o cxx_modules=True -b missing -s build_type=Debug
|
||||
conan install . -pr clang17 -o cxx_modules=True -b missing
|
||||
conan install . -pr clang17 -o cxx_modules=True -b missing -s build_type=Debug
|
||||
gp sync-done conan-clang17-20
|
||||
conan remote login -p $ARTIFACTORY_TOKEN conan-gitpod-mp-units $ARTIFACTORY_USER
|
||||
conan upload "*" -r conan-gitpod-mp-units -c
|
||||
@ -88,29 +88,29 @@ tasks:
|
||||
init: |
|
||||
gp sync-await conan-gcc12-20
|
||||
source ${PYTHON_VENV}/bin/activate
|
||||
conan build . -pr gcc12 -c user.build:all=True -o use_fmtlib=True
|
||||
conan build . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -s build_type=Debug
|
||||
conan build . -pr gcc12 -o use_fmtlib=True
|
||||
conan build . -pr gcc12 -o use_fmtlib=True -s build_type=Debug
|
||||
echo "🛠️ gcc-12 pre-build done for C++20, header files, and libfmt! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: gcc-13-20
|
||||
init: |
|
||||
gp sync-await conan-gcc13-20
|
||||
source ${PYTHON_VENV}/bin/activate
|
||||
conan build . -pr gcc13 -c user.build:all=True
|
||||
conan build . -pr gcc13 -c user.build:all=True -s build_type=Debug
|
||||
conan build . -pr gcc13
|
||||
conan build . -pr gcc13 -s build_type=Debug
|
||||
echo "🛠️ gcc-13 pre-build done for C++20 and header files! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-16-20
|
||||
init: |
|
||||
gp sync-await conan-clang16-20
|
||||
source ${PYTHON_VENV}/bin/activate
|
||||
conan build . -pr clang16 -c user.build:all=True -o use_fmtlib=True
|
||||
conan build . -pr clang16 -c user.build:all=True -o use_fmtlib=True -s build_type=Debug
|
||||
conan build . -pr clang16 -o use_fmtlib=True
|
||||
conan build . -pr clang16 -o use_fmtlib=True -s build_type=Debug
|
||||
echo "🛠️ clang-16 pre-build done for C++20, header files, and libfmt! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: clang-17-20
|
||||
init: |
|
||||
gp sync-await conan-clang17-20
|
||||
source ${PYTHON_VENV}/bin/activate
|
||||
conan build . -pr clang17 -c user.build:all=True -o cxx_modules=True
|
||||
conan build . -pr clang17 -c user.build:all=True -o cxx_modules=True -s build_type=Debug
|
||||
conan build . -pr clang17 -o cxx_modules=True
|
||||
conan build . -pr clang17 -o cxx_modules=True -s build_type=Debug
|
||||
echo "🛠️ clang-17 pre-build done for C++20! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
|
||||
- name: documentation
|
||||
init: |
|
||||
|
@ -1,2 +1,3 @@
|
||||
tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
|
||||
tools.cmake.cmake_layout:build_folder_vars=["settings.compiler", "settings.compiler.version", "settings.compiler.cppstd"]
|
||||
user.mp-units.build:all=True
|
||||
|
@ -56,13 +56,21 @@ After the script is done please make sure to stage all those changes to git comm
|
||||
The simplest way to verify if all targets build correctly and all unit tests pass is to run:
|
||||
|
||||
```bash
|
||||
conan build . -pr <your_conan_profile> -s compiler.cppstd=23 -o cxx_modules=True -c user.build:all=True -b missing
|
||||
conan build . -pr <your_conan_profile> -s compiler.cppstd=23 -o cxx_modules=True -c user.mp-units.build:all=True -b missing
|
||||
```
|
||||
|
||||
as described in the
|
||||
[Installation and Usage](https://mpusz.github.io/mp-units/latest/getting_started/installation_and_usage/#contributing-or-just-building-all-the-tests-and-examples)
|
||||
chapter of our documentation.
|
||||
|
||||
_Hint:_ To ensure that that we always build all the targets and to save some typing of the Conan commands,
|
||||
it is a good practice to set the following in the `~/.conan2/global.conf`:
|
||||
|
||||
```text
|
||||
user.mp-units.build:all=True
|
||||
```
|
||||
|
||||
|
||||
### Backward Compatibility
|
||||
|
||||
Before submission, please remember to check if the code compiles fine on the supported compilers.
|
||||
|
@ -83,7 +83,7 @@ class MPUnitsConan(ConanFile):
|
||||
return {
|
||||
"gcc": "12",
|
||||
"clang": "16",
|
||||
"apple-clang": "15"
|
||||
"apple-clang": "15",
|
||||
# , "msvc": "192"
|
||||
}
|
||||
|
||||
@ -91,18 +91,18 @@ class MPUnitsConan(ConanFile):
|
||||
def _std_format_minimum_compilers_version(self):
|
||||
return {
|
||||
"gcc": "13",
|
||||
"clang": "17"
|
||||
"clang": "17",
|
||||
# , "apple-clang": "15"
|
||||
# , "msvc": "192"
|
||||
}
|
||||
|
||||
@property
|
||||
def _build_all(self):
|
||||
return bool(self.conf.get("user.build:all", default=False))
|
||||
return bool(self.conf.get("user.mp-units.build:all", default=False))
|
||||
|
||||
@property
|
||||
def _skip_la(self):
|
||||
return bool(self.conf.get("user.build:skip_la", default=False))
|
||||
return bool(self.conf.get("user.mp-units.build:skip_la", default=False))
|
||||
|
||||
def set_version(self):
|
||||
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
||||
|
@ -194,9 +194,9 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
|
||||
### Conan configuration properties
|
||||
|
||||
[`user.build:all`](#user-build-all){ #user-build-all }
|
||||
[`user.mp-units.build:all`](#user.mp-units.build-all){ #user.mp-units.build-all }
|
||||
|
||||
: [:octicons-tag-24: 0.8.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
: [:octicons-tag-24: 2.2.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
|
||||
Enables compilation of all the source code, including tests and examples. To support this, it requires some additional Conan build dependencies described in
|
||||
[Repository Structure and Dependencies](#repository-structure-and-dependencies).
|
||||
@ -204,19 +204,19 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
[`tools.build:skip_test`](https://docs.conan.io/2/reference/commands/config.html?highlight=tools.build:skip_test#conan-config-list)
|
||||
configuration property is set to `True`).
|
||||
|
||||
[build all support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
|
||||
[build all support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
|
||||
|
||||
|
||||
[`user.build:skip_la`](#user-skip-la){ #user-skip-la }
|
||||
[`user.mp-units.build:skip_la`](#user-skip-la){ #user-skip-la }
|
||||
|
||||
: [:octicons-tag-24: 0.8.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
: [:octicons-tag-24: 2.2.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
|
||||
If `user.build:all` is enabled, among others, Conan installs the external
|
||||
If `user.mp-units.build:all` is enabled, among others, Conan installs the external
|
||||
[wg21-linear_algebra](https://conan.io/center/recipes/wg21-linear_algebra)
|
||||
dependency and enables the compilation of linear algebra-based tests and usage examples.
|
||||
Such behavior can be disabled with this option.
|
||||
|
||||
[skip la support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
|
||||
[skip la support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
|
||||
|
||||
|
||||
### CMake options
|
||||
@ -453,11 +453,11 @@ In case you would like to build all the **mp-units** source code (with unit test
|
||||
you should:
|
||||
|
||||
1. Use the _CMakeLists.txt_ from the top-level directory.
|
||||
2. Run Conan with [`user.build:all`](#user-build-all) = `True`.
|
||||
2. Run Conan with [`user.mp-units.build:all`](#user.mp-units.build-all) = `True`.
|
||||
|
||||
```shell
|
||||
git clone https://github.com/mpusz/mp-units.git && cd units
|
||||
conan build . -pr <your_conan_profile> -s compiler.cppstd=23 -o cxx_modules=True -c user.build:all=True -b missing
|
||||
conan build . -pr <your_conan_profile> -s compiler.cppstd=23 -o cxx_modules=True -c user.mp-units.build:all=True -b missing
|
||||
```
|
||||
|
||||
The above will download and install all of the dependencies needed for the development of the library,
|
||||
@ -504,7 +504,7 @@ After that, you can either:
|
||||
To test CMake installation and Conan packaging or create a Conan package run:
|
||||
|
||||
```shell
|
||||
conan create . --user <username> --channel <channel> -pr <your_conan_profile> -s compiler.cppstd=20 -o cxx_modules=True -c user.build:all=True -b missing
|
||||
conan create . --user <username> --channel <channel> -pr <your_conan_profile> -s compiler.cppstd=20 -o cxx_modules=True -c user.mp-units.build:all=True -b missing
|
||||
```
|
||||
|
||||
The above will create a Conan package and run tests provided in _./test_package_ directory.
|
||||
|
@ -392,4 +392,9 @@ static_assert(same_type<kind_of<isq::length> / isq::time, isq::length / isq::tim
|
||||
|
||||
Only a root quantity from the hierarchy tree or the one marked with `is_kind` specifier
|
||||
in the `quantity_spec` definition can be put as a template parameter to the `kind_of`
|
||||
specifier. For example, `kind_of<isq::width>` will fail to compile.
|
||||
specifier. For example, `kind_of<isq::width>` will fail to compile. However, we can call
|
||||
`get_kind(q)` to obtain a kind of any quantity:
|
||||
|
||||
```cpp
|
||||
static_assert(get_kind(isq::width) == kind_of<isq::length>);
|
||||
```
|
||||
|
@ -50,13 +50,13 @@ QuantityOf<isq::mechanical_energy> auto total_energy(QuantityOf<isq::momentum> a
|
||||
void si_example()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
constexpr auto GeV = si::giga<si::electronvolt>;
|
||||
constexpr QuantityOf<isq::speed> auto c = 1. * si::si2019::speed_of_light_in_vacuum;
|
||||
auto c2 = pow<2>(c);
|
||||
constexpr Unit auto GeV = si::giga<si::electronvolt>;
|
||||
constexpr quantity c = 1. * si::si2019::speed_of_light_in_vacuum;
|
||||
quantity c2 = pow<2>(c);
|
||||
|
||||
const auto p1 = isq::momentum(4. * GeV / c);
|
||||
const quantity p1 = isq::momentum(4. * GeV / c);
|
||||
const QuantityOf<isq::mass> auto m1 = 3. * GeV / c2;
|
||||
const auto E = total_energy(p1, m1, c);
|
||||
const quantity E = total_energy(p1, m1, c);
|
||||
|
||||
std::cout << "\n*** SI units (c = " << c << " = " << c.in(si::metre / s) << ") ***\n";
|
||||
|
||||
@ -65,18 +65,18 @@ void si_example()
|
||||
<< "m = " << m1 << "\n"
|
||||
<< "E = " << E << "\n";
|
||||
|
||||
const auto p2 = p1.in(GeV / (m / s));
|
||||
const auto m2 = m1.in(GeV / pow<2>(m / s));
|
||||
const auto E2 = total_energy(p2, m2, c).in(GeV);
|
||||
const quantity p2 = p1.in(GeV / (m / s));
|
||||
const quantity m2 = m1.in(GeV / pow<2>(m / s));
|
||||
const quantity E2 = total_energy(p2, m2, c).in(GeV);
|
||||
|
||||
std::cout << "\n[in `GeV`]\n"
|
||||
<< "p = " << p2 << "\n"
|
||||
<< "m = " << m2 << "\n"
|
||||
<< "E = " << E2 << "\n";
|
||||
|
||||
const auto p3 = p1.in(kg * m / s);
|
||||
const auto m3 = m1.in(kg);
|
||||
const auto E3 = total_energy(p3, m3, c).in(J);
|
||||
const quantity p3 = p1.in(kg * m / s);
|
||||
const quantity m3 = m1.in(kg);
|
||||
const quantity E3 = total_energy(p3, m3, c).in(J);
|
||||
|
||||
std::cout << "\n[in SI base units]\n"
|
||||
<< "p = " << p3 << "\n"
|
||||
@ -92,10 +92,10 @@ void natural_example()
|
||||
using namespace mp_units::natural;
|
||||
using namespace mp_units::natural::unit_symbols;
|
||||
|
||||
constexpr auto c = 1. * speed_of_light;
|
||||
const auto p = 4. * momentum[GeV];
|
||||
const auto m = 3. * mass[GeV];
|
||||
const auto E = total_energy(p, m, c);
|
||||
constexpr quantity c = 1. * speed_of_light;
|
||||
const quantity p = 4. * momentum[GeV];
|
||||
const quantity m = 3. * mass[GeV];
|
||||
const quantity E = total_energy(p, m, c);
|
||||
|
||||
std::cout << "\n*** Natural units (c = " << c << ") ***\n"
|
||||
<< "p = " << p << "\n"
|
||||
|
@ -83,7 +83,7 @@
|
||||
// TODO revise the below when clang-18 is released
|
||||
#if MP_UNITS_COMP_CLANG >= 18 && !defined __cpp_explicit_this_parameter
|
||||
|
||||
#define __cpp_explicit_this_parameter
|
||||
#define __cpp_explicit_this_parameter 202110L
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -130,7 +130,7 @@ concept QuantitySpec =
|
||||
detail::NamedQuantitySpec<T> || detail::IntermediateDerivedQuantitySpec<T> || detail::QuantityKindSpec<T>;
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval QuantitySpec auto get_kind(Q q);
|
||||
[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q);
|
||||
|
||||
namespace detail {
|
||||
|
||||
@ -138,7 +138,7 @@ template<auto To, auto From>
|
||||
concept NestedQuantityKindSpecOf =
|
||||
QuantitySpec<std::remove_const_t<decltype(From)>> && QuantitySpec<std::remove_const_t<decltype(To)>> &&
|
||||
get_kind(From) != get_kind(To) &&
|
||||
std::derived_from<std::remove_cvref_t<decltype(To)>, std::remove_cvref_t<decltype(get_kind(From))>>;
|
||||
std::derived_from<std::remove_cvref_t<decltype(To)>, std::remove_cvref_t<decltype(get_kind(From)._quantity_spec_)>>;
|
||||
|
||||
}
|
||||
|
||||
|
@ -444,11 +444,15 @@ namespace detail {
|
||||
template<typename T>
|
||||
concept QuantitySpecWithNoSpecifiers = detail::NamedQuantitySpec<T> || detail::IntermediateDerivedQuantitySpec<T>;
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval QuantitySpec auto get_kind_tree_root(Q q);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#ifdef __cpp_explicit_this_parameter
|
||||
template<auto Q>
|
||||
requires(detail::QuantitySpecWithNoSpecifiers<std::remove_const_t<decltype(Q)>>) && (get_kind(Q) == Q)
|
||||
requires(detail::QuantitySpecWithNoSpecifiers<std::remove_const_t<decltype(Q)>>) &&
|
||||
(detail::get_kind_tree_root(Q) == Q)
|
||||
struct kind_of_<Q> : std::remove_const_t<decltype(Q)> {
|
||||
static constexpr auto _quantity_spec_ = Q;
|
||||
};
|
||||
@ -456,10 +460,11 @@ struct kind_of_<Q> : std::remove_const_t<decltype(Q)> {
|
||||
|
||||
#if MP_UNITS_COMP_CLANG
|
||||
template<auto Q>
|
||||
requires detail::QuantitySpecWithNoSpecifiers<std::remove_cvref_t<decltype(Q)>> && (get_kind(Q) == Q)
|
||||
requires detail::QuantitySpecWithNoSpecifiers<std::remove_cvref_t<decltype(Q)>> &&
|
||||
(detail::get_kind_tree_root(Q) == Q)
|
||||
#else
|
||||
template<detail::QuantitySpecWithNoSpecifiers auto Q>
|
||||
requires(get_kind(Q) == Q)
|
||||
requires(detail::get_kind_tree_root(Q) == Q)
|
||||
#endif
|
||||
struct kind_of_<Q> : quantity_spec<kind_of_<Q>, Q> {
|
||||
static constexpr auto _quantity_spec_ = Q;
|
||||
@ -467,7 +472,7 @@ struct kind_of_<Q> : quantity_spec<kind_of_<Q>, Q> {
|
||||
#endif
|
||||
|
||||
template<detail::QuantitySpecWithNoSpecifiers auto Q>
|
||||
requires(get_kind(Q) == Q)
|
||||
requires(detail::get_kind_tree_root(Q) == Q)
|
||||
inline constexpr kind_of_<Q> kind_of;
|
||||
|
||||
namespace detail {
|
||||
@ -484,6 +489,15 @@ template<QuantitySpec auto... From, QuantitySpec Q>
|
||||
return q;
|
||||
}
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval auto remove_kind(Q q)
|
||||
{
|
||||
if constexpr (detail::QuantityKindSpec<Q>)
|
||||
return Q::_quantity_spec_;
|
||||
else
|
||||
return q;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Operators
|
||||
@ -493,7 +507,7 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||
{
|
||||
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
||||
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||
remove_kind(lhs), remove_kind(rhs)));
|
||||
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
||||
}
|
||||
|
||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||
@ -501,7 +515,7 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||
{
|
||||
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
||||
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||
remove_kind(lhs), remove_kind(rhs)));
|
||||
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
||||
}
|
||||
|
||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||
@ -538,13 +552,13 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
||||
else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>)
|
||||
return detail::clone_kind_of<Q{}>(
|
||||
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||
remove_kind(q)));
|
||||
detail::remove_kind(q)));
|
||||
else if constexpr (Den == 1)
|
||||
return detail::clone_kind_of<Q{}>(
|
||||
derived_quantity_spec<power<std::remove_const_t<decltype(remove_kind(Q{}))>, Num>>{});
|
||||
derived_quantity_spec<power<std::remove_const_t<decltype(detail::remove_kind(Q{}))>, Num>>{});
|
||||
else
|
||||
return detail::clone_kind_of<Q{}>(
|
||||
derived_quantity_spec<power<std::remove_const_t<decltype(remove_kind(Q{}))>, Num, Den>>{});
|
||||
derived_quantity_spec<power<std::remove_const_t<decltype(detail::remove_kind(Q{}))>, Num, Den>>{});
|
||||
}
|
||||
|
||||
|
||||
@ -1315,8 +1329,8 @@ template<QuantitySpec From, QuantitySpec To>
|
||||
else if constexpr (From{} == To{})
|
||||
return yes;
|
||||
else if constexpr (QuantityKindSpec<From> || QuantityKindSpec<To>) {
|
||||
constexpr auto from_kind = get_kind(From{});
|
||||
constexpr auto to_kind = get_kind(To{});
|
||||
constexpr auto from_kind = get_kind_tree_root(From{});
|
||||
constexpr auto to_kind = get_kind_tree_root(To{});
|
||||
constexpr auto exploded_kind_result = [](specs_convertible_result res) {
|
||||
using enum specs_convertible_result;
|
||||
return res == no ? no : yes;
|
||||
@ -1327,11 +1341,11 @@ template<QuantitySpec From, QuantitySpec To>
|
||||
return convertible_impl(from_kind, to_kind);
|
||||
else if constexpr (get_complexity(from_kind) > get_complexity(to_kind))
|
||||
return exploded_kind_result(
|
||||
convertible_impl(get_kind(explode<get_complexity(to_kind)>(from_kind).quantity), to_kind));
|
||||
convertible_impl(get_kind_tree_root(explode<get_complexity(to_kind)>(from_kind).quantity), to_kind));
|
||||
else
|
||||
return exploded_kind_result(
|
||||
convertible_impl(from_kind, get_kind(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
||||
} else if constexpr (NestedQuantityKindSpecOf<get_kind(To{}), from> && get_kind(To{}) == To{})
|
||||
convertible_impl(from_kind, get_kind_tree_root(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
||||
} else if constexpr (NestedQuantityKindSpecOf<get_kind_tree_root(To{}), from> && get_kind_tree_root(To{}) == To{})
|
||||
return yes;
|
||||
else if constexpr (NamedQuantitySpec<From> && NamedQuantitySpec<To>) {
|
||||
if constexpr (have_common_base(From{}, To{})) {
|
||||
@ -1401,8 +1415,8 @@ template<QuantitySpec QS1, QuantitySpec QS2>
|
||||
namespace detail {
|
||||
|
||||
template<QuantitySpec Q>
|
||||
requires requires(Q q) { get_kind(q); }
|
||||
using to_kind = std::remove_const_t<decltype(get_kind(Q{}))>;
|
||||
requires requires(Q q) { get_kind_tree_root(q); }
|
||||
using to_kind = std::remove_const_t<decltype(get_kind_tree_root(Q{}))>;
|
||||
|
||||
#ifdef __cpp_explicit_this_parameter
|
||||
template<NamedQuantitySpec auto QS, auto... Args>
|
||||
@ -1415,19 +1429,8 @@ template<typename Self, NamedQuantitySpec auto QS, auto... Args>
|
||||
return contains<struct is_kind, Args...>();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval auto remove_kind(Q q)
|
||||
{
|
||||
if constexpr (detail::QuantityKindSpec<Q>)
|
||||
return Q::_quantity_spec_;
|
||||
else
|
||||
return q;
|
||||
}
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval QuantitySpec auto get_kind(Q q)
|
||||
[[nodiscard]] consteval QuantitySpec auto get_kind_tree_root(Q q)
|
||||
{
|
||||
auto defined_as_kind = []<typename QQ>(QQ qq) {
|
||||
if constexpr (requires { detail::defined_as_kind(qq); })
|
||||
@ -1441,7 +1444,7 @@ template<QuantitySpec Q>
|
||||
} else if constexpr (defined_as_kind(Q{})) {
|
||||
return q;
|
||||
} else if constexpr (requires { Q::_parent_; }) {
|
||||
return get_kind(Q::_parent_);
|
||||
return get_kind_tree_root(Q::_parent_);
|
||||
} else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>) {
|
||||
return detail::expr_map<detail::to_kind, derived_quantity_spec, struct dimensionless,
|
||||
detail::type_list_of_quantity_spec_less>(q);
|
||||
@ -1451,20 +1454,29 @@ template<QuantitySpec Q>
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q)
|
||||
{
|
||||
return kind_of<detail::get_kind_tree_root(q)>;
|
||||
}
|
||||
|
||||
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q) { return q; }
|
||||
|
||||
template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(Q1 q1, Q2 q2)
|
||||
requires(implicitly_convertible(get_kind(q1), get_kind(q2)) || implicitly_convertible(get_kind(q2), get_kind(q1)))
|
||||
requires(implicitly_convertible(get_kind_tree_root(q1), get_kind_tree_root(q2)) ||
|
||||
implicitly_convertible(get_kind_tree_root(q2), get_kind_tree_root(q1)))
|
||||
{
|
||||
using QQ1 = std::remove_const_t<decltype(remove_kind(q1))>;
|
||||
using QQ2 = std::remove_const_t<decltype(remove_kind(q2))>;
|
||||
using QQ1 = std::remove_const_t<decltype(detail::remove_kind(q1))>;
|
||||
using QQ2 = std::remove_const_t<decltype(detail::remove_kind(q2))>;
|
||||
if constexpr (is_same_v<Q1, Q2>)
|
||||
return q1;
|
||||
else if constexpr (detail::NestedQuantityKindSpecOf<Q1{}, Q2{}>)
|
||||
return remove_kind(q1);
|
||||
return detail::remove_kind(q1);
|
||||
else if constexpr (detail::NestedQuantityKindSpecOf<Q2{}, Q1{}>)
|
||||
return remove_kind(q2);
|
||||
return detail::remove_kind(q2);
|
||||
else if constexpr ((detail::QuantityKindSpec<Q1> && !detail::QuantityKindSpec<Q2>) ||
|
||||
(detail::IntermediateDerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
||||
implicitly_convertible(Q1{}, Q2{})))
|
||||
@ -1479,10 +1491,10 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
return q2;
|
||||
else if constexpr (implicitly_convertible(Q2{}, Q1{}))
|
||||
return q1;
|
||||
else if constexpr (implicitly_convertible(get_kind(Q1{}), get_kind(Q2{})))
|
||||
return get_kind(q2);
|
||||
else if constexpr (implicitly_convertible(get_kind_tree_root(Q1{}), get_kind_tree_root(Q2{})))
|
||||
return get_kind_tree_root(q2);
|
||||
else
|
||||
return get_kind(q1);
|
||||
return get_kind_tree_root(q1);
|
||||
}
|
||||
|
||||
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q1, QuantitySpec auto q2,
|
||||
|
@ -27,23 +27,23 @@
|
||||
namespace mp_units::iec80000 {
|
||||
|
||||
// clang-format off
|
||||
template<PrefixableUnit auto U> struct kibi_ : prefixed_unit<"Ki", mag_power<2, 10>, U> {};
|
||||
template<PrefixableUnit auto U> struct mebi_ : prefixed_unit<"Mi", mag_power<2, 20>, U> {};
|
||||
template<PrefixableUnit auto U> struct gibi_ : prefixed_unit<"Gi", mag_power<2, 30>, U> {};
|
||||
template<PrefixableUnit auto U> struct tebi_ : prefixed_unit<"Ti", mag_power<2, 40>, U> {};
|
||||
template<PrefixableUnit auto U> struct pebi_ : prefixed_unit<"Pi", mag_power<2, 50>, U> {};
|
||||
template<PrefixableUnit auto U> struct exbi_ : prefixed_unit<"Ei", mag_power<2, 60>, U> {};
|
||||
template<PrefixableUnit auto U> struct zebi_ : prefixed_unit<"Zi", mag_power<2, 70>, U> {};
|
||||
template<PrefixableUnit auto U> struct yobi_ : prefixed_unit<"Yi", mag_power<2, 80>, U> {};
|
||||
template<PrefixableUnit U> struct kibi_ : prefixed_unit<"Ki", mag_power<2, 10>, U{}> {};
|
||||
template<PrefixableUnit U> struct mebi_ : prefixed_unit<"Mi", mag_power<2, 20>, U{}> {};
|
||||
template<PrefixableUnit U> struct gibi_ : prefixed_unit<"Gi", mag_power<2, 30>, U{}> {};
|
||||
template<PrefixableUnit U> struct tebi_ : prefixed_unit<"Ti", mag_power<2, 40>, U{}> {};
|
||||
template<PrefixableUnit U> struct pebi_ : prefixed_unit<"Pi", mag_power<2, 50>, U{}> {};
|
||||
template<PrefixableUnit U> struct exbi_ : prefixed_unit<"Ei", mag_power<2, 60>, U{}> {};
|
||||
template<PrefixableUnit U> struct zebi_ : prefixed_unit<"Zi", mag_power<2, 70>, U{}> {};
|
||||
template<PrefixableUnit U> struct yobi_ : prefixed_unit<"Yi", mag_power<2, 80>, U{}> {};
|
||||
|
||||
template<PrefixableUnit auto U> inline constexpr kibi_<U> kibi;
|
||||
template<PrefixableUnit auto U> inline constexpr mebi_<U> mebi;
|
||||
template<PrefixableUnit auto U> inline constexpr gibi_<U> gibi;
|
||||
template<PrefixableUnit auto U> inline constexpr tebi_<U> tebi;
|
||||
template<PrefixableUnit auto U> inline constexpr pebi_<U> pebi;
|
||||
template<PrefixableUnit auto U> inline constexpr exbi_<U> exbi;
|
||||
template<PrefixableUnit auto U> inline constexpr zebi_<U> zebi;
|
||||
template<PrefixableUnit auto U> inline constexpr yobi_<U> yobi;
|
||||
template<PrefixableUnit auto U> inline constexpr kibi_<std::remove_const_t<decltype(U)>> kibi;
|
||||
template<PrefixableUnit auto U> inline constexpr mebi_<std::remove_const_t<decltype(U)>> mebi;
|
||||
template<PrefixableUnit auto U> inline constexpr gibi_<std::remove_const_t<decltype(U)>> gibi;
|
||||
template<PrefixableUnit auto U> inline constexpr tebi_<std::remove_const_t<decltype(U)>> tebi;
|
||||
template<PrefixableUnit auto U> inline constexpr pebi_<std::remove_const_t<decltype(U)>> pebi;
|
||||
template<PrefixableUnit auto U> inline constexpr exbi_<std::remove_const_t<decltype(U)>> exbi;
|
||||
template<PrefixableUnit auto U> inline constexpr zebi_<std::remove_const_t<decltype(U)>> zebi;
|
||||
template<PrefixableUnit auto U> inline constexpr yobi_<std::remove_const_t<decltype(U)>> yobi;
|
||||
// clang-format on
|
||||
|
||||
} // namespace mp_units::iec80000
|
||||
|
@ -27,55 +27,55 @@
|
||||
namespace mp_units::si {
|
||||
|
||||
// clang-format off
|
||||
template<PrefixableUnit auto U> struct quecto_ : prefixed_unit<"q", mag_power<10, -30>, U> {};
|
||||
template<PrefixableUnit auto U> struct ronto_ : prefixed_unit<"r", mag_power<10, -27>, U> {};
|
||||
template<PrefixableUnit auto U> struct yocto_ : prefixed_unit<"y", mag_power<10, -24>, U> {};
|
||||
template<PrefixableUnit auto U> struct zepto_ : prefixed_unit<"z", mag_power<10, -21>, U> {};
|
||||
template<PrefixableUnit auto U> struct atto_ : prefixed_unit<"a", mag_power<10, -18>, U> {};
|
||||
template<PrefixableUnit auto U> struct femto_ : prefixed_unit<"f", mag_power<10, -15>, U> {};
|
||||
template<PrefixableUnit auto U> struct pico_ : prefixed_unit<"p", mag_power<10, -12>, U> {};
|
||||
template<PrefixableUnit auto U> struct nano_ : prefixed_unit<"n", mag_power<10, -9>, U> {};
|
||||
template<PrefixableUnit auto U> struct micro_ : prefixed_unit<basic_symbol_text{"µ", "u"}, mag_power<10, -6>, U> {};
|
||||
template<PrefixableUnit auto U> struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U> {};
|
||||
template<PrefixableUnit auto U> struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U> {};
|
||||
template<PrefixableUnit auto U> struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U> {};
|
||||
template<PrefixableUnit auto U> struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U> {};
|
||||
template<PrefixableUnit auto U> struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U> {};
|
||||
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
|
||||
template<PrefixableUnit auto U> struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U> {};
|
||||
template<PrefixableUnit auto U> struct giga_ : prefixed_unit<"G", mag_power<10, 9>, U> {};
|
||||
template<PrefixableUnit auto U> struct tera_ : prefixed_unit<"T", mag_power<10, 12>, U> {};
|
||||
template<PrefixableUnit auto U> struct peta_ : prefixed_unit<"P", mag_power<10, 15>, U> {};
|
||||
template<PrefixableUnit auto U> struct exa_ : prefixed_unit<"E", mag_power<10, 18>, U> {};
|
||||
template<PrefixableUnit auto U> struct zetta_ : prefixed_unit<"Z", mag_power<10, 21>, U> {};
|
||||
template<PrefixableUnit auto U> struct yotta_ : prefixed_unit<"Y", mag_power<10, 24>, U> {};
|
||||
template<PrefixableUnit auto U> struct ronna_ : prefixed_unit<"R", mag_power<10, 27>, U> {};
|
||||
template<PrefixableUnit auto U> struct quetta_ : prefixed_unit<"Q", mag_power<10, 30>, U> {};
|
||||
template<PrefixableUnit U> struct quecto_ : prefixed_unit<"q", mag_power<10, -30>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronto_ : prefixed_unit<"r", mag_power<10, -27>, U{}> {};
|
||||
template<PrefixableUnit U> struct yocto_ : prefixed_unit<"y", mag_power<10, -24>, U{}> {};
|
||||
template<PrefixableUnit U> struct zepto_ : prefixed_unit<"z", mag_power<10, -21>, U{}> {};
|
||||
template<PrefixableUnit U> struct atto_ : prefixed_unit<"a", mag_power<10, -18>, U{}> {};
|
||||
template<PrefixableUnit U> struct femto_ : prefixed_unit<"f", mag_power<10, -15>, U{}> {};
|
||||
template<PrefixableUnit U> struct pico_ : prefixed_unit<"p", mag_power<10, -12>, U{}> {};
|
||||
template<PrefixableUnit U> struct nano_ : prefixed_unit<"n", mag_power<10, -9>, U{}> {};
|
||||
template<PrefixableUnit U> struct micro_ : prefixed_unit<basic_symbol_text{"µ", "u"}, mag_power<10, -6>, U{}> {};
|
||||
template<PrefixableUnit U> struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U{}> {};
|
||||
template<PrefixableUnit U> struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U{}> {};
|
||||
template<PrefixableUnit U> struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U{}> {};
|
||||
template<PrefixableUnit U> struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U{}> {};
|
||||
template<PrefixableUnit U> struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U{}> {};
|
||||
template<PrefixableUnit U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U{}> {};
|
||||
template<PrefixableUnit U> struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U{}> {};
|
||||
template<PrefixableUnit U> struct giga_ : prefixed_unit<"G", mag_power<10, 9>, U{}> {};
|
||||
template<PrefixableUnit U> struct tera_ : prefixed_unit<"T", mag_power<10, 12>, U{}> {};
|
||||
template<PrefixableUnit U> struct peta_ : prefixed_unit<"P", mag_power<10, 15>, U{}> {};
|
||||
template<PrefixableUnit U> struct exa_ : prefixed_unit<"E", mag_power<10, 18>, U{}> {};
|
||||
template<PrefixableUnit U> struct zetta_ : prefixed_unit<"Z", mag_power<10, 21>, U{}> {};
|
||||
template<PrefixableUnit U> struct yotta_ : prefixed_unit<"Y", mag_power<10, 24>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronna_ : prefixed_unit<"R", mag_power<10, 27>, U{}> {};
|
||||
template<PrefixableUnit U> struct quetta_ : prefixed_unit<"Q", mag_power<10, 30>, U{}> {};
|
||||
|
||||
template<PrefixableUnit auto U> inline constexpr quecto_<U> quecto;
|
||||
template<PrefixableUnit auto U> inline constexpr ronto_<U> ronto;
|
||||
template<PrefixableUnit auto U> inline constexpr yocto_<U> yocto;
|
||||
template<PrefixableUnit auto U> inline constexpr zepto_<U> zepto;
|
||||
template<PrefixableUnit auto U> inline constexpr atto_<U> atto;
|
||||
template<PrefixableUnit auto U> inline constexpr femto_<U> femto;
|
||||
template<PrefixableUnit auto U> inline constexpr pico_<U> pico;
|
||||
template<PrefixableUnit auto U> inline constexpr nano_<U> nano;
|
||||
template<PrefixableUnit auto U> inline constexpr micro_<U> micro;
|
||||
template<PrefixableUnit auto U> inline constexpr milli_<U> milli;
|
||||
template<PrefixableUnit auto U> inline constexpr centi_<U> centi;
|
||||
template<PrefixableUnit auto U> inline constexpr deci_<U> deci;
|
||||
template<PrefixableUnit auto U> inline constexpr deca_<U> deca;
|
||||
template<PrefixableUnit auto U> inline constexpr hecto_<U> hecto;
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<U> kilo;
|
||||
template<PrefixableUnit auto U> inline constexpr mega_<U> mega;
|
||||
template<PrefixableUnit auto U> inline constexpr giga_<U> giga;
|
||||
template<PrefixableUnit auto U> inline constexpr tera_<U> tera;
|
||||
template<PrefixableUnit auto U> inline constexpr peta_<U> peta;
|
||||
template<PrefixableUnit auto U> inline constexpr exa_<U> exa;
|
||||
template<PrefixableUnit auto U> inline constexpr zetta_<U> zetta;
|
||||
template<PrefixableUnit auto U> inline constexpr yotta_<U> yotta;
|
||||
template<PrefixableUnit auto U> inline constexpr ronna_<U> ronna;
|
||||
template<PrefixableUnit auto U> inline constexpr quetta_<U> quetta;
|
||||
template<PrefixableUnit auto U> inline constexpr quecto_<std::remove_const_t<decltype(U)>> quecto;
|
||||
template<PrefixableUnit auto U> inline constexpr ronto_<std::remove_const_t<decltype(U)>> ronto;
|
||||
template<PrefixableUnit auto U> inline constexpr yocto_<std::remove_const_t<decltype(U)>> yocto;
|
||||
template<PrefixableUnit auto U> inline constexpr zepto_<std::remove_const_t<decltype(U)>> zepto;
|
||||
template<PrefixableUnit auto U> inline constexpr atto_<std::remove_const_t<decltype(U)>> atto;
|
||||
template<PrefixableUnit auto U> inline constexpr femto_<std::remove_const_t<decltype(U)>> femto;
|
||||
template<PrefixableUnit auto U> inline constexpr pico_<std::remove_const_t<decltype(U)>> pico;
|
||||
template<PrefixableUnit auto U> inline constexpr nano_<std::remove_const_t<decltype(U)>> nano;
|
||||
template<PrefixableUnit auto U> inline constexpr micro_<std::remove_const_t<decltype(U)>> micro;
|
||||
template<PrefixableUnit auto U> inline constexpr milli_<std::remove_const_t<decltype(U)>> milli;
|
||||
template<PrefixableUnit auto U> inline constexpr centi_<std::remove_const_t<decltype(U)>> centi;
|
||||
template<PrefixableUnit auto U> inline constexpr deci_<std::remove_const_t<decltype(U)>> deci;
|
||||
template<PrefixableUnit auto U> inline constexpr deca_<std::remove_const_t<decltype(U)>> deca;
|
||||
template<PrefixableUnit auto U> inline constexpr hecto_<std::remove_const_t<decltype(U)>> hecto;
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<std::remove_const_t<decltype(U)>> kilo;
|
||||
template<PrefixableUnit auto U> inline constexpr mega_<std::remove_const_t<decltype(U)>> mega;
|
||||
template<PrefixableUnit auto U> inline constexpr giga_<std::remove_const_t<decltype(U)>> giga;
|
||||
template<PrefixableUnit auto U> inline constexpr tera_<std::remove_const_t<decltype(U)>> tera;
|
||||
template<PrefixableUnit auto U> inline constexpr peta_<std::remove_const_t<decltype(U)>> peta;
|
||||
template<PrefixableUnit auto U> inline constexpr exa_<std::remove_const_t<decltype(U)>> exa;
|
||||
template<PrefixableUnit auto U> inline constexpr zetta_<std::remove_const_t<decltype(U)>> zetta;
|
||||
template<PrefixableUnit auto U> inline constexpr yotta_<std::remove_const_t<decltype(U)>> yotta;
|
||||
template<PrefixableUnit auto U> inline constexpr ronna_<std::remove_const_t<decltype(U)>> ronna;
|
||||
template<PrefixableUnit auto U> inline constexpr quetta_<std::remove_const_t<decltype(U)>> quetta;
|
||||
// clang-format on
|
||||
|
||||
} // namespace mp_units::si
|
||||
|
@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
find_package(Catch2 3 REQUIRED)
|
||||
|
||||
add_executable(unit_tests_runtime distribution_test.cpp fmt_test.cpp math_test.cpp)
|
||||
add_executable(unit_tests_runtime distribution_test.cpp fmt_test.cpp math_test.cpp atomic_test.cpp)
|
||||
if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
target_compile_definitions(unit_tests_runtime PUBLIC ${projectPrefix}MODULES)
|
||||
endif()
|
||||
|
37
test/runtime/atomic_test.cpp
Normal file
37
test/runtime/atomic_test.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2024 Nick Thompson
|
||||
//
|
||||
// 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 <catch2/catch_all.hpp>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si/unit_symbols.h>
|
||||
#include <mp-units/systems/si/units.h>
|
||||
#include <atomic>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
TEST_CASE("std::atomic works with dimensioned types", "[atomic][assignment]")
|
||||
{
|
||||
std::atomic<quantity<isq::area[m2]>> a1 = 3.0 * isq::area[m2];
|
||||
std::atomic<quantity<isq::area[m2]>> a2 = 3.0 * isq::area[m2];
|
||||
REQUIRE(a1.load() == a2.load());
|
||||
}
|
@ -396,25 +396,25 @@ static_assert(acceleration * (time * time) != position_vector);
|
||||
static_assert(acceleration / speed != frequency);
|
||||
|
||||
// get_kind
|
||||
static_assert(get_kind(length) == length);
|
||||
static_assert(get_kind(distance) == length);
|
||||
static_assert(get_kind(time) == time);
|
||||
static_assert(get_kind(period_duration) == time);
|
||||
static_assert(get_kind(length / time) == length / time);
|
||||
static_assert(get_kind(speed) == speed);
|
||||
static_assert(get_kind(height / time) == length / time);
|
||||
static_assert(get_kind(inverse(time)) == inverse(time));
|
||||
static_assert(get_kind(inverse(period_duration)) == inverse(time));
|
||||
static_assert(get_kind(frequency) == frequency);
|
||||
static_assert(get_kind(mass * frequency) == mass * frequency);
|
||||
static_assert(get_kind(moment_of_force) == moment_of_force);
|
||||
static_assert(get_kind(energy) == energy);
|
||||
static_assert(get_kind(potential_energy) == energy);
|
||||
static_assert(get_kind(kinetic_energy) == energy);
|
||||
static_assert(get_kind(pow<1, 2>(area)) == pow<1, 2>(area));
|
||||
static_assert(get_kind(angular_measure) == angular_measure);
|
||||
static_assert(get_kind(phase_angle) == angular_measure);
|
||||
static_assert(get_kind(rotational_displacement) == angular_measure);
|
||||
static_assert(get_kind(length) == kind_of<length>);
|
||||
static_assert(get_kind(distance) == kind_of<length>);
|
||||
static_assert(get_kind(time) == kind_of<time>);
|
||||
static_assert(get_kind(period_duration) == kind_of<time>);
|
||||
static_assert(get_kind(length / time) == kind_of<length / time>);
|
||||
static_assert(get_kind(speed) == kind_of<speed>);
|
||||
static_assert(get_kind(height / time) == kind_of<length / time>);
|
||||
static_assert(get_kind(inverse(time)) == kind_of<inverse(time)>);
|
||||
static_assert(get_kind(inverse(period_duration)) == kind_of<inverse(time)>);
|
||||
static_assert(get_kind(frequency) == kind_of<frequency>);
|
||||
static_assert(get_kind(mass * frequency) == kind_of<mass * frequency>);
|
||||
static_assert(get_kind(moment_of_force) == kind_of<moment_of_force>);
|
||||
static_assert(get_kind(energy) == kind_of<energy>);
|
||||
static_assert(get_kind(potential_energy) == kind_of<energy>);
|
||||
static_assert(get_kind(kinetic_energy) == kind_of<energy>);
|
||||
static_assert(get_kind(pow<1, 2>(area)) == kind_of<pow<1, 2>(area)>);
|
||||
static_assert(get_kind(angular_measure) == kind_of<angular_measure>);
|
||||
static_assert(get_kind(phase_angle) == kind_of<angular_measure>);
|
||||
static_assert(get_kind(rotational_displacement) == kind_of<angular_measure>);
|
||||
|
||||
// comparisons of the same dimensions
|
||||
static_assert(length == length);
|
||||
@ -507,7 +507,7 @@ static_assert(convertible_impl(width, width) == yes);
|
||||
static_assert(convertible_impl(energy, energy) == yes);
|
||||
static_assert(convertible_impl(kind_of<length>, kind_of<length>) == yes);
|
||||
static_assert(convertible_impl(kind_of<energy>, kind_of<energy>) == yes);
|
||||
static_assert(convertible_impl(kind_of<get_kind(moment_of_force)>, kind_of<get_kind(moment_of_force)>) == yes);
|
||||
static_assert(convertible_impl(get_kind(moment_of_force), get_kind(moment_of_force)) == yes);
|
||||
|
||||
// converting to a different branch
|
||||
static_assert(convertible_impl(height, width) == cast);
|
||||
|
@ -520,7 +520,8 @@ static_assert(is_of_type<1 * percent * (1 * m), quantity<derived_unit<struct per
|
||||
|
||||
static_assert(is_of_type<1 * m / (1 * s), quantity<derived_unit<struct si::metre, per<struct si::second>>{}, int>>);
|
||||
static_assert(is_of_type<1 * m / (1 * m), quantity<one, int>>);
|
||||
static_assert(is_of_type<1 * km / (1 * m), quantity<derived_unit<si::kilo_<si::metre>, per<struct si::metre>>{}, int>>);
|
||||
static_assert(
|
||||
is_of_type<1 * km / (1 * m), quantity<derived_unit<si::kilo_<struct si::metre>, per<struct si::metre>>{}, int>>);
|
||||
|
||||
static_assert(is_of_type<1 * m / 1, quantity<si::metre, int>>);
|
||||
static_assert(is_of_type<1 * m / (1 * one), quantity<si::metre, int>>);
|
||||
@ -568,7 +569,7 @@ static_assert(is_of_type<1 * percent * (1. * m), quantity<derived_unit<struct pe
|
||||
static_assert(is_of_type<1 * m / (1. * s), quantity<derived_unit<struct si::metre, per<struct si::second>>{}, double>>);
|
||||
static_assert(is_of_type<1. * m / (1 * m), quantity<one, double>>);
|
||||
static_assert(
|
||||
is_of_type<1. * km / (1 * m), quantity<derived_unit<si::kilo_<si::metre>, per<struct si::metre>>{}, double>>);
|
||||
is_of_type<1. * km / (1 * m), quantity<derived_unit<si::kilo_<struct si::metre>, per<struct si::metre>>{}, double>>);
|
||||
|
||||
static_assert(is_of_type<1. * m / 1, quantity<si::metre, double>>);
|
||||
static_assert(is_of_type<1 * m / (1. * one), quantity<si::metre, double>>);
|
||||
@ -612,11 +613,12 @@ static_assert(is_of_type<1 * m * (1 * min), quantity<derived_unit<struct si::met
|
||||
static_assert(is_of_type<1 * s * (1 * Hz), quantity<derived_unit<struct si::hertz, struct si::second>{}, int>>);
|
||||
static_assert(is_of_type<1 / (1 * min), quantity<derived_unit<struct one, per<struct si::minute>>{}, int>>);
|
||||
static_assert(is_of_type<1 / (1 * Hz), quantity<derived_unit<struct one, per<struct si::hertz>>{}, int>>);
|
||||
static_assert(is_of_type<1 / (1 * km), quantity<derived_unit<struct one, per<si::kilo_<si::metre>>>{}, int>>);
|
||||
static_assert(is_of_type<1 / (1 * km), quantity<derived_unit<struct one, per<si::kilo_<struct si::metre>>>{}, int>>);
|
||||
static_assert(is_of_type<1 / min, quantity<derived_unit<struct one, per<struct si::minute>>{}, int>>);
|
||||
static_assert(is_of_type<1 / Hz, quantity<derived_unit<struct one, per<struct si::hertz>>{}, int>>);
|
||||
static_assert(is_of_type<1 / km, quantity<derived_unit<struct one, per<si::kilo_<si::metre>>>{}, int>>);
|
||||
static_assert(is_of_type<1 * km / (1 * m), quantity<derived_unit<si::kilo_<si::metre>, per<struct si::metre>>{}, int>>);
|
||||
static_assert(is_of_type<1 / km, quantity<derived_unit<struct one, per<si::kilo_<struct si::metre>>>{}, int>>);
|
||||
static_assert(
|
||||
is_of_type<1 * km / (1 * m), quantity<derived_unit<si::kilo_<struct si::metre>, per<struct si::metre>>{}, int>>);
|
||||
static_assert(is_of_type<1 * m / (1 * s), quantity<derived_unit<struct si::metre, per<struct si::second>>{}, int>>);
|
||||
static_assert(is_of_type<1 * m / (1 * min), quantity<derived_unit<struct si::metre, per<struct si::minute>>{}, int>>);
|
||||
static_assert(is_of_type<1 * min / (1 * m), quantity<derived_unit<struct si::minute, per<struct si::metre>>{}, int>>);
|
||||
|
@ -61,8 +61,9 @@ static_assert(1 * Rm == 1'000'000'000'000'000'000 * Gm);
|
||||
static_assert(1 * Qm == 1'000'000'000'000'000'000 * Tm);
|
||||
|
||||
// check for invalid prefixes
|
||||
template<template<auto U> typename prefix, auto V1>
|
||||
concept can_not_be_prefixed = Unit<std::remove_const_t<decltype(V1)>> && !requires { typename prefix<V1>; };
|
||||
template<template<typename U> typename prefix, auto V1>
|
||||
concept can_not_be_prefixed =
|
||||
Unit<std::remove_const_t<decltype(V1)>> && !requires { typename prefix<std::remove_const_t<decltype(V1)>>; };
|
||||
|
||||
static_assert(can_not_be_prefixed<si::milli_, si::degree_Celsius>);
|
||||
static_assert(can_not_be_prefixed<si::milli_, si::minute>);
|
||||
|
@ -212,8 +212,8 @@ static_assert(convertible(kilojoule, joule));
|
||||
static_assert(kilojoule != joule);
|
||||
static_assert(kilojoule.symbol == "kJ");
|
||||
|
||||
static_assert(is_of_type<si::kilo<metre>, si::kilo_<metre>>);
|
||||
static_assert(is_of_type<si::kilo<joule>, si::kilo_<joule>>);
|
||||
static_assert(is_of_type<si::kilo<metre>, si::kilo_<metre_>>);
|
||||
static_assert(is_of_type<si::kilo<joule>, si::kilo_<joule_>>);
|
||||
|
||||
// TODO Should the below be a scaled version of metre^2?
|
||||
static_assert(is_of_type<kilometre * metre, derived_unit<kilometre_, metre_>>); // !!!
|
||||
@ -264,7 +264,7 @@ static_assert(is_of_type<get_canonical_unit(km_2).reference_unit, metre_>);
|
||||
static_assert(get_canonical_unit(km_2).mag == mag<2000>);
|
||||
|
||||
constexpr auto kJ_42 = mag<42> * si::kilo<joule>;
|
||||
static_assert(is_of_type<kJ_42, scaled_unit<mag<42>, si::kilo_<joule>>>);
|
||||
static_assert(is_of_type<kJ_42, scaled_unit<mag<42>, si::kilo_<joule_>>>);
|
||||
static_assert(
|
||||
is_of_type<get_canonical_unit(kJ_42).reference_unit, derived_unit<gram_, power<metre_, 2>, per<power<second_, 2>>>>);
|
||||
static_assert(get_canonical_unit(kJ_42).mag == mag<42'000'000>);
|
||||
@ -467,7 +467,7 @@ static_assert(!convertible(metre, metre* metre));
|
||||
|
||||
// one
|
||||
static_assert(is_of_type<metre / metre, one_>);
|
||||
static_assert(is_of_type<si::kilo<metre> / metre, derived_unit<si::kilo_<metre>, per<metre_>>>);
|
||||
static_assert(is_of_type<si::kilo<metre> / metre, derived_unit<si::kilo_<metre_>, per<metre_>>>);
|
||||
static_assert(metre / metre == one);
|
||||
static_assert(hertz * second == one);
|
||||
static_assert(one * one == one);
|
||||
@ -509,7 +509,7 @@ static_assert(is_of_type<pow<1, 2>(metre / (second * second)), derived_unit<powe
|
||||
static_assert(is_of_type<kilometre * kilometre, derived_unit<power<kilometre_, 2>>>);
|
||||
|
||||
static_assert(is_of_type<pow<2>(kilometre), derived_unit<power<kilometre_, 2>>>);
|
||||
static_assert(is_of_type<pow<2>(si::kilo<metre>), derived_unit<power<si::kilo_<metre>, 2>>>);
|
||||
static_assert(is_of_type<pow<2>(si::kilo<metre>), derived_unit<power<si::kilo_<metre_>, 2>>>);
|
||||
static_assert(is_of_type<pow<2>(hour), derived_unit<power<hour_, 2>>>);
|
||||
static_assert(
|
||||
is_of_type<pow<2>(mag<3600>* second), scaled_unit<mag<3600> * mag<3600>, derived_unit<power<second_, 2>>>>);
|
||||
|
Reference in New Issue
Block a user