Merge branch 'new_design'
@@ -25,15 +25,15 @@ AccessModifierOffset: -2
|
|||||||
# AlwaysBreakTemplateDeclarations: Yes
|
# AlwaysBreakTemplateDeclarations: Yes
|
||||||
# BinPackArguments: true
|
# BinPackArguments: true
|
||||||
# BinPackParameters: true
|
# BinPackParameters: true
|
||||||
# BraceWrapping:
|
BraceWrapping:
|
||||||
# AfterCaseLabel: false
|
# AfterCaseLabel: false
|
||||||
# AfterClass: false
|
AfterClass: false
|
||||||
# AfterControlStatement: false
|
# AfterControlStatement: false
|
||||||
# AfterEnum: false
|
# AfterEnum: false
|
||||||
# AfterFunction: false
|
AfterFunction: true
|
||||||
# AfterNamespace: false
|
# AfterNamespace: false
|
||||||
# AfterObjCDeclaration: false
|
# AfterObjCDeclaration: false
|
||||||
# AfterStruct: false
|
AfterStruct: false
|
||||||
# AfterUnion: false
|
# AfterUnion: false
|
||||||
# AfterExternBlock: false
|
# AfterExternBlock: false
|
||||||
# BeforeCatch: false
|
# BeforeCatch: false
|
||||||
@@ -44,9 +44,9 @@ AccessModifierOffset: -2
|
|||||||
# SplitEmptyNamespace: true
|
# SplitEmptyNamespace: true
|
||||||
# BreakAfterJavaFieldAnnotations: false
|
# BreakAfterJavaFieldAnnotations: false
|
||||||
# BreakBeforeBinaryOperators: None
|
# BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Stroustrup
|
BreakBeforeBraces: Custom
|
||||||
# BreakBeforeInheritanceComma: false
|
# BreakBeforeInheritanceComma: false
|
||||||
BreakBeforeTernaryOperators: false
|
# BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializers: AfterColon
|
BreakConstructorInitializers: AfterColon
|
||||||
BreakConstructorInitializersBeforeComma: true
|
BreakConstructorInitializersBeforeComma: true
|
||||||
BreakInheritanceList: AfterColon
|
BreakInheritanceList: AfterColon
|
||||||
@@ -66,6 +66,7 @@ ForEachMacros:
|
|||||||
- foreach
|
- foreach
|
||||||
- Q_FOREACH
|
- Q_FOREACH
|
||||||
- BOOST_FOREACH
|
- BOOST_FOREACH
|
||||||
|
- SECTION
|
||||||
- GIVEN
|
- GIVEN
|
||||||
- WHEN
|
- WHEN
|
||||||
- THEN
|
- THEN
|
||||||
@@ -93,7 +94,7 @@ IncludeCategories:
|
|||||||
# MacroBlockBegin: ''
|
# MacroBlockBegin: ''
|
||||||
# MacroBlockEnd: ''
|
# MacroBlockEnd: ''
|
||||||
# MaxEmptyLinesToKeep: 1
|
# MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: All
|
# NamespaceIndentation: None
|
||||||
# ObjCBinPackProtocolList: Never
|
# ObjCBinPackProtocolList: Never
|
||||||
# ObjCBlockIndentWidth: 2
|
# ObjCBlockIndentWidth: 2
|
||||||
# ObjCSpaceAfterProperty: false
|
# ObjCSpaceAfterProperty: false
|
||||||
@@ -143,9 +144,9 @@ NamespaceIndentation: All
|
|||||||
SpaceAfterTemplateKeyword: false
|
SpaceAfterTemplateKeyword: false
|
||||||
# SpaceBeforeAssignmentOperators: true
|
# SpaceBeforeAssignmentOperators: true
|
||||||
# SpaceBeforeCpp11BracedList: false
|
# SpaceBeforeCpp11BracedList: false
|
||||||
SpaceBeforeCtorInitializerColon: false
|
# SpaceBeforeCtorInitializerColon: true
|
||||||
# SpaceBeforeInheritanceColon: true
|
# SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeParens: Never
|
# SpaceBeforeParens: ControlStatements
|
||||||
# SpaceBeforeRangeBasedForLoopColon: true
|
# SpaceBeforeRangeBasedForLoopColon: true
|
||||||
# SpaceInEmptyBlock: false
|
# SpaceInEmptyBlock: false
|
||||||
# SpaceInEmptyParentheses: false
|
# SpaceInEmptyParentheses: false
|
||||||
|
13
.gitattributes
vendored
@@ -1,3 +1,16 @@
|
|||||||
|
# Set the default behavior
|
||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||||
|
|
||||||
|
# Explicitly declare text files to always be normalized and converted to native line endings on checkout
|
||||||
|
*.cpp text
|
||||||
|
*.h text
|
||||||
|
*.py text
|
||||||
|
*.txt text
|
||||||
|
*.md text
|
||||||
|
*.yml text
|
||||||
|
|
||||||
|
# Denote all files that are truly binary and should not be modified
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
149
README.md
@@ -5,9 +5,32 @@
|
|||||||
|
|
||||||
# `mp-units` - A Units Library for C++
|
# `mp-units` - A Units Library for C++
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Velocity auto avg_speed(Length auto d, Time auto t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
Velocity auto v1 = avg_speed(220km, 2h);
|
||||||
|
Velocity auto v2 = avg_speed(140mi, 2h);
|
||||||
|
|
||||||
|
std::cout << v1 << '\n'; // 110 km/h
|
||||||
|
std::cout << quantity_cast<si::metre_per_second>(speed) << '\n'; // 30.5556 m/s
|
||||||
|
std::cout << v2 << '\n'; // 70 mi/h
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Try it on [Compiler Explorer](https://godbolt.org/z/OVpkT1).
|
||||||
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
`Units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
`mp-units` is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
||||||
analysis and unit/quantity manipulation. The basic idea and design heavily bases on
|
analysis and unit/quantity manipulation. The basic idea and design heavily bases on
|
||||||
`std::chrono::duration` and extends it to work properly with many dimensions.
|
`std::chrono::duration` and extends it to work properly with many dimensions.
|
||||||
|
|
||||||
@@ -31,74 +54,120 @@ static_assert(1000 / 1s == 1kHz);
|
|||||||
static_assert(10km / 5km == 2);
|
static_assert(10km / 5km == 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage Overview
|
|
||||||
|
|
||||||
The library framework consists of a few concepts: quantities, units, dimensions and their exponents. From the user's
|
## Getting Started
|
||||||
point of view the most important is a `quantity`.
|
|
||||||
|
|
||||||
Quantity is a concrete amount of a unit for a specified dimension with a specific representation:
|
The library framework consists of a few concepts: quantities, units, dimensions and their
|
||||||
|
exponents. From the user's point of view the most important is a `quantity`.
|
||||||
|
|
||||||
|
A quantity is a concrete amount of a unit for a specified dimension with a specific representation:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
units::quantity<units::kilometre, double> d1(123);
|
units::quantity<units::si::dim_length, units::si::kilometre, double> d(123);
|
||||||
auto d2 = 123km; // units::quantity<units::kilometre, std::int64_t>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
There are C++ concepts provided for each such quantity type:
|
To simplify quantity creation the library provides helper aliases for quantities of different
|
||||||
|
dimensions. Thanks to then the above example can be rewritten as follows:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
template<typename T>
|
units::si::length<units::si::kilometre, double> d(123);
|
||||||
concept Length = QuantityOf<T, length>;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
With that we can easily write a function template like this:
|
To simplify creations of compile-time known constants the library provides UDLs for each unit.
|
||||||
|
Thanks to them the same code can be as simple as:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
constexpr units::Velocity auto avg_speed(units::Length auto d, units::Time auto t)
|
using namespace units::si::literals;
|
||||||
|
auto d = 123km; // units::length<units::si::kilometre, std::int64_t>
|
||||||
|
```
|
||||||
|
|
||||||
|
For brevity, the next examples will assume:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace units;
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's assume that the user wants to write the following code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
auto v1 = avg_speed(220km, 2h);
|
||||||
|
auto v2 = avg_speed(140mi, 2h);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`avg_speed` is a simple function calculating an average speed from a distance and duration. It can
|
||||||
|
be implemented as:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr si::velocity<si::metre_per_second, int> avg_speed(si::length<si::metre> d, si::time<si::second> t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Concepts usage in the function above guarantee correctness enforced in compile-time and the
|
However, this function will perform unnecessary intermediate conversions (from kilometers to meters,
|
||||||
guarantee that no unneeded intermediate conversions will ever be applied no matter which
|
from hours to seconds, and from meters per second to kilometers per hour). To eliminate all that
|
||||||
units the user will decide to pass to such function template:
|
overhead we have to write a template function:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
using namespace units;
|
template<typename U1, typename R1, typename U2, typename R2>
|
||||||
|
constexpr auto avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
|
||||||
constexpr quantity<kilometre> distance(220);
|
{
|
||||||
constexpr quantity<hour> time(2);
|
return d / t;
|
||||||
constexpr Velocity speed = avg_speed(distance, time);
|
}
|
||||||
|
|
||||||
static_assert(std::same_as<std::remove_cvref_t<decltype(speed)>, quantity<kilometre_per_hour>>);
|
|
||||||
static_assert(speed.count() == 110);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The units library also tries really hard to printing any quantity in the most user friendly fashion:
|
This function will work for every SI unit and representation without any unnecessary overhead.
|
||||||
|
It is also simple enough to ensure that the returned type is actually a velocity. However,
|
||||||
|
it might not always be the case. For more complicated calculations we would like to ensure
|
||||||
|
that we are returning a correct type and also inform the user of that fact in the function
|
||||||
|
template interface. Also we might want to implement a truly generic function that will work
|
||||||
|
efficiently not only with SI units but also with other systems of units like CGS. The solution
|
||||||
|
to this are C++20 concepts and generic functions.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
std::cout << speed << '\n';
|
constexpr Velocity auto avg_speed(Length auto d, Time auto t)
|
||||||
std::cout << quantity_cast<metre_per_second>(speed) << '\n';
|
{
|
||||||
std::cout << avg_speed(140.mi, 2h) << '\n';
|
return d / t;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Try it on [Compiler Explorer](https://godbolt.org/z/OVpkT1).
|
The units library also tries really hard to print any quantity in the most user friendly
|
||||||
|
fashion:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
Velocity auto v1 = avg_speed(220km, 2h);
|
||||||
|
Velocity auto v2 = avg_speed(140mi, 2h);
|
||||||
|
|
||||||
|
std::cout << v1 << '\n'; // 110 km/h
|
||||||
|
std::cout << quantity_cast<si::metre_per_second>(speed) << '\n'; // 30.5556 m/s
|
||||||
|
std::cout << v2 << '\n'; // 70 mi/h
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Library design
|
## Library design
|
||||||
|
|
||||||
`mp-units` library design rationale and documentation can be found in [doc/DESIGN.md](doc/DESIGN.md)
|
A detailed `mp-units` library design rationale and documentation can be found in
|
||||||
|
[doc/DESIGN.md](doc/DESIGN.md)
|
||||||
|
|
||||||
|
|
||||||
## Repository structure
|
## Repository structure
|
||||||
|
|
||||||
That repository contains the following independent `cmake`-based projects:
|
This repository contains three independent `cmake`-based projects:
|
||||||
- `./src` - header-only project for `units`
|
1. `./src` - header-only project containing whole `mp-units` library
|
||||||
- `.` - project used for development needs that wraps `./src` project together with
|
2. `.` - project used as an entry point for library development (it wraps `./src` project
|
||||||
usage examples and unit tests
|
together with usage examples and tests)
|
||||||
- `./test_package` - library installation and Conan package verification
|
3. `./test_package` - library installation and Conan package verification
|
||||||
|
|
||||||
Please note that the projects depend on `cmake` git submodule in the `./cmake/common`
|
NOTE: Please note that this repository depends on a git submodule in the `./cmake/common`
|
||||||
subdirectory.
|
subdirectory.
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +181,16 @@ NOTE: This library as of now compiles correctly only with gcc-9.1 and newer.
|
|||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
|
||||||
|
- 0.5.0 ???
|
||||||
|
- Major refactoring and rewrite of the library
|
||||||
|
- Units are now independent from dimensions
|
||||||
|
- Dimensions are now depended on units (base or coherent units are provided in a class template)
|
||||||
|
- Quantity gets a Dimension template parameter again (as unit does not provide information about
|
||||||
|
its dimension anymore)
|
||||||
|
- Added official CGS system support
|
||||||
|
- Added official data information system support
|
||||||
|
- Repository file tree cleanup
|
||||||
|
|
||||||
- 0.4.0 Nov 17, 2019
|
- 0.4.0 Nov 17, 2019
|
||||||
- Support for derived dimensions in `exp` added
|
- Support for derived dimensions in `exp` added
|
||||||
- Added `pow()` and `sqrt()` operations on quantities
|
- Added `pow()` and `sqrt()` operations on quantities
|
||||||
|
14
conanfile.py
@@ -47,9 +47,10 @@ class UnitsConan(ConanFile):
|
|||||||
exports_sources = ["src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"]
|
exports_sources = ["src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"]
|
||||||
settings = "os", "compiler", "build_type", "arch"
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
requires = (
|
requires = (
|
||||||
"range-v3/0.9.1@ericniebler/stable",
|
"fmt/6.1.0"
|
||||||
"Catch2/2.10.0@catchorg/stable",
|
)
|
||||||
"fmt/6.0.0"
|
build_requires = (
|
||||||
|
"Catch2/2.11.0@catchorg/stable"
|
||||||
)
|
)
|
||||||
generators = "cmake"
|
generators = "cmake"
|
||||||
|
|
||||||
@@ -73,6 +74,10 @@ class UnitsConan(ConanFile):
|
|||||||
cmake.configure(source_folder="src", build_folder="src")
|
cmake.configure(source_folder="src", build_folder="src")
|
||||||
return cmake
|
return cmake
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
if Version(self.settings.compiler.version) < "10":
|
||||||
|
self.requires("range-v3/0.10.0@ericniebler/stable")
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
cmake = self._configure_cmake()
|
cmake = self._configure_cmake()
|
||||||
cmake.build()
|
cmake.build()
|
||||||
@@ -91,8 +96,7 @@ class UnitsConan(ConanFile):
|
|||||||
"-fconcepts",
|
"-fconcepts",
|
||||||
"-Wno-literal-suffix",
|
"-Wno-literal-suffix",
|
||||||
"-Wno-non-template-friend",
|
"-Wno-non-template-friend",
|
||||||
"-Wno-stringop-overflow",
|
"-Wno-stringop-overflow"
|
||||||
"-Wno-pedantic"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def package_id(self):
|
def package_id(self):
|
||||||
|
1153
doc/DESIGN.md
@@ -39,18 +39,18 @@ steps may be done:
|
|||||||
```
|
```
|
||||||
|
|
||||||
- add `units` as a dependency to your `conan` file. For example to use testing version of
|
- add `units` as a dependency to your `conan` file. For example to use testing version of
|
||||||
`0.4.0` of `mp-units` add:
|
`0.5.0` of `mp-units` add:
|
||||||
- `conanfile.txt`
|
- `conanfile.txt`
|
||||||
|
|
||||||
```text
|
```text
|
||||||
[requires]
|
[requires]
|
||||||
mp-units/0.4.0@mpusz/testing
|
mp-units/0.5.0@mpusz/testing
|
||||||
```
|
```
|
||||||
|
|
||||||
- `conanfile.py`
|
- `conanfile.py`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
requires = "mp-units/0.4.0@mpusz/testing"
|
requires = "mp-units/0.5.0@mpusz/testing"
|
||||||
```
|
```
|
||||||
|
|
||||||
- link your `cmake` target with units
|
- link your `cmake` target with units
|
||||||
@@ -93,5 +93,5 @@ conan create . <username>/<channel> -s cppstd=20 -b=outdated <your_profile_and_s
|
|||||||
## Upload package to conan server
|
## Upload package to conan server
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
conan upload -r <remote-name> --all mp-units/0.4.0@<user>/<channel>
|
conan upload -r <remote-name> --all mp-units/0.5.0@<user>/<channel>
|
||||||
```
|
```
|
||||||
|
BIN
doc/design.png
Normal file
After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 32 KiB |
46
doc/nomnoml.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# nomnoml
|
||||||
|
|
||||||
|
Graphs in the documentation are created with <http://www.nomnoml.com>.
|
||||||
|
|
||||||
|
## Concepts
|
||||||
|
|
||||||
|
```text
|
||||||
|
[<abstract>Dimension|
|
||||||
|
[base_dimension<Symbol, Unit>]<-[exp<Dimension, Num, Den>]
|
||||||
|
[derived_dimension<Child, Unit, Exponent...>]<-[exp<Dimension, Num, Den>]
|
||||||
|
[exp<Dimension, Num, Den>]<-[derived_dimension<Child, Unit, Exponent...>]
|
||||||
|
]
|
||||||
|
|
||||||
|
[<abstract>Quantity|
|
||||||
|
[quantity<Dimension, Unit, Rep>]
|
||||||
|
]
|
||||||
|
|
||||||
|
[<abstract>Unit]<-[Dimension]
|
||||||
|
[Dimension]<-[Quantity]
|
||||||
|
[Unit]<-[Quantity]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Units
|
||||||
|
|
||||||
|
```text
|
||||||
|
#direction: right
|
||||||
|
|
||||||
|
[scaled_unit<Ratio, Unit>]<:-[unit<Child>]
|
||||||
|
[scaled_unit<Ratio, Unit>]<:-[named_unit<Child, Symbol, PrefixType>]
|
||||||
|
[scaled_unit<Ratio, Unit>]<:-[named_scaled_unit<Child, Symbol, PrefixType, Ratio, Unit>]
|
||||||
|
[scaled_unit<Ratio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>]
|
||||||
|
[scaled_unit<Ratio, Unit>]<:-[deduced_unit<Child, Dimension, Unit, Unit...>]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Downcasting 1
|
||||||
|
|
||||||
|
```text
|
||||||
|
[detail::derived_dimension_base<exp<si::dim_length, 2>>]<:-[dim_area]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Downcasting 2
|
||||||
|
|
||||||
|
```text
|
||||||
|
[downcast_base<detail::derived_dimension_base<exp<si::dim_length, 2>>>]<:-[detail::derived_dimension_base<exp<si::dim_length, 2>>]
|
||||||
|
[detail::derived_dimension_base<exp<si::dim_length, 2>>]<:-[downcast_child<dim_area, detail::derived_dimension_base<exp<si::dim_length, 2>>>]
|
||||||
|
[downcast_child<dim_area, detail::derived_dimension_base<exp<si::dim_length, 2>>>]<:-[dim_area]```
|
BIN
doc/units.png
Normal file
After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 30 KiB |
@@ -20,15 +20,11 @@
|
|||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
# example app
|
function(add_example target)
|
||||||
add_executable(example example.cpp)
|
add_executable(${target} ${target}.cpp)
|
||||||
target_link_libraries(example
|
target_link_libraries(${target} PRIVATE mp::units)
|
||||||
PRIVATE
|
endfunction()
|
||||||
mp::units
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(measurement measurement.cpp)
|
add_example(avg_velocity)
|
||||||
target_link_libraries(measurement
|
add_example(measurement)
|
||||||
PRIVATE
|
add_example(unknown_dimension)
|
||||||
mp::units
|
|
||||||
)
|
|
||||||
|
186
example/avg_velocity.cpp
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// 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 <units/physical/si/velocity.h>
|
||||||
|
#include <units/physical/cgs/velocity.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr units::si::velocity<units::si::metre_per_second, int>
|
||||||
|
fixed_int_si_avg_speed(units::si::length<units::si::metre, int> d,
|
||||||
|
units::si::time<units::si::second, int> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr units::si::velocity<units::si::metre_per_second>
|
||||||
|
fixed_double_si_avg_speed(units::si::length<units::si::metre> d,
|
||||||
|
units::si::time<units::si::second> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U1, typename R1, typename U2, typename R2>
|
||||||
|
constexpr units::Velocity AUTO si_avg_speed(units::si::length<U1, R1> d,
|
||||||
|
units::si::time<U2, R2> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr units::Velocity AUTO avg_speed(units::Length AUTO d, units::Time AUTO t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<units::Length D, units::Time T, units::Velocity V>
|
||||||
|
void print_result(D distance, T duration, V velocity)
|
||||||
|
{
|
||||||
|
const auto result_in_kmph = units::quantity_cast<units::si::velocity<units::si::kilometre_per_hour>>(velocity);
|
||||||
|
std::cout << "Average speed of a car that makes " << distance << " in "
|
||||||
|
<< duration << " is " << result_in_kmph << ".\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace units;
|
||||||
|
|
||||||
|
// SI (int)
|
||||||
|
{
|
||||||
|
using namespace units::si::literals;
|
||||||
|
constexpr Length AUTO distance = 220km; // constructed from a UDL
|
||||||
|
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "SI units with 'int' as representation\n";
|
||||||
|
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SI (double)
|
||||||
|
{
|
||||||
|
using namespace units::si::literals;
|
||||||
|
constexpr Length AUTO distance = 220.km; // constructed from a UDL
|
||||||
|
constexpr si::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "\nSI units with 'double' as representation\n";
|
||||||
|
|
||||||
|
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration)));
|
||||||
|
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customary Units (int)
|
||||||
|
{
|
||||||
|
using namespace units::si::literals;
|
||||||
|
constexpr Length AUTO distance = 140mi; // constructed from a UDL
|
||||||
|
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "\nUS Customary Units with 'int' as representation\n";
|
||||||
|
|
||||||
|
// it is not possible to make a lossless conversion of miles to meters on an integral type
|
||||||
|
// (explicit cast needed)
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::metre>(distance), duration));
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customary Units (double)
|
||||||
|
{
|
||||||
|
using namespace units::si::literals;
|
||||||
|
constexpr Length AUTO distance = 140.mi; // constructed from a UDL
|
||||||
|
constexpr si::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "\nUS Customary Units with 'double' as representation\n";
|
||||||
|
|
||||||
|
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
|
||||||
|
// also it is not possible to make a lossless conversion of miles to meters on an integral type
|
||||||
|
// (explicit cast needed)
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
|
||||||
|
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, si_avg_speed(distance, duration));
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CGS (int)
|
||||||
|
{
|
||||||
|
using namespace units::cgs::literals;
|
||||||
|
constexpr Length AUTO distance = 22'000'000cm; // constructed from a UDL
|
||||||
|
constexpr cgs::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "\nCGS units with 'int' as representation\n";
|
||||||
|
|
||||||
|
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
||||||
|
// (explicit cast needed)
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::metre>(distance), duration));
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
|
||||||
|
// not possible to convert both a dimension and a unit with implicit cast
|
||||||
|
print_result(distance, duration, si_avg_speed(quantity_cast<si::dim_length>(distance), duration));
|
||||||
|
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CGS (double)
|
||||||
|
{
|
||||||
|
using namespace units::cgs::literals;
|
||||||
|
constexpr Length AUTO distance = 22'000'000.cm; // constructed from a UDL
|
||||||
|
constexpr cgs::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
|
std::cout << "\nCGS units with 'double' as representation\n";
|
||||||
|
|
||||||
|
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
|
||||||
|
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
||||||
|
// (explicit cast needed)
|
||||||
|
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
|
||||||
|
|
||||||
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
|
|
||||||
|
// not possible to convert both a dimension and a unit with implicit cast
|
||||||
|
print_result(distance, duration, si_avg_speed(quantity_cast<si::dim_length>(distance), duration));
|
||||||
|
|
||||||
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
example();
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex) {
|
||||||
|
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cerr << "Unhandled unknown exception caught\n";
|
||||||
|
}
|
||||||
|
}
|
@@ -20,30 +20,30 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include <units/dimensions/acceleration.h>
|
#include <units/physical/si/acceleration.h>
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<typename T, template<typename> typename Trait>
|
// root sum of squares
|
||||||
concept Satisfies = Trait<T>::value;
|
template<typename T>
|
||||||
|
T rss(const T& v1, const T& v2)
|
||||||
// root sum of squares
|
{
|
||||||
template<typename T>
|
|
||||||
T rss(const T& v1, const T& v2)
|
|
||||||
{
|
|
||||||
return std::sqrt(std::pow(v1, 2) + std::pow(v2, 2));
|
return std::sqrt(std::pow(v1, 2) + std::pow(v2, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class measurement {
|
class measurement {
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
measurement() = default;
|
measurement() = default;
|
||||||
|
|
||||||
constexpr /* explicit */ measurement(const value_type& val, const value_type& err = {}): // cannot be explicit as `magma` concept requires implicit conversions :-(
|
constexpr /* explicit */ measurement(const value_type& val, const value_type& err = {}) :
|
||||||
value_(val), uncertainty_(std::abs(err))
|
// cannot be explicit as `magma` concept requires implicit conversions :-(
|
||||||
|
value_(val),
|
||||||
|
uncertainty_(std::abs(err))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +78,13 @@ namespace {
|
|||||||
return measurement(val, val * rss(lhs.relative_uncertainty(), rhs.relative_uncertainty()));
|
return measurement(val, val * rss(lhs.relative_uncertainty(), rhs.relative_uncertainty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __GNUC__ >= 10
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const measurement& lhs, const measurement& rhs) = default;
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const measurement& lhs, const measurement& rhs) = default;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const measurement& lhs, const measurement& rhs)
|
[[nodiscard]] friend constexpr bool operator==(const measurement& lhs, const measurement& rhs)
|
||||||
{
|
{
|
||||||
return lhs.value() == rhs.value() && lhs.uncertainty() == rhs.uncertainty();
|
return lhs.value() == rhs.value() && lhs.uncertainty() == rhs.uncertainty();
|
||||||
@@ -93,10 +100,7 @@ namespace {
|
|||||||
return lhs.value() == rhs.value() ? lhs.uncertainty() < rhs.uncertainty() : lhs.value() < rhs.value();
|
return lhs.value() == rhs.value() ? lhs.uncertainty() < rhs.uncertainty() : lhs.value() < rhs.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator>(const measurement& lhs, const measurement& rhs)
|
[[nodiscard]] friend constexpr bool operator>(const measurement& lhs, const measurement& rhs) { return rhs < lhs; }
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator<=(const measurement& lhs, const measurement& rhs)
|
[[nodiscard]] friend constexpr bool operator<=(const measurement& lhs, const measurement& rhs)
|
||||||
{
|
{
|
||||||
@@ -108,34 +112,50 @@ namespace {
|
|||||||
return !(lhs < rhs);
|
return !(lhs < rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const measurement& v)
|
friend std::ostream& operator<<(std::ostream& os, const measurement& v)
|
||||||
{
|
{
|
||||||
return os << v.value() << " ± " << v.uncertainty();
|
return os << v.value() << " ± " << v.uncertainty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_type value_{};
|
value_type value_{};
|
||||||
value_type uncertainty_{};
|
value_type uncertainty_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<units::Unit U>
|
static_assert(units::Scalar<measurement<double>>);
|
||||||
using m_quantity = units::quantity<U, measurement<double>>;
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr bool units::treat_as_floating_point<measurement<T>> = std::is_floating_point_v<T>;
|
inline constexpr bool units::treat_as_floating_point<measurement<T>> = std::is_floating_point_v<T>;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace units;
|
||||||
|
|
||||||
|
const auto a = si::acceleration<si::metre_per_second_sq, measurement<double>>(measurement(9.8, 0.1));
|
||||||
|
const auto t = si::time<si::second, measurement<double>>(measurement(1.2, 0.1));
|
||||||
|
|
||||||
|
const Velocity AUTO v1 = a * t;
|
||||||
|
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
||||||
|
|
||||||
|
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
||||||
|
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const auto a = m_quantity<units::metre_per_second_sq>(measurement(9.8, 0.1));
|
try {
|
||||||
const auto t = m_quantity<units::second>(measurement(1.2, 0.1));
|
example();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
units::Velocity AUTO v1 = a * t;
|
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
|
||||||
m_quantity<units::kilometre_per_hour> v2(v1);
|
} catch (...) {
|
||||||
std::cout << a << " * " << t << " = " << v1 << " = " << v2 << '\n';
|
std::cerr << "Unhandled unknown exception caught\n";
|
||||||
|
}
|
||||||
m_quantity<units::metre> length(measurement(123., 1.));
|
|
||||||
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
|
||||||
}
|
}
|
||||||
|
@@ -20,43 +20,43 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#include <units/dimensions/velocity.h>
|
#include <units/physical/si/velocity.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace units::literals;
|
|
||||||
|
|
||||||
template<units::Length D, units::Time T>
|
template<units::Length D, units::Time T>
|
||||||
constexpr units::Velocity AUTO avg_speed(D d, T t)
|
constexpr units::Velocity AUTO avg_speed(D d, T t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<units::Velocity V, units::Time T>
|
void example()
|
||||||
void example_1(V v, T t)
|
|
||||||
{
|
{
|
||||||
const units::Length AUTO distance = v * t;
|
using namespace units::si::literals;
|
||||||
std::cout << "A car driving " << v << " in a time of " << t << " will pass "
|
|
||||||
<< units::quantity_cast<units::quantity<units::metre, double>>(distance) << ".\n";
|
units::Length AUTO d1 = 123m;
|
||||||
|
units::Time AUTO t1 = 10s;
|
||||||
|
units::Velocity AUTO v1 = avg_speed(d1, t1);
|
||||||
|
|
||||||
|
auto temp1 = v1 * 50m; // produces intermediate unknown dimension with 'unknown_unit' as its 'coherent_unit'
|
||||||
|
units::Velocity AUTO v2 = temp1 / 100m; // back to known dimensions again
|
||||||
|
units::Length AUTO d2 = v2 * 60s;
|
||||||
|
|
||||||
|
std::cout << "d1 = " << d1 << '\n';
|
||||||
|
std::cout << "t1 = " << t1 << '\n';
|
||||||
|
std::cout << "v1 = " << v1 << '\n';
|
||||||
|
std::cout << "temp1 = " << temp1 << '\n';
|
||||||
|
std::cout << "v2 = " << v2 << '\n';
|
||||||
|
std::cout << "d2 = " << d2 << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void example_2(double distance_v, double duration_v)
|
} // namespace
|
||||||
{
|
|
||||||
units::quantity<units::kilometre> distance(distance_v);
|
|
||||||
units::quantity<units::hour> duration(duration_v);
|
|
||||||
const auto kmph = quantity_cast<units::kilometre_per_hour>(avg_speed(distance, duration));
|
|
||||||
std::cout << "Average speed of a car that makes " << distance << " in "
|
|
||||||
<< duration << " is " << kmph << ".\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
example_1(60kmph, 10.0min);
|
example();
|
||||||
example_2(220, 2);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex) {
|
catch (const std::exception& ex) {
|
||||||
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
|
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
|
@@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 3.8)
|
|||||||
#cmake_policy(SET CMP0076 NEW)
|
#cmake_policy(SET CMP0076 NEW)
|
||||||
|
|
||||||
project(units
|
project(units
|
||||||
VERSION 0.4.0
|
VERSION 0.5.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,7 +53,6 @@ add_library(units INTERFACE)
|
|||||||
target_compile_features(units INTERFACE cxx_std_20)
|
target_compile_features(units INTERFACE cxx_std_20)
|
||||||
target_link_libraries(units
|
target_link_libraries(units
|
||||||
INTERFACE
|
INTERFACE
|
||||||
CONAN_PKG::range-v3
|
|
||||||
CONAN_PKG::fmt
|
CONAN_PKG::fmt
|
||||||
)
|
)
|
||||||
target_include_directories(units
|
target_include_directories(units
|
||||||
@@ -67,10 +66,13 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
-Wno-literal-suffix
|
-Wno-literal-suffix
|
||||||
-Wno-non-template-friend
|
-Wno-non-template-friend
|
||||||
-Wno-stringop-overflow
|
-Wno-stringop-overflow
|
||||||
# TODO gcc:92101
|
|
||||||
-Wno-pedantic
|
|
||||||
)
|
)
|
||||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
|
||||||
|
target_link_libraries(units
|
||||||
|
INTERFACE
|
||||||
|
CONAN_PKG::range-v3
|
||||||
|
)
|
||||||
|
|
||||||
target_compile_options(units
|
target_compile_options(units
|
||||||
INTERFACE
|
INTERFACE
|
||||||
-fconcepts
|
-fconcepts
|
||||||
|
66
src/include/units/base_dimension.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/external/fixed_string.h>
|
||||||
|
#include <units/concepts.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A dimension of a base quantity
|
||||||
|
*
|
||||||
|
* Base quantity is a quantity in a conventionally chosen subset of a given system of quantities, where no quantity
|
||||||
|
* in the subset can be expressed in terms of the other quantities within that subset. They are referred to as
|
||||||
|
* being mutually independent since a base quantity cannot be expressed as a product of powers of the other base
|
||||||
|
* quantities.
|
||||||
|
*
|
||||||
|
* Base unit is a measurement unit that is adopted by convention for a base quantity in a specific system of units.
|
||||||
|
*
|
||||||
|
* Pair of Symbol and Unit template parameters form an unique identifier of the base dimension. The same identifiers can
|
||||||
|
* be multiplied and divided which will result with an adjustment of its factor in an Exponent of a DerivedDimension
|
||||||
|
* (in case of zero the dimension will be simplified and removed from further analysis of current expresion). In case
|
||||||
|
* the Symbol is the same but the Unit differs (i.e. mixing SI and CGS length), there is no automatic simplification but
|
||||||
|
* is possible to force it with a quantity_cast.
|
||||||
|
*
|
||||||
|
* @tparam Symbol an unique identifier of the base dimension used to provide dimensional analysis support
|
||||||
|
* @tparam U a base unit to be used for this base dimension
|
||||||
|
*/
|
||||||
|
template<basic_fixed_string Symbol, Unit U>
|
||||||
|
requires U::is_named
|
||||||
|
struct base_dimension {
|
||||||
|
using base_type_workaround = base_dimension; // TODO Replace with is_derived_from_instantiation when fixed
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
using base_unit = U;
|
||||||
|
};
|
||||||
|
|
||||||
|
// base_dimension_less
|
||||||
|
// TODO Remove the below when https://bugs.llvm.org/show_bug.cgi?id=32208 is fixed
|
||||||
|
// clang-format off
|
||||||
|
template<BaseDimension D1, BaseDimension D2>
|
||||||
|
struct base_dimension_less : std::bool_constant<
|
||||||
|
D1::symbol < D2::symbol || (D1::symbol == D2::symbol && D1::base_unit::symbol < D1::base_unit::symbol)> {};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -22,32 +22,39 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/hacks.h>
|
#include <units/base_dimension.h>
|
||||||
#include <units/bits/numeric_concepts.h>
|
#include <units/exp.h>
|
||||||
#include <units/bits/customization_points.h>
|
|
||||||
#include <units/ratio.h>
|
#include <units/ratio.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::detail {
|
||||||
|
|
||||||
namespace detail {
|
template<Exponent E>
|
||||||
|
requires (E::den == 1 || E::den == 2) // TODO provide support for any den
|
||||||
|
struct exp_ratio {
|
||||||
|
using base_ratio = E::dimension::base_unit::ratio;
|
||||||
|
using positive_ratio = conditional<E::num * E::den < 0, ratio<base_ratio::den, base_ratio::num>, base_ratio>;
|
||||||
|
static constexpr std::int64_t N = E::num * E::den < 0 ? -E::num : E::num;
|
||||||
|
using pow = ratio_pow<positive_ratio, N>;
|
||||||
|
using type = conditional<E::den == 2, ratio_sqrt<pow>, pow>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename U = T>
|
template<typename ExpList>
|
||||||
concept basic_arithmetic = // exposition only
|
struct base_units_ratio_impl;
|
||||||
std::magma<std::ranges::plus, T, U> &&
|
|
||||||
std::magma<std::ranges::minus, T, U> &&
|
|
||||||
std::magma<std::ranges::times, T, U> &&
|
|
||||||
std::magma<std::ranges::divided_by, T, U>;
|
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename E, typename... Es>
|
||||||
concept safe_convertible = // exposition only
|
struct base_units_ratio_impl<exp_list<E, Es...>> {
|
||||||
std::convertible_to<From, To> &&
|
using type = ratio_multiply<typename exp_ratio<E>::type, typename base_units_ratio_impl<exp_list<Es...>>::type>;
|
||||||
(treat_as_floating_point<To> || (!treat_as_floating_point<From>));
|
};
|
||||||
|
|
||||||
template<typename Rep, typename unit_from, typename unit_to>
|
template<typename E>
|
||||||
concept safe_divisible = // exposition only
|
struct base_units_ratio_impl<exp_list<E>> {
|
||||||
treat_as_floating_point<Rep> ||
|
using type = exp_ratio<E>::type;
|
||||||
ratio_divide<typename unit_from::ratio, typename unit_to::ratio>::den == 1;
|
};
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* @brief Calculates the common ratio of all the references of base units in the derived dimension
|
||||||
|
*/
|
||||||
|
template<typename D>
|
||||||
|
using base_units_ratio = base_units_ratio_impl<typename D::exponents>::type;
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units::detail
|
66
src/include/units/bits/common_quantity.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/dimension_op.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
template<Dimension D, UnitOf<D> U, Scalar Rep>
|
||||||
|
class quantity;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename Q1, typename Q2, typename Rep>
|
||||||
|
struct common_quantity_impl;
|
||||||
|
|
||||||
|
template<typename D, typename U, typename Rep1, typename Rep2, typename Rep>
|
||||||
|
struct common_quantity_impl<quantity<D, U, Rep1>, quantity<D, U, Rep2>, Rep> {
|
||||||
|
using type = quantity<D, U, Rep>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2, typename Rep>
|
||||||
|
struct common_quantity_impl<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, Rep> {
|
||||||
|
using type = quantity<D, downcast_unit<D, common_ratio<typename U1::ratio, typename U2::ratio>>, Rep>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2, typename Rep>
|
||||||
|
requires same_unit_reference<dimension_unit<D1>, dimension_unit<D2>>::value
|
||||||
|
struct common_quantity_impl<quantity<D1, U1, Rep1>, quantity<D2, U2, Rep2>, Rep> {
|
||||||
|
using type = quantity<D1, downcast_unit<D1, common_ratio<typename U1::ratio, typename U2::ratio>>, Rep>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2, typename Rep>
|
||||||
|
struct common_quantity_impl<quantity<D1, U1, Rep1>, quantity<D2, U2, Rep2>, Rep> {
|
||||||
|
using ratio1 = ratio_multiply<typename D1::base_units_ratio, typename U1::ratio>;
|
||||||
|
using ratio2 = ratio_multiply<typename D2::base_units_ratio, typename U2::ratio>;
|
||||||
|
using type = quantity<D1, downcast_unit<D1, common_ratio<ratio1, ratio2>>, Rep>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
||||||
|
requires equivalent_dim<typename Q1::dimension, typename Q2::dimension>
|
||||||
|
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -1,115 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
// treat_as_floating_point
|
|
||||||
|
|
||||||
template<typename Rep> // TODO Conceptify that
|
|
||||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
|
||||||
|
|
||||||
// isnan
|
|
||||||
namespace isnan_impl {
|
|
||||||
|
|
||||||
// non-ADL lookup block
|
|
||||||
void isnan(); // undefined
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
inline constexpr bool has_customization = false;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires requires(const T& t) {
|
|
||||||
{ isnan(t) } -> bool;
|
|
||||||
}
|
|
||||||
inline constexpr bool has_customization<T> = true;
|
|
||||||
|
|
||||||
struct fn {
|
|
||||||
template<typename T>
|
|
||||||
constexpr bool operator()(const T&) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires treat_as_floating_point<T>
|
|
||||||
constexpr bool operator()(const T& value) const
|
|
||||||
{
|
|
||||||
return std::isnan(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires treat_as_floating_point<T> && has_customization<T>
|
|
||||||
constexpr bool operator()(const T& value) const
|
|
||||||
{
|
|
||||||
return isnan(value); // uses ADL
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr isnan_impl::fn isnan{};
|
|
||||||
|
|
||||||
// isfinite
|
|
||||||
namespace isfinite_impl {
|
|
||||||
|
|
||||||
// non-ADL lookup block
|
|
||||||
void isfinite(); // undefined
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
inline constexpr bool has_customization = false;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires requires(const T& t) {
|
|
||||||
{ isfinite(t) } -> bool;
|
|
||||||
}
|
|
||||||
inline constexpr bool has_customization<T> = true;
|
|
||||||
|
|
||||||
struct fn {
|
|
||||||
template<typename T>
|
|
||||||
constexpr bool operator()(const T&) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires treat_as_floating_point<T>
|
|
||||||
constexpr bool operator()(const T& value) const
|
|
||||||
{
|
|
||||||
return std::isfinite(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
requires treat_as_floating_point<T> && has_customization<T>
|
|
||||||
constexpr bool operator()(const T& value) const
|
|
||||||
{
|
|
||||||
return isfinite(value); // uses ADL
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr isfinite_impl::fn isfinite{};
|
|
||||||
|
|
||||||
}
|
|
82
src/include/units/bits/deduced_symbol_text.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/external/fixed_string.h>
|
||||||
|
#include <units/bits/external/text_tools.h>
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
template<bool Divide, std::size_t Idx>
|
||||||
|
constexpr auto operator_text()
|
||||||
|
{
|
||||||
|
if constexpr(Idx == 0) {
|
||||||
|
if constexpr(Divide) {
|
||||||
|
return basic_fixed_string("1/");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return basic_fixed_string("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if constexpr(Divide) {
|
||||||
|
return basic_fixed_string("/");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return basic_fixed_string("⋅");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E, basic_fixed_string Symbol, std::size_t Idx>
|
||||||
|
constexpr auto exp_text()
|
||||||
|
{
|
||||||
|
// get calculation operator + symbol
|
||||||
|
const auto txt = operator_text<E::num < 0, Idx>() + Symbol;
|
||||||
|
if constexpr(E::den != 1) {
|
||||||
|
// add root part
|
||||||
|
return txt + basic_fixed_string("^(") + regular<abs(E::num)>() + basic_fixed_string("/") + regular<E::den>() + basic_fixed_string(")");
|
||||||
|
}
|
||||||
|
else if constexpr(abs(E::num) != 1) {
|
||||||
|
// add exponent part
|
||||||
|
return txt + superscript<abs(E::num)>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Us, typename... Es, std::size_t... Idxs>
|
||||||
|
constexpr auto deduced_symbol_text(exp_list<Es...>, std::index_sequence<Idxs...>)
|
||||||
|
{
|
||||||
|
return (exp_text<Es, Us::symbol, Idxs>() + ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<DerivedDimension Dim, Unit... Us>
|
||||||
|
constexpr auto deduced_symbol_text()
|
||||||
|
{
|
||||||
|
return deduced_symbol_text<Us...>(typename Dim::recipe(), std::index_sequence_for<Us...>());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units::detail
|
71
src/include/units/bits/deduced_unit.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
// same_scaled_units
|
||||||
|
template<typename ExpList, Unit... Us>
|
||||||
|
inline constexpr bool same_scaled_units = false;
|
||||||
|
|
||||||
|
template<typename... Es, Unit... Us>
|
||||||
|
inline constexpr bool same_scaled_units<exp_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
||||||
|
|
||||||
|
// deduced_unit
|
||||||
|
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
|
||||||
|
struct ratio_op;
|
||||||
|
|
||||||
|
template<typename Result, int UnitExpDen, typename UnitRatio>
|
||||||
|
struct ratio_op<Result, 0, UnitExpDen, UnitRatio> {
|
||||||
|
using ratio = Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
|
||||||
|
struct ratio_op {
|
||||||
|
using calc_ratio =
|
||||||
|
conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply<Result, UnitRatio>, ratio_divide<Result, UnitRatio>>;
|
||||||
|
static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen);
|
||||||
|
using ratio = ratio_op<calc_ratio, value, UnitExpDen, UnitRatio>::ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ExpList, Unit... Us>
|
||||||
|
struct derived_ratio;
|
||||||
|
|
||||||
|
template<Unit... Us>
|
||||||
|
struct derived_ratio<exp_list<>, Us...> {
|
||||||
|
using ratio = ::units::ratio<1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E, typename... ERest, Unit U, Unit... URest>
|
||||||
|
struct derived_ratio<exp_list<E, ERest...>, U, URest...> {
|
||||||
|
using rest_ratio = derived_ratio<exp_list<ERest...>, URest...>::ratio;
|
||||||
|
using ratio = ratio_op<rest_ratio, E::num, E::den, typename U::ratio>::ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D, Unit... Us>
|
||||||
|
using deduced_unit =
|
||||||
|
scaled_unit<typename detail::derived_ratio<typename D::recipe, Us...>::ratio, typename D::coherent_unit::reference>;
|
||||||
|
|
||||||
|
} // namespace units::detail
|
61
src/include/units/bits/derived_dimension_base.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/base_dimension.h>
|
||||||
|
#include <units/bits/external/downcasting.h>
|
||||||
|
#include <units/exp.h>
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A dimension of a derived quantity
|
||||||
|
*
|
||||||
|
* Expression of the dependence of a quantity on the base quantities (and their base dimensions) of a system of
|
||||||
|
* quantities as a product of powers of factors corresponding to the base quantities, omitting any numerical factors.
|
||||||
|
* A power of a factor is the factor raised to an exponent.
|
||||||
|
*
|
||||||
|
* A derived dimension can be formed from multiple exponents (i.e. velocity is represented as "exp<L, 1>, exp<T, -1>").
|
||||||
|
* It is also possible to form a derived dimension with only one exponent (i.e. frequency is represented as just
|
||||||
|
* "exp<T, -1>").
|
||||||
|
*
|
||||||
|
* @note This class template is used by the library engine and should not be directly instantiated by the user.
|
||||||
|
*
|
||||||
|
* @tparam E a first exponent of a derived dimension
|
||||||
|
* @tparam ERest zero or more following exponents of a derived dimension
|
||||||
|
*/
|
||||||
|
template<Exponent E, Exponent... ERest>
|
||||||
|
requires (BaseDimension<typename E::dimension> && ... && BaseDimension<typename ERest::dimension>)
|
||||||
|
struct derived_dimension_base : downcast_base<derived_dimension_base<E, ERest...>> {
|
||||||
|
using exponents = exp_list<E, ERest...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct to_derived_dimension_base;
|
||||||
|
|
||||||
|
template<Exponent... Es>
|
||||||
|
struct to_derived_dimension_base<exp_list<Es...>> {
|
||||||
|
using type = derived_dimension_base<Es...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace units::detail
|
67
src/include/units/bits/dim_consolidate.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/external/type_list.h>
|
||||||
|
#include <units/exp.h>
|
||||||
|
#include <ratio> // TODO remove this dependency with #11
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Consolidates contiguous ranges of exponents of the same dimension
|
||||||
|
*
|
||||||
|
* If there is more than one exponent with the same dimension they are aggregated into one exponent by adding
|
||||||
|
* their exponents. If this accumulation will result with 0, such a dimension is removed from the list.
|
||||||
|
*
|
||||||
|
* @tparam D derived dimension to consolidate
|
||||||
|
*/
|
||||||
|
template<typename ExpList>
|
||||||
|
struct dim_consolidate;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct dim_consolidate<exp_list<>> {
|
||||||
|
using type = exp_list<>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
struct dim_consolidate<exp_list<E>> {
|
||||||
|
using type = exp_list<E>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E1, typename... ERest>
|
||||||
|
struct dim_consolidate<exp_list<E1, ERest...>> {
|
||||||
|
using type = type_list_push_front<typename dim_consolidate<exp_list<ERest...>>::type, E1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension Dim, int Num1, int Den1, int Num2, int Den2, typename... ERest>
|
||||||
|
struct dim_consolidate<exp_list<exp<Dim, Num1, Den1>, exp<Dim, Num2, Den2>, ERest...>> {
|
||||||
|
// TODO: provide custom implementation for ratio_add
|
||||||
|
using r1 = std::ratio<Num1, Den1>;
|
||||||
|
using r2 = std::ratio<Num2, Den2>;
|
||||||
|
using r = std::ratio_add<r1, r2>;
|
||||||
|
using type = conditional<r::num == 0, typename dim_consolidate<exp_list<ERest...>>::type,
|
||||||
|
typename dim_consolidate<exp_list<exp<Dim, r::num, r::den>, ERest...>>::type>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace units::detail
|
@@ -22,29 +22,38 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
#include <units/bits/derived_dimension_base.h>
|
||||||
#include <units/quantity.h>
|
#include <units/bits/external/type_list.h>
|
||||||
|
#include <units/exp.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::detail {
|
||||||
|
|
||||||
struct mass : derived_dimension<mass, exp<base_dim_mass, 1>> {};
|
/**
|
||||||
|
* @brief Unpacks the list of potentially derived dimensions to a list containing only base dimensions
|
||||||
|
*
|
||||||
|
* @tparam Es Exponents of potentially derived dimensions
|
||||||
|
*/
|
||||||
|
template<Exponent... Es>
|
||||||
|
struct dim_unpack;
|
||||||
|
|
||||||
template<typename T>
|
template<>
|
||||||
concept Mass = QuantityOf<T, mass>;
|
struct dim_unpack<> {
|
||||||
|
using type = exp_list<>;
|
||||||
|
};
|
||||||
|
|
||||||
struct gram : named_scaled_derived_unit<gram, mass, "g", ratio<1, 1000>, si_prefix> {};
|
template<BaseDimension Dim, int Num, int Den, Exponent... ERest>
|
||||||
struct kilogram : prefixed_derived_unit<kilogram, kilo, gram> {};
|
struct dim_unpack<exp<Dim, Num, Den>, ERest...> {
|
||||||
|
using type = type_list_push_front<typename dim_unpack<ERest...>::type, exp<Dim, Num, Den>>;
|
||||||
|
};
|
||||||
|
|
||||||
inline namespace literals {
|
template<DerivedDimension Dim, int Num, int Den, Exponent... ERest>
|
||||||
|
struct dim_unpack<exp<Dim, Num, Den>, ERest...> {
|
||||||
|
using type = dim_unpack<exp<downcast_base_t<Dim>, Num, Den>, ERest...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
// g
|
template<Exponent... Es, int Num, int Den, Exponent... ERest>
|
||||||
constexpr auto operator""g(unsigned long long l) { return quantity<gram, std::int64_t>(l); }
|
struct dim_unpack<exp<derived_dimension_base<Es...>, Num, Den>, ERest...> {
|
||||||
constexpr auto operator""g(long double l) { return quantity<gram, long double>(l); }
|
using type = type_list_push_front<typename dim_unpack<ERest...>::type, exp_multiply<Es, Num, Den>...>;
|
||||||
|
};
|
||||||
|
|
||||||
// kg
|
} // namespace units::detail
|
||||||
constexpr auto operator""kg(unsigned long long l) { return quantity<kilogram, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""kg(long double l) { return quantity<kilogram, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
266
src/include/units/bits/dimension_op.h
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
|
#include <units/unit.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
// equivalent_dim
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
struct equivalent_dim_impl : std::false_type {};
|
||||||
|
|
||||||
|
template<BaseDimension D1, BaseDimension D2>
|
||||||
|
struct equivalent_base_dim : std::conjunction<std::bool_constant<D1::symbol == D2::symbol>,
|
||||||
|
same_unit_reference<typename D1::base_unit, typename D2::base_unit>> {};
|
||||||
|
|
||||||
|
template<BaseDimension D1, BaseDimension D2>
|
||||||
|
struct equivalent_dim_impl<D1, D2> : std::disjunction<std::is_same<D1, D2>, equivalent_base_dim<D1, D2>> {};
|
||||||
|
|
||||||
|
template<Exponent E1, Exponent E2>
|
||||||
|
struct equivalent_exp : std::false_type {};
|
||||||
|
|
||||||
|
template<BaseDimension Dim1, int Num, int Den, BaseDimension Dim2>
|
||||||
|
struct equivalent_exp<exp<Dim1, Num, Den>, exp<Dim2, Num, Den>> : equivalent_dim_impl<Dim1, Dim2> {};
|
||||||
|
|
||||||
|
template<DerivedDimension D1, DerivedDimension D2>
|
||||||
|
struct equivalent_derived_dim : std::false_type {};
|
||||||
|
|
||||||
|
template<typename... Es1, typename... Es2>
|
||||||
|
requires (sizeof...(Es1) == sizeof...(Es2))
|
||||||
|
struct equivalent_derived_dim<derived_dimension_base<Es1...>, derived_dimension_base<Es2...>> : std::conjunction<equivalent_exp<Es1, Es2>...> {};
|
||||||
|
|
||||||
|
template<DerivedDimension D1, DerivedDimension D2>
|
||||||
|
struct equivalent_dim_impl<D1, D2> : std::disjunction<std::is_same<D1, D2>, equivalent_derived_dim<downcast_base_t<D1>, downcast_base_t<D2>>> {};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
inline constexpr bool equivalent_dim = detail::equivalent_dim_impl<D1, D2>::value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unknown dimension
|
||||||
|
*
|
||||||
|
* Sometimes a temporary partial result of a complex calculation may not result in a predefined
|
||||||
|
* dimension. In such a case an `unknown_dimension` is created with a coherent unit of `unknown_unit`
|
||||||
|
* and ratio<1>.
|
||||||
|
*
|
||||||
|
* @tparam E the list of exponents of ingredient dimensions
|
||||||
|
* @tparam ERest the list of exponents of ingredient dimensions
|
||||||
|
*/
|
||||||
|
template<Exponent E, Exponent... ERest>
|
||||||
|
struct unknown_dimension : derived_dimension<unknown_dimension<E, ERest...>, scaled_unit<ratio<1>, unknown_unit>, E, ERest...> {
|
||||||
|
using coherent_unit = scaled_unit<ratio<1>, unknown_unit>;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<DerivedDimension D>
|
||||||
|
struct check_unknown {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
// downcast did not find a user predefined type
|
||||||
|
template<typename... Es>
|
||||||
|
struct check_unknown<derived_dimension_base<Es...>> {
|
||||||
|
using type = unknown_dimension<Es...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct downcast_dimension_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct downcast_dimension_impl<D> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D>
|
||||||
|
struct downcast_dimension_impl<D> {
|
||||||
|
using type = check_unknown<downcast<D>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
using downcast_dimension = detail::downcast_dimension_impl<D>::type;
|
||||||
|
|
||||||
|
// dim_invert
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct dim_invert_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dim_invert_impl<D> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp<D, -1>>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dim_invert_impl<derived_dimension_base<exp<D, -1>>> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Es>
|
||||||
|
struct dim_invert_impl<derived_dimension_base<Es...>> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp_invert<Es>...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D>
|
||||||
|
struct dim_invert_impl<D> : dim_invert_impl<downcast_base_t<D>> {
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
using dim_invert = detail::dim_invert_impl<D>::type;
|
||||||
|
|
||||||
|
// dimension_multiply
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct to_dimension;
|
||||||
|
|
||||||
|
template<Exponent... Es>
|
||||||
|
struct to_dimension<exp_list<Es...>> {
|
||||||
|
using type = derived_dimension_base<Es...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct to_dimension<exp_list<exp<D, 1>>> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Merges 2 sorted derived dimensions into one units::derived_dimension_base
|
||||||
|
*
|
||||||
|
* A result of a dimensional calculation may result with many exponents of the same base dimension orginated
|
||||||
|
* from different parts of the equation. As the exponents lists of both operands it is enough to merge them
|
||||||
|
* into one list and consolidate duplicates. Also it is possible that final exponents list will contain only
|
||||||
|
* one element being a base dimension with exponent 1. In such a case the final dimension should be the base
|
||||||
|
* dimension itself.
|
||||||
|
*/
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
using merge_dimension = to_dimension<typename dim_consolidate<type_list_merge_sorted<typename D1::exponents, typename D2::exponents, exp_less>>::type>::type;
|
||||||
|
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
struct dimension_multiply_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D1, BaseDimension D2>
|
||||||
|
struct dimension_multiply_impl<D1, D2> {
|
||||||
|
using type = downcast_dimension<merge_dimension<derived_dimension_base<exp<D1, 1>>, derived_dimension_base<exp<D2, 1>>>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D1, DerivedDimension D2>
|
||||||
|
struct dimension_multiply_impl<D1, D2> {
|
||||||
|
using type = downcast_dimension<merge_dimension<derived_dimension_base<exp<D1, 1>>, typename D2::downcast_base_type>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D1, BaseDimension D2>
|
||||||
|
struct dimension_multiply_impl<D1, D2> {
|
||||||
|
using type = dimension_multiply_impl<D2, D1>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D1, DerivedDimension D2>
|
||||||
|
struct dimension_multiply_impl<D1, D2> {
|
||||||
|
using type = downcast_dimension<merge_dimension<typename D1::downcast_base_type, typename D2::downcast_base_type>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
using dimension_multiply = detail::dimension_multiply_impl<D1, D2>::type;
|
||||||
|
|
||||||
|
template<Dimension D1, Dimension D2>
|
||||||
|
using dimension_divide = detail::dimension_multiply_impl<D1, dim_invert<D2>>::type;
|
||||||
|
|
||||||
|
// dimension_sqrt
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct dimension_sqrt_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dimension_sqrt_impl<D> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp<D, 1, 2>>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dimension_sqrt_impl<derived_dimension_base<exp<D, 2>>> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D>
|
||||||
|
struct dimension_sqrt_impl<D> {
|
||||||
|
using type = dimension_sqrt_impl<typename D::downcast_base_type>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Es>
|
||||||
|
struct dimension_sqrt_impl<derived_dimension_base<Es...>> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp_multiply<Es, 1, 2>...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
using dimension_sqrt = detail::dimension_sqrt_impl<D>::type;
|
||||||
|
|
||||||
|
// dimension_pow
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Dimension D, std::size_t N>
|
||||||
|
struct dimension_pow_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D, std::size_t N>
|
||||||
|
struct dimension_pow_impl<D, N> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp<D, N>>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dimension_pow_impl<D, 1> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<BaseDimension D, std::size_t N>
|
||||||
|
struct dimension_pow_impl<derived_dimension_base<exp<D, 1, N>>, N> {
|
||||||
|
using type = D;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D, std::size_t N>
|
||||||
|
struct dimension_pow_impl<D, N> {
|
||||||
|
using type = dimension_pow_impl<downcast_base_t<D>, N>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Es, std::size_t N>
|
||||||
|
struct dimension_pow_impl<derived_dimension_base<Es...>, N> {
|
||||||
|
using type = downcast_dimension<derived_dimension_base<exp_multiply<Es, N, 1>...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D, std::size_t N>
|
||||||
|
using dimension_pow = detail::dimension_pow_impl<D, N>::type;
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -22,23 +22,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/hacks.h>
|
#include <units/bits/external/hacks.h>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
template<typename BaseType>
|
template<typename BaseType>
|
||||||
struct downcast_base {
|
struct downcast_base {
|
||||||
using base_type = BaseType;
|
using downcast_base_type = BaseType;
|
||||||
friend auto downcast_guide(downcast_base);
|
friend auto downcast_guide(downcast_base);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Downcastable =
|
concept Downcastable =
|
||||||
requires {
|
requires {
|
||||||
typename T::base_type;
|
typename T::downcast_base_type;
|
||||||
} &&
|
} &&
|
||||||
std::derived_from<T, downcast_base<typename T::base_type>>;
|
std::derived_from<T, downcast_base<typename T::downcast_base_type>>;
|
||||||
|
|
||||||
template<typename Target, Downcastable T>
|
template<typename Target, Downcastable T>
|
||||||
struct downcast_child : T {
|
struct downcast_child : T {
|
||||||
@@ -67,6 +67,6 @@ namespace units {
|
|||||||
using downcast = decltype(detail::downcast_impl<T>());
|
using downcast = decltype(detail::downcast_impl<T>());
|
||||||
|
|
||||||
template<Downcastable T>
|
template<Downcastable T>
|
||||||
using downcast_base_t = T::base_type;
|
using downcast_base_t = T::downcast_base_type;
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <concepts/concepts.hpp>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
@@ -32,16 +31,24 @@
|
|||||||
#define Expects(cond) assert(cond);
|
#define Expects(cond) assert(cond);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __GNUC__ > 9
|
#if __GNUC__ < 10
|
||||||
#define AUTO auto
|
|
||||||
#define SAME_AS(T) std::same_as<T>
|
#include <concepts/concepts.hpp>
|
||||||
#else
|
|
||||||
#define AUTO
|
#define AUTO
|
||||||
#define SAME_AS(T) T
|
#define SAME_AS(T) T
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#define AUTO auto
|
||||||
|
#define SAME_AS(T) std::same_as<T>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
|
#if __GNUC__ < 10
|
||||||
|
|
||||||
// concepts
|
// concepts
|
||||||
using concepts::common_reference_with;
|
using concepts::common_reference_with;
|
||||||
using concepts::common_with;
|
using concepts::common_with;
|
||||||
@@ -64,4 +71,11 @@ namespace std {
|
|||||||
template<class F, class... Args>
|
template<class F, class... Args>
|
||||||
concept regular_invocable = invocable<F, Args...>;
|
concept regular_invocable = invocable<F, Args...>;
|
||||||
|
|
||||||
}
|
#else
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
concept default_constructible = constructible_from<T>;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace std
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/hacks.h>
|
#include <units/bits/external/hacks.h>
|
||||||
|
|
||||||
// P1813 - A Concept Design for the Numeric Algorithms
|
// P1813 - A Concept Design for the Numeric Algorithms
|
||||||
|
|
64
src/include/units/bits/external/text_tools.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/external/fixed_string.h>
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
template<int Value>
|
||||||
|
requires (0 <= Value) && (Value < 10)
|
||||||
|
inline constexpr basic_fixed_string superscript_number = "";
|
||||||
|
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<0> = "\u2070";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<1> = "\u00b9";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<2> = "\u00b2";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<3> = "\u00b3";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<4> = "\u2074";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<5> = "\u2075";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<6> = "\u2076";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<7> = "\u2077";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<8> = "\u2078";
|
||||||
|
template<> inline constexpr basic_fixed_string superscript_number<9> = "\u2079";
|
||||||
|
|
||||||
|
template<int Value>
|
||||||
|
requires (Value >= 0)
|
||||||
|
constexpr auto superscript()
|
||||||
|
{
|
||||||
|
if constexpr(Value < 10)
|
||||||
|
return superscript_number<Value>;
|
||||||
|
else
|
||||||
|
return superscript<Value / 10>() + superscript<Value % 10>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int Value>
|
||||||
|
requires (Value >= 0)
|
||||||
|
constexpr auto regular()
|
||||||
|
{
|
||||||
|
if constexpr(Value < 10)
|
||||||
|
return basic_fixed_string(static_cast<char>('0' + Value));
|
||||||
|
else
|
||||||
|
return regular<Value / 10>() + regular<Value % 10>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units::detail
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/type_traits.h>
|
#include <units/bits/external/type_traits.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
78
src/include/units/bits/external/type_traits.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
// conditional
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<bool>
|
||||||
|
struct conditional_impl {
|
||||||
|
template<typename T, typename F>
|
||||||
|
using type = F;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct conditional_impl<true> {
|
||||||
|
template<typename T, typename F>
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<bool B, typename T, typename F>
|
||||||
|
using conditional = detail::conditional_impl<B>::template type<T, F>;
|
||||||
|
|
||||||
|
// is_instantiation
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T, template<typename...> typename Type>
|
||||||
|
inline constexpr bool is_instantiation_impl = false;
|
||||||
|
|
||||||
|
template<typename... Params, template<typename...> typename Type>
|
||||||
|
inline constexpr bool is_instantiation_impl<Type<Params...>, Type> = true;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T, template<typename...> typename Type>
|
||||||
|
inline constexpr bool is_instantiation = detail::is_instantiation_impl<T, Type>;
|
||||||
|
|
||||||
|
// is_derived_from_instantiation
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<template<typename...> typename Type>
|
||||||
|
struct is_derived_from_instantiation_impl {
|
||||||
|
template<typename... Params>
|
||||||
|
static constexpr std::true_type check_base(const Type<Params...>&);
|
||||||
|
static constexpr std::true_type check_base(...);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T, template<typename...> typename Type>
|
||||||
|
inline constexpr bool is_derived_from_instantiation = decltype(detail::is_derived_from_instantiation_impl<Type>::check_base(std::declval<T>()))::value;
|
||||||
|
|
||||||
|
} // namespace units
|
128
src/include/units/bits/unit_text.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
|
|
||||||
|
namespace units::detail {
|
||||||
|
|
||||||
|
template<typename Ratio>
|
||||||
|
constexpr auto ratio_text()
|
||||||
|
{
|
||||||
|
if constexpr(Ratio::num != 1 || Ratio::den != 1) {
|
||||||
|
auto txt = basic_fixed_string("[") + regular<Ratio::num>();
|
||||||
|
if constexpr(Ratio::den == 1) {
|
||||||
|
return txt + basic_fixed_string("]");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return txt + basic_fixed_string("/") + regular<Ratio::den>() + basic_fixed_string("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return basic_fixed_string("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ratio, typename PrefixType>
|
||||||
|
constexpr auto prefix_or_ratio_text()
|
||||||
|
{
|
||||||
|
if constexpr(Ratio::num == 1 && Ratio::den == 1) {
|
||||||
|
// no ratio/prefix
|
||||||
|
return basic_fixed_string("");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if constexpr (!std::same_as<PrefixType, no_prefix>) {
|
||||||
|
// try to form a prefix
|
||||||
|
using prefix = downcast<detail::prefix_base<PrefixType, Ratio>>;
|
||||||
|
|
||||||
|
if constexpr(!std::same_as<prefix, prefix_base<PrefixType, Ratio>>) {
|
||||||
|
// print as a prefixed unit
|
||||||
|
return prefix::symbol;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// print as a ratio of the coherent unit
|
||||||
|
return ratio_text<Ratio>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// print as a ratio of the coherent unit
|
||||||
|
return ratio_text<Ratio>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Es, std::size_t... Idxs>
|
||||||
|
constexpr auto derived_dimension_unit_text(exp_list<Es...>, std::index_sequence<Idxs...>)
|
||||||
|
{
|
||||||
|
return (exp_text<Es, dimension_unit<typename Es::dimension>::symbol, Idxs>() + ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Es>
|
||||||
|
constexpr auto derived_dimension_unit_text(exp_list<Es...> list)
|
||||||
|
{
|
||||||
|
return derived_dimension_unit_text(list, std::index_sequence_for<Es...>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Es>
|
||||||
|
constexpr bool all_named(exp_list<Es...>)
|
||||||
|
{
|
||||||
|
return (dimension_unit<typename Es::dimension>::is_named && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Dimension Dim>
|
||||||
|
constexpr auto derived_dimension_unit_text()
|
||||||
|
{
|
||||||
|
using recipe = typename Dim::recipe;
|
||||||
|
if constexpr(all_named(recipe()))
|
||||||
|
return derived_dimension_unit_text(recipe());
|
||||||
|
else
|
||||||
|
return derived_dimension_unit_text(typename Dim::exponents());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Inline below concept when switched to gcc-10
|
||||||
|
template<typename T>
|
||||||
|
concept has_symbol = requires{ T::symbol; };
|
||||||
|
|
||||||
|
template<Dimension Dim, Unit U>
|
||||||
|
constexpr auto unit_text()
|
||||||
|
{
|
||||||
|
if constexpr(has_symbol<U>) {
|
||||||
|
// already has a symbol so print it
|
||||||
|
return U::symbol;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// print as a prefix or ratio of a reference unit
|
||||||
|
auto prefix_txt = prefix_or_ratio_text<typename U::ratio, typename U::reference::prefix_type>();
|
||||||
|
|
||||||
|
if constexpr(has_symbol<typename U::reference>) {
|
||||||
|
// use predefined reference unit symbol
|
||||||
|
return prefix_txt + U::reference::symbol;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// use derived dimension ingredients to create a unit symbol
|
||||||
|
return prefix_txt + derived_dimension_unit_text<Dim>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units::detail
|
187
src/include/units/concepts.h
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/bits/external/downcasting.h>
|
||||||
|
#include <units/bits/external/fixed_string.h>
|
||||||
|
#include <units/bits/external/hacks.h>
|
||||||
|
#include <units/bits/external/numeric_concepts.h>
|
||||||
|
#include <units/bits/external/type_traits.h>
|
||||||
|
#include <units/customization_points.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T, typename U = T>
|
||||||
|
concept basic_arithmetic = // exposition only
|
||||||
|
std::magma<std::ranges::plus, T, U> &&
|
||||||
|
std::magma<std::ranges::minus, T, U> &&
|
||||||
|
std::magma<std::ranges::times, T, U> &&
|
||||||
|
std::magma<std::ranges::divided_by, T, U>;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// PrefixType
|
||||||
|
struct prefix_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept PrefixType = std::derived_from<T, prefix_type>;
|
||||||
|
|
||||||
|
// Prefix
|
||||||
|
// TODO gcc:92150
|
||||||
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92150
|
||||||
|
// namespace detail {
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// inline constexpr bool is_prefix = false;
|
||||||
|
|
||||||
|
// template<typename PrefixType, Ratio R, basic_fixed_string Symbol>
|
||||||
|
// inline constexpr bool is_prefix<prefix<PrefixType, R, Symbol>> = true;
|
||||||
|
|
||||||
|
// } // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
// concept Prefix = detail::is_prefix<T>;
|
||||||
|
concept Prefix = true;
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_ratio = false;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Ratio = detail::is_ratio<T>;
|
||||||
|
|
||||||
|
|
||||||
|
// UnitRatio
|
||||||
|
template<typename R>
|
||||||
|
concept UnitRatio = Ratio<R> && (R::num * R::den > 0);
|
||||||
|
|
||||||
|
// Unit
|
||||||
|
template<UnitRatio R, typename U>
|
||||||
|
struct scaled_unit;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Unit = is_derived_from_instantiation<T, scaled_unit>;
|
||||||
|
|
||||||
|
// BaseDimension
|
||||||
|
template<basic_fixed_string Symbol, Unit U>
|
||||||
|
requires U::is_named
|
||||||
|
struct base_dimension;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
#if __GNUC__ == 9 && __GNUC_MINOR__ < 2
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_base_dimension = true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_base_dimension = false;
|
||||||
|
|
||||||
|
template<basic_fixed_string Name, typename... Params>
|
||||||
|
inline constexpr bool is_base_dimension<base_dimension<Name, Params...>> = true;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept BaseDimension = detail::is_base_dimension<typename T::base_type_workaround>;
|
||||||
|
|
||||||
|
// Exponent
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_exp = false;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Exponent = detail::is_exp<T>;
|
||||||
|
|
||||||
|
// DerivedDimension
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Exponent E, Exponent... ERest>
|
||||||
|
requires (BaseDimension<typename E::dimension> && ... && BaseDimension<typename ERest::dimension>)
|
||||||
|
struct derived_dimension_base;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept DerivedDimension = is_instantiation<downcast_base_t<T>, detail::derived_dimension_base>;
|
||||||
|
|
||||||
|
// Dimension
|
||||||
|
template<typename T>
|
||||||
|
concept Dimension = BaseDimension<T> || DerivedDimension<T>;
|
||||||
|
|
||||||
|
// UnitOf
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct dimension_unit_impl;
|
||||||
|
|
||||||
|
template<BaseDimension D>
|
||||||
|
struct dimension_unit_impl<D> {
|
||||||
|
using type = D::base_unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension D>
|
||||||
|
struct dimension_unit_impl<D> {
|
||||||
|
using type = D::coherent_unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
using dimension_unit = detail::dimension_unit_impl<D>::type;
|
||||||
|
|
||||||
|
template<typename U, typename D>
|
||||||
|
concept UnitOf =
|
||||||
|
Unit<U> &&
|
||||||
|
Dimension<D> &&
|
||||||
|
std::same_as<typename U::reference, typename dimension_unit<D>::reference>;
|
||||||
|
|
||||||
|
// Quantity
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_quantity = false;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Quantity = detail::is_quantity<T>;
|
||||||
|
|
||||||
|
// Scalar
|
||||||
|
template<typename T>
|
||||||
|
concept Scalar = (!Quantity<T>) && std::regular<T> && std::totally_ordered<T> && detail::basic_arithmetic<T>;
|
||||||
|
|
||||||
|
} // namespace units
|
141
src/include/units/customization_points.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specifies if a value of a type should be treated as a floating-point value
|
||||||
|
*
|
||||||
|
* This type trait should be specialized for a custom representation type to specify
|
||||||
|
* that values fo this type should be treated by the library as a floating-point ones
|
||||||
|
* which will enable implicit conversions between quantities.
|
||||||
|
*
|
||||||
|
* @tparam Rep a representation type for which a type trait is defined
|
||||||
|
*/
|
||||||
|
template<typename Rep>
|
||||||
|
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A type trait that defines zero, one, min, and max for a representation type
|
||||||
|
*
|
||||||
|
* The zero, one, min, and max member functions in units::quantity forward their work to
|
||||||
|
* these methods. This type can be specialized if the representation Rep requires a specific
|
||||||
|
* implementation to return these quantity objects.
|
||||||
|
*
|
||||||
|
* @tparam Rep a representation type for which a type trait is defined
|
||||||
|
*/
|
||||||
|
template<typename Rep>
|
||||||
|
struct quantity_values {
|
||||||
|
static constexpr Rep zero() noexcept { return Rep(0); }
|
||||||
|
static constexpr Rep one() noexcept { return Rep(1); }
|
||||||
|
static constexpr Rep min() noexcept { return std::numeric_limits<Rep>::lowest(); }
|
||||||
|
static constexpr Rep max() noexcept { return std::numeric_limits<Rep>::max(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // isnan
|
||||||
|
// namespace isnan_impl {
|
||||||
|
|
||||||
|
// // non-ADL lookup block
|
||||||
|
// void isnan(); // undefined
|
||||||
|
|
||||||
|
// template<typename>
|
||||||
|
// inline constexpr bool has_customization = false;
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires requires(const T& t) {
|
||||||
|
// { isnan(t) } -> bool;
|
||||||
|
// }
|
||||||
|
// inline constexpr bool has_customization<T> = true;
|
||||||
|
|
||||||
|
// struct fn {
|
||||||
|
// template<typename T>
|
||||||
|
// constexpr bool operator()(const T&) const
|
||||||
|
// {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires treat_as_floating_point<T>
|
||||||
|
// constexpr bool operator()(const T& value) const
|
||||||
|
// {
|
||||||
|
// return std::isnan(value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires treat_as_floating_point<T> && has_customization<T>
|
||||||
|
// constexpr bool operator()(const T& value) const
|
||||||
|
// {
|
||||||
|
// return isnan(value); // uses ADL
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// inline constexpr isnan_impl::fn isnan{};
|
||||||
|
|
||||||
|
// // isfinite
|
||||||
|
// namespace isfinite_impl {
|
||||||
|
|
||||||
|
// // non-ADL lookup block
|
||||||
|
// void isfinite(); // undefined
|
||||||
|
|
||||||
|
// template<typename>
|
||||||
|
// inline constexpr bool has_customization = false;
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires requires(const T& t) {
|
||||||
|
// { isfinite(t) } -> bool;
|
||||||
|
// }
|
||||||
|
// inline constexpr bool has_customization<T> = true;
|
||||||
|
|
||||||
|
// struct fn {
|
||||||
|
// template<typename T>
|
||||||
|
// constexpr bool operator()(const T&) const
|
||||||
|
// {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires treat_as_floating_point<T>
|
||||||
|
// constexpr bool operator()(const T& value) const
|
||||||
|
// {
|
||||||
|
// return std::isfinite(value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// requires treat_as_floating_point<T> && has_customization<T>
|
||||||
|
// constexpr bool operator()(const T& value) const
|
||||||
|
// {
|
||||||
|
// return isfinite(value); // uses ADL
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// inline constexpr isfinite_impl::fn isfinite{};
|
||||||
|
|
||||||
|
} // namespace units
|
59
src/include/units/data/bitrate.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/data/information.h>
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
|
#include <units/physical/si/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::data {
|
||||||
|
|
||||||
|
struct bit_per_second : unit<bit_per_second> {};
|
||||||
|
struct dim_bitrate : derived_dimension<dim_bitrate, bit_per_second, exp<dim_information, 1>, exp<si::dim_time, -1>> {};
|
||||||
|
|
||||||
|
struct kibibit_per_second : deduced_unit<kibibit_per_second, dim_bitrate, kibibit, si::second> {};
|
||||||
|
struct mebibit_per_second : deduced_unit<mebibit_per_second, dim_bitrate, mebibit, si::second> {};
|
||||||
|
struct gibibit_per_second : deduced_unit<gibibit_per_second, dim_bitrate, gibibit, si::second> {};
|
||||||
|
struct tebibit_per_second : deduced_unit<tebibit_per_second, dim_bitrate, tebibit, si::second> {};
|
||||||
|
struct pebibit_per_second : deduced_unit<pebibit_per_second, dim_bitrate, pebibit, si::second> {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Bitrate = QuantityOf<T, dim_bitrate>;
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using bitrate = quantity<dim_bitrate, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// bits
|
||||||
|
constexpr auto operator""_bps(unsigned long long l) { return bitrate<bit_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_Kibps(unsigned long long l) { return bitrate<kibibit_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_Mibps(unsigned long long l) { return bitrate<mebibit_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_Gibps(unsigned long long l) { return bitrate<gibibit_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_Tibps(unsigned long long l) { return bitrate<tebibit_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_Pibps(unsigned long long l) { return bitrate<pebibit_per_second, std::int64_t>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::data
|
74
src/include/units/data/information.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/base_dimension.h>
|
||||||
|
#include <units/data/prefixes.h>
|
||||||
|
#include <units/unit.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::data {
|
||||||
|
|
||||||
|
struct bit : named_unit<bit, "b", prefix> {};
|
||||||
|
struct kibibit : prefixed_unit<kibibit, kibi, bit> {};
|
||||||
|
struct mebibit : prefixed_unit<mebibit, mebi, bit> {};
|
||||||
|
struct gibibit : prefixed_unit<gibibit, gibi, bit> {};
|
||||||
|
struct tebibit : prefixed_unit<tebibit, tebi, bit> {};
|
||||||
|
struct pebibit : prefixed_unit<pebibit, pebi, bit> {};
|
||||||
|
|
||||||
|
struct byte : named_scaled_unit<byte, "B", prefix, ratio<8>, bit> {};
|
||||||
|
struct kibibyte : prefixed_unit<kibibyte, kibi, byte> {};
|
||||||
|
struct mebibyte : prefixed_unit<mebibyte, mebi, byte> {};
|
||||||
|
struct gibibyte : prefixed_unit<gibibyte, gibi, byte> {};
|
||||||
|
struct tebibyte : prefixed_unit<tebibyte, tebi, byte> {};
|
||||||
|
struct pebibyte : prefixed_unit<pebibyte, pebi, byte> {};
|
||||||
|
|
||||||
|
struct dim_information : base_dimension<"information", bit> {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Information = QuantityOf<T, dim_information>;
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using information = quantity<dim_information, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// bits
|
||||||
|
constexpr auto operator""b(unsigned long long l) { return information<bit, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Kib(unsigned long long l) { return information<kibibit, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Mib(unsigned long long l) { return information<mebibit, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Gib(unsigned long long l) { return information<gibibit, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Tib(unsigned long long l) { return information<tebibit, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Pib(unsigned long long l) { return information<pebibit, std::int64_t>(l); }
|
||||||
|
|
||||||
|
// bytes
|
||||||
|
constexpr auto operator""B(unsigned long long l) { return information<byte, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""KiB(unsigned long long l) { return information<kibibyte, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""MiB(unsigned long long l) { return information<mebibyte, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""GiB(unsigned long long l) { return information<gibibyte, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""TiB(unsigned long long l) { return information<tebibyte, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""PiB(unsigned long long l) { return information<pebibyte, std::int64_t>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::data
|
@@ -22,23 +22,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/velocity.h>
|
#include <units/prefix.h>
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
namespace units {
|
namespace units::data {
|
||||||
|
|
||||||
struct acceleration : derived_dimension<acceleration, exp<velocity, 1>, exp<time, -1>> {};
|
struct prefix : prefix_type {};
|
||||||
|
|
||||||
template<typename T>
|
struct kibi : units::prefix<kibi, prefix, "Ki", ratio< 1'024>> {};
|
||||||
concept Acceleration = QuantityOf<T, acceleration>;
|
struct mebi : units::prefix<mebi, prefix, "Mi", ratio< 1'048'576>> {};
|
||||||
|
struct gibi : units::prefix<gibi, prefix, "Gi", ratio< 1'073'741'824>> {};
|
||||||
|
struct tebi : units::prefix<tebi, prefix, "Ti", ratio< 1'099'511'627'776>> {};
|
||||||
|
struct pebi : units::prefix<pebi, prefix, "Pi", ratio< 1'125'899'906'842'624>> {};
|
||||||
|
struct exbi : units::prefix<exbi, prefix, "Ei", ratio<1'152'921'504'606'846'976>> {};
|
||||||
|
|
||||||
struct metre_per_second_sq : coherent_derived_unit<metre_per_second_sq, acceleration> {};
|
} // namespace units::si
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// mps_sq
|
|
||||||
constexpr auto operator""mps_sq(unsigned long long l) { return quantity<metre_per_second_sq, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mps_sq(long double l) { return quantity<metre_per_second_sq, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
78
src/include/units/derived_dimension.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/base_dimension.h>
|
||||||
|
#include <units/bits/base_units_ratio.h>
|
||||||
|
#include <units/bits/derived_dimension_base.h>
|
||||||
|
#include <units/bits/dim_consolidate.h>
|
||||||
|
#include <units/bits/dim_unpack.h>
|
||||||
|
#include <units/bits/external/downcasting.h>
|
||||||
|
#include <units/bits/external/type_list.h>
|
||||||
|
#include <units/exp.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts user provided derived dimension specification into a valid units::derived_dimension_base definition
|
||||||
|
*
|
||||||
|
* User provided definition of a derived dimension may contain the same base dimension repeated more than once on the
|
||||||
|
* list possibly hidden in other derived units provided by the user. The process here should:
|
||||||
|
* 1. Extract derived dimensions into exponents of base dimensions.
|
||||||
|
* 2. Sort the exponents so the same dimensions are placed next to each other.
|
||||||
|
* 3. Consolidate contiguous range of exponents of the same base dimensions to a one (or possibly zero) exponent for
|
||||||
|
* this base dimension.
|
||||||
|
*/
|
||||||
|
template<Exponent... Es>
|
||||||
|
using make_dimension = to_derived_dimension_base<typename dim_consolidate<type_list_sort<typename dim_unpack<Es...>::type, exp_less>>::type>::type;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The list of exponents of dimensions (both base and derived) provided by the user
|
||||||
|
*
|
||||||
|
* This is the user's interface to create derived dimensions. Exponents list can contain powers of factors of both
|
||||||
|
* base and derived dimensions. This is called a "recipe" of the dimension and among others is used to print
|
||||||
|
* unnamed coherent units of this dimension.
|
||||||
|
*
|
||||||
|
* Coherent unit is a unit that, for a given system of quantities and for a chosen set of base units, is a product
|
||||||
|
* of powers of base units with no other proportionality factor than one.
|
||||||
|
*
|
||||||
|
* The implementation is responsible for unpacking all of the dimensions into a list containing only base dimensions
|
||||||
|
* and their factors and putting them to derived_dimension_base class template.
|
||||||
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
* @tparam U a coherent unit of a derived dimension
|
||||||
|
* @tparam E the list of exponents of ingredient dimensions
|
||||||
|
* @tparam ERest the list of exponents of ingredient dimensions
|
||||||
|
*/
|
||||||
|
template<typename Child, Unit U, Exponent E, Exponent... ERest>
|
||||||
|
struct derived_dimension : downcast_child<Child, typename detail::make_dimension<E, ERest...>> {
|
||||||
|
using recipe = exp_list<E, ERest...>;
|
||||||
|
using coherent_unit = U;
|
||||||
|
using base_units_ratio = detail::base_units_ratio<derived_dimension>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -1,292 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/bits/type_list.h>
|
|
||||||
#include <units/bits/downcasting.h>
|
|
||||||
#include <units/bits/fixed_string.h>
|
|
||||||
#include <units/ratio.h>
|
|
||||||
#include <ratio>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
template<basic_fixed_string Name, basic_fixed_string Symbol>
|
|
||||||
struct base_dimension {
|
|
||||||
static constexpr auto name = Name;
|
|
||||||
static constexpr auto symbol = Symbol;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept BaseDimension = std::is_empty_v<T> &&
|
|
||||||
requires {
|
|
||||||
T::name;
|
|
||||||
T::symbol;
|
|
||||||
};// && // TODO file a bug for this gcc issue
|
|
||||||
// std::derived_from<T, base_dimension<T::name, T::symbol>>;
|
|
||||||
|
|
||||||
// base_dimension_less
|
|
||||||
|
|
||||||
template<BaseDimension D1, BaseDimension D2>
|
|
||||||
struct base_dimension_less : std::bool_constant<D1::name < D2::name> {
|
|
||||||
};
|
|
||||||
|
|
||||||
// is_exp
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline constexpr bool is_exp = false;
|
|
||||||
|
|
||||||
// partial specialization for an exp type provided below
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Exponent = detail::is_exp<T>;
|
|
||||||
|
|
||||||
template<Exponent... Es>
|
|
||||||
struct dimension;
|
|
||||||
|
|
||||||
// is_dimension
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline constexpr bool is_dimension = false;
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
inline constexpr bool is_dimension<dimension<Es...>> = true;
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Dimension =
|
|
||||||
std::is_empty_v<T> &&
|
|
||||||
detail::is_dimension<downcast_base_t<T>>;
|
|
||||||
|
|
||||||
// exp
|
|
||||||
template<typename BaseOrDim, int Num, int Den = 1>
|
|
||||||
requires BaseDimension<BaseOrDim> || Dimension<BaseOrDim>
|
|
||||||
struct exp {
|
|
||||||
using dimension = BaseOrDim;
|
|
||||||
static constexpr int num = Num;
|
|
||||||
static constexpr int den = Den;
|
|
||||||
};
|
|
||||||
|
|
||||||
// is_exp
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename Dim, int Num, int Den>
|
|
||||||
inline constexpr bool is_exp<exp<Dim, Num, Den>> = true;
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// exp_less
|
|
||||||
template<Exponent E1, Exponent E2>
|
|
||||||
struct exp_less : base_dimension_less<typename E1::dimension, typename E2::dimension> {
|
|
||||||
};
|
|
||||||
|
|
||||||
// exp_invert
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<Exponent E>
|
|
||||||
struct exp_invert_impl;
|
|
||||||
|
|
||||||
template<typename Dim, int Num, int Den>
|
|
||||||
struct exp_invert_impl<exp<Dim, Num, Den>> {
|
|
||||||
using type = exp<Dim, -Num, Den>;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Exponent E>
|
|
||||||
using exp_invert = detail::exp_invert_impl<E>::type;
|
|
||||||
|
|
||||||
// exp_multiply
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<Exponent E, int Num, int Den>
|
|
||||||
struct exp_multiply_impl {
|
|
||||||
using r1 = ratio<E::num, E::den>;
|
|
||||||
using r2 = ratio<Num, Den>;
|
|
||||||
using r = ratio_multiply<r1, r2>;
|
|
||||||
using type = exp<typename E::dimension, r::num, r::den>;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Exponent E, int Num, int Den>
|
|
||||||
using exp_multiply = detail::exp_multiply_impl<E, Num, Den>::type;
|
|
||||||
|
|
||||||
// dimension
|
|
||||||
template<Exponent... Es>
|
|
||||||
struct dimension : downcast_base<dimension<Es...>> {};
|
|
||||||
|
|
||||||
// same_dim
|
|
||||||
template<typename D1, Dimension D2>
|
|
||||||
requires BaseDimension<D1> || Dimension<D1>
|
|
||||||
inline constexpr bool same_dim = std::is_same_v<typename D1::base_type, typename D2::base_type>;
|
|
||||||
|
|
||||||
template<BaseDimension D1, Dimension D2>
|
|
||||||
inline constexpr bool same_dim<D1, D2> = std::is_same_v<dimension<units::exp<D1, 1>>, typename D2::base_type>;
|
|
||||||
|
|
||||||
// dim_invert
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<Dimension E>
|
|
||||||
struct dim_invert_impl;
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
struct dim_invert_impl<dimension<Es...>> : std::type_identity<downcast<dimension<exp_invert<Es>...>>> {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D>
|
|
||||||
using dim_invert = detail::dim_invert_impl<downcast_base_t<D>>::type;
|
|
||||||
|
|
||||||
// make_dimension
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<Dimension D>
|
|
||||||
struct dim_consolidate;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct dim_consolidate<dimension<>> {
|
|
||||||
using type = dimension<>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename E>
|
|
||||||
struct dim_consolidate<dimension<E>> {
|
|
||||||
using type = dimension<E>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename E1, typename... ERest>
|
|
||||||
struct dim_consolidate<dimension<E1, ERest...>> {
|
|
||||||
using type = type_list_push_front<typename dim_consolidate<dimension<ERest...>>::type, E1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<BaseDimension D, int Num1, int Den1, int Num2, int Den2, typename... ERest>
|
|
||||||
struct dim_consolidate<dimension<exp<D, Num1, Den1>, exp<D, Num2, Den2>, ERest...>> {
|
|
||||||
// TODO: provide custom implementation for ratio_add
|
|
||||||
using r1 = std::ratio<Num1, Den1>;
|
|
||||||
using r2 = std::ratio<Num2, Den2>;
|
|
||||||
using r = std::ratio_add<r1, r2>;
|
|
||||||
using type = conditional<r::num == 0, typename dim_consolidate<dimension<ERest...>>::type,
|
|
||||||
typename dim_consolidate<dimension<exp<D, r::num, r::den>, ERest...>>::type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<Exponent... Es>
|
|
||||||
struct extract;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct extract<> {
|
|
||||||
using type = dimension<>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<BaseDimension Dim, int Num, int Den, Exponent... ERest>
|
|
||||||
struct extract<exp<Dim, Num, Den>, ERest...> {
|
|
||||||
using type = type_list_push_front<typename extract<ERest...>::type, exp<Dim, Num, Den>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<Exponent... Es, int Num, int Den, Exponent... ERest>
|
|
||||||
struct extract<exp<dimension<Es...>, Num, Den>, ERest...> {
|
|
||||||
using type = type_list_push_front<typename extract<ERest...>::type, exp_multiply<Es, Num, Den>...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<Dimension Dim, int Num, int Den, Exponent... ERest>
|
|
||||||
struct extract<exp<Dim, Num, Den>, ERest...> {
|
|
||||||
using type = extract<exp<downcast_base_t<Dim>, Num, Den>, ERest...>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<Exponent... Es>
|
|
||||||
using make_dimension = dim_consolidate<type_list_sort<typename extract<Es...>::type, exp_less>>::type;
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// derived_dimension
|
|
||||||
template<typename Child, Exponent... Es>
|
|
||||||
struct derived_dimension : downcast_child<Child, typename detail::make_dimension<Es...>> {
|
|
||||||
using recipe = dimension<Es...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// merge_dimension
|
|
||||||
template<Dimension D1, Dimension D2>
|
|
||||||
using merge_dimension = detail::dim_consolidate<type_list_merge_sorted<D1, D2, exp_less>>::type;
|
|
||||||
|
|
||||||
// dimension_multiply
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename D1, typename D2>
|
|
||||||
struct dimension_multiply_impl;
|
|
||||||
|
|
||||||
template<typename... E1, typename... E2>
|
|
||||||
struct dimension_multiply_impl<dimension<E1...>, dimension<E2...>> : std::type_identity<downcast<merge_dimension<dimension<E1...>, dimension<E2...>>>> {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
|
||||||
using dimension_multiply = detail::dimension_multiply_impl<typename D1::base_type, typename D2::base_type>::type;
|
|
||||||
|
|
||||||
// dimension_divide
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename D1, typename D2>
|
|
||||||
struct dimension_divide_impl;
|
|
||||||
|
|
||||||
template<typename... E1, typename... E2>
|
|
||||||
struct dimension_divide_impl<dimension<E1...>, dimension<E2...>>
|
|
||||||
: dimension_multiply_impl<dimension<E1...>, dimension<exp_invert<E2>...>> {
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
|
||||||
using dimension_divide = detail::dimension_divide_impl<typename D1::base_type, typename D2::base_type>::type;
|
|
||||||
|
|
||||||
// dimension_sqrt
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename D>
|
|
||||||
struct dimension_sqrt_impl;
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
struct dimension_sqrt_impl<dimension<Es...>> : std::type_identity<downcast<dimension<exp_multiply<Es, 1, 2>...>>> {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D>
|
|
||||||
using dimension_sqrt = detail::dimension_sqrt_impl<typename D::base_type>::type;
|
|
||||||
|
|
||||||
// dimension_pow
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename D, std::size_t N>
|
|
||||||
struct dimension_pow_impl;
|
|
||||||
|
|
||||||
template<typename... Es, std::size_t N>
|
|
||||||
struct dimension_pow_impl<dimension<Es...>, N> : std::type_identity<downcast<dimension<exp_multiply<Es, N, 1>...>>> {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D, std::size_t N>
|
|
||||||
using dimension_pow = detail::dimension_pow_impl<typename D::base_type, N>::type;
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,64 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/length.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct area : derived_dimension<area, exp<length, 2>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Area = QuantityOf<T, area>;
|
|
||||||
|
|
||||||
struct square_metre : coherent_derived_unit<square_metre, area> {};
|
|
||||||
struct square_millimetre : deduced_derived_unit<square_millimetre, area, millimetre> {};
|
|
||||||
struct square_centimetre : deduced_derived_unit<square_centimetre, area, centimetre> {};
|
|
||||||
struct square_kilometre : deduced_derived_unit<square_kilometre, area, kilometre> {};
|
|
||||||
struct square_foot : deduced_derived_unit<square_foot, area, foot> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// sq_m
|
|
||||||
constexpr auto operator""sq_m(unsigned long long l) { return quantity<square_metre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""sq_m(long double l) { return quantity<square_metre, long double>(l); }
|
|
||||||
|
|
||||||
// sq_mm
|
|
||||||
constexpr auto operator""sq_mm(unsigned long long l) { return quantity<square_millimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""sq_mm(long double l) { return quantity<square_millimetre, long double>(l); }
|
|
||||||
|
|
||||||
// sq_cm
|
|
||||||
constexpr auto operator""sq_cm(unsigned long long l) { return quantity<square_centimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""sq_cm(long double l) { return quantity<square_centimetre, long double>(l); }
|
|
||||||
|
|
||||||
// sq_km
|
|
||||||
constexpr auto operator""sq_km(unsigned long long l) { return quantity<square_kilometre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""sq_km(long double l) { return quantity<square_kilometre, long double>(l); }
|
|
||||||
|
|
||||||
// sq_ft
|
|
||||||
constexpr auto operator""sq_ft(unsigned long long l) { return quantity<square_foot, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""sq_ft(long double l) { return quantity<square_foot, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,46 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/electric_charge.h>
|
|
||||||
#include <units/dimensions/voltage.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct capacitance : derived_dimension<capacitance, exp<electric_charge, 1>, exp<voltage, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Capacitance = QuantityOf<T, capacitance>;
|
|
||||||
|
|
||||||
struct farad : named_coherent_derived_unit<farad, capacitance, "F", si_prefix> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// F
|
|
||||||
constexpr auto operator""F(unsigned long long l) { return quantity<farad, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""_F(long double l) { return quantity<farad, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,46 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/time.h>
|
|
||||||
#include <units/dimensions/current.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct electric_charge : derived_dimension<electric_charge, exp<time, 1>, exp<current, 1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept ElectricCharge = QuantityOf<T, electric_charge>;
|
|
||||||
|
|
||||||
struct coulomb : named_coherent_derived_unit<coulomb, electric_charge, "C", si_prefix> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// C
|
|
||||||
constexpr auto operator""C(unsigned long long l) { return quantity<coulomb, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""C(long double l) { return quantity<coulomb, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,67 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/si_prefixes.h>
|
|
||||||
#include <units/dimensions/force.h>
|
|
||||||
#include <units/dimensions/pressure.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct energy : derived_dimension<energy, exp<force, 1>, exp<length, 1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Energy = QuantityOf<T, energy>;
|
|
||||||
|
|
||||||
struct joule : named_coherent_derived_unit<joule, energy, "J", si_prefix> {};
|
|
||||||
struct millijoule : prefixed_derived_unit<millijoule, milli, joule> {};
|
|
||||||
struct kilojoule : prefixed_derived_unit<kilojoule, kilo, joule> {};
|
|
||||||
struct megajoule : prefixed_derived_unit<megajoule, mega, joule> {};
|
|
||||||
struct gigajoule : prefixed_derived_unit<gigajoule, giga, joule> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// J
|
|
||||||
constexpr auto operator""_J(unsigned long long l) { return quantity<joule, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""_J(long double l) { return quantity<joule, long double>(l); }
|
|
||||||
|
|
||||||
// mJ
|
|
||||||
constexpr auto operator""mJ(unsigned long long l) { return quantity<millijoule, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mJ(long double l) { return quantity<millijoule, long double>(l); }
|
|
||||||
|
|
||||||
// kJ
|
|
||||||
constexpr auto operator""kJ(unsigned long long l) { return quantity<kilojoule, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""kJ(long double l) { return quantity<kilojoule, long double>(l); }
|
|
||||||
|
|
||||||
// MJ
|
|
||||||
constexpr auto operator""MJ(unsigned long long l) { return quantity<megajoule, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""MJ(long double l) { return quantity<megajoule, long double>(l); }
|
|
||||||
|
|
||||||
// GJ
|
|
||||||
constexpr auto operator""GJ(unsigned long long l) { return quantity<gigajoule, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""GJ(long double l) { return quantity<gigajoule, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,46 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/mass.h>
|
|
||||||
#include <units/dimensions/acceleration.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct force : derived_dimension<force, exp<mass, 1>, exp<acceleration, 1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Force = QuantityOf<T, force>;
|
|
||||||
|
|
||||||
struct newton : named_coherent_derived_unit<newton, force, "N", si_prefix> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// N
|
|
||||||
constexpr auto operator""N(unsigned long long l) { return quantity<newton, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""N(long double l) { return quantity<newton, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,71 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/si_prefixes.h>
|
|
||||||
#include <units/dimensions/time.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct frequency : derived_dimension<frequency, exp<time, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Frequency = QuantityOf<T, frequency>;
|
|
||||||
|
|
||||||
struct hertz : named_coherent_derived_unit<hertz, frequency, "Hz", si_prefix> {};
|
|
||||||
struct millihertz : prefixed_derived_unit<millihertz, milli, hertz> {};
|
|
||||||
struct kilohertz : prefixed_derived_unit<kilohertz, kilo, hertz> {};
|
|
||||||
struct megahertz : prefixed_derived_unit<megahertz, mega, hertz> {};
|
|
||||||
struct gigahertz : prefixed_derived_unit<gigahertz, giga, hertz> {};
|
|
||||||
struct terahertz : prefixed_derived_unit<terahertz, tera, hertz> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// Hz
|
|
||||||
constexpr auto operator""Hz(unsigned long long l) { return quantity<hertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""Hz(long double l) { return quantity<hertz, long double>(l); }
|
|
||||||
|
|
||||||
// mHz
|
|
||||||
constexpr auto operator""mHz(unsigned long long l) { return quantity<millihertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mHz(long double l) { return quantity<millihertz, long double>(l); }
|
|
||||||
|
|
||||||
// kHz
|
|
||||||
constexpr auto operator""kHz(unsigned long long l) { return quantity<kilohertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""kHz(long double l) { return quantity<kilohertz, long double>(l); }
|
|
||||||
|
|
||||||
// MHz
|
|
||||||
constexpr auto operator""MHz(unsigned long long l) { return quantity<megahertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""MHz(long double l) { return quantity<megahertz, long double>(l); }
|
|
||||||
|
|
||||||
// GHz
|
|
||||||
constexpr auto operator""GHz(unsigned long long l) { return quantity<gigahertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""GHz(long double l) { return quantity<gigahertz, long double>(l); }
|
|
||||||
|
|
||||||
// THz
|
|
||||||
constexpr auto operator""THz(unsigned long long l) { return quantity<terahertz, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""THz(long double l) { return quantity<terahertz, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,88 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/si_prefixes.h>
|
|
||||||
#include <units/quantity.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct length : derived_dimension<length, exp<base_dim_length, 1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Length = QuantityOf<T, length>;
|
|
||||||
|
|
||||||
// SI units
|
|
||||||
struct metre : named_coherent_derived_unit<metre, length, "m", si_prefix> {};
|
|
||||||
struct millimetre : prefixed_derived_unit<millimetre, milli, metre> {};
|
|
||||||
struct centimetre : prefixed_derived_unit<centimetre, centi, metre> {};
|
|
||||||
struct kilometre : prefixed_derived_unit<kilometre, kilo, metre> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// m
|
|
||||||
constexpr auto operator""m(unsigned long long l) { return quantity<metre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""m(long double l) { return quantity<metre, long double>(l); }
|
|
||||||
|
|
||||||
// mm
|
|
||||||
constexpr auto operator""mm(unsigned long long l) { return quantity<millimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mm(long double l) { return quantity<millimetre, long double>(l); }
|
|
||||||
|
|
||||||
// cm
|
|
||||||
constexpr auto operator""cm(unsigned long long l) { return quantity<centimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cm(long double l) { return quantity<centimetre, long double>(l); }
|
|
||||||
|
|
||||||
// km
|
|
||||||
constexpr auto operator""km(unsigned long long l) { return quantity<kilometre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""km(long double l) { return quantity<kilometre, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
// US customary units
|
|
||||||
struct yard : named_scaled_derived_unit<yard, length, "yd", ratio<9'144, 10'000>> {};
|
|
||||||
struct foot : named_scaled_derived_unit<foot, length, "ft", ratio_divide<yard::ratio, ratio<3>>> {};
|
|
||||||
struct inch : named_scaled_derived_unit<inch, length, "in", ratio_divide<foot::ratio, ratio<12>>> {};
|
|
||||||
struct mile : named_scaled_derived_unit<mile, length, "mi", ratio_multiply<ratio<1'760>, yard::ratio>> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// yd
|
|
||||||
constexpr auto operator""yd(unsigned long long l) { return quantity<yard, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""yd(long double l) { return quantity<yard, long double>(l); }
|
|
||||||
|
|
||||||
// ft
|
|
||||||
constexpr auto operator""ft(unsigned long long l) { return quantity<foot, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""ft(long double l) { return quantity<foot, long double>(l); }
|
|
||||||
|
|
||||||
// in
|
|
||||||
constexpr auto operator""in(unsigned long long l) { return quantity<inch, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""in(long double l) { return quantity<inch, long double>(l); }
|
|
||||||
|
|
||||||
// mi
|
|
||||||
constexpr auto operator""mi(unsigned long long l) { return quantity<mile, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mi(long double l) { return quantity<mile, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,66 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/si_prefixes.h>
|
|
||||||
#include <units/dimensions/energy.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct power : derived_dimension<power, exp<energy, 1>, exp<time, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Power = QuantityOf<T, power>;
|
|
||||||
|
|
||||||
struct watt : named_coherent_derived_unit<watt, power, "W", si_prefix> {};
|
|
||||||
struct milliwatt : prefixed_derived_unit<milliwatt, milli, watt> {};
|
|
||||||
struct kilowatt : prefixed_derived_unit<kilowatt, kilo, watt> {};
|
|
||||||
struct megawatt : prefixed_derived_unit<megawatt, mega, watt> {};
|
|
||||||
struct gigawatt : prefixed_derived_unit<gigawatt, giga, watt> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// W
|
|
||||||
constexpr auto operator""W(unsigned long long l) { return quantity<watt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""_W(long double l) { return quantity<watt, long double>(l); }
|
|
||||||
|
|
||||||
// mW
|
|
||||||
constexpr auto operator""mW(unsigned long long l) { return quantity<milliwatt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mW(long double l) { return quantity<milliwatt, long double>(l); }
|
|
||||||
|
|
||||||
// kW
|
|
||||||
constexpr auto operator""kW(unsigned long long l) { return quantity<kilowatt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""kW(long double l) { return quantity<kilowatt, long double>(l); }
|
|
||||||
|
|
||||||
// MW
|
|
||||||
constexpr auto operator""MW(unsigned long long l) { return quantity<megawatt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""MW(long double l) { return quantity<megawatt, long double>(l); }
|
|
||||||
|
|
||||||
// GW
|
|
||||||
constexpr auto operator""GW(unsigned long long l) { return quantity<gigawatt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""GW(long double l) { return quantity<gigawatt, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,46 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/force.h>
|
|
||||||
#include <units/dimensions/area.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct pressure : derived_dimension<pressure, exp<force, 1>, exp<area, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Pressure = QuantityOf<T, pressure>;
|
|
||||||
|
|
||||||
struct pascal : named_coherent_derived_unit<pascal, pressure, "Pa", si_prefix> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// Pa
|
|
||||||
constexpr auto operator""Pa(unsigned long long l) { return quantity<pascal, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""Pa(long double l) { return quantity<pascal, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,52 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/unit.h>
|
|
||||||
#include <units/format.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
// prefix tags
|
|
||||||
struct si_prefix : prefix_type {};
|
|
||||||
|
|
||||||
// SI prefixes
|
|
||||||
|
|
||||||
struct atto : prefix<atto, si_prefix, ratio<1, std::atto::den>, "a"> {};
|
|
||||||
struct femto : prefix<femto, si_prefix, ratio<1, std::femto::den>, "f"> {};
|
|
||||||
struct pico : prefix<pico, si_prefix, ratio<1, std::pico::den>, "p"> {};
|
|
||||||
struct nano : prefix<nano, si_prefix, ratio<1, std::nano::den>, "n"> {};
|
|
||||||
struct micro : prefix<micro, si_prefix, ratio<1, std::micro::den>, "\u00b5"> {};
|
|
||||||
struct milli : prefix<milli, si_prefix, ratio<1, std::milli::den>, "m"> {};
|
|
||||||
struct centi : prefix<centi, si_prefix, ratio<1, std::centi::den>, "c"> {};
|
|
||||||
struct deci : prefix<deci, si_prefix, ratio<1, std::deci::den>, "d"> {};
|
|
||||||
struct deca : prefix<deca, si_prefix, ratio<std::deca::num>, "da"> {};
|
|
||||||
struct hecto : prefix<hecto, si_prefix, ratio<std::hecto::num>, "h"> {};
|
|
||||||
struct kilo : prefix<kilo, si_prefix, ratio<std::kilo::num>, "k"> {};
|
|
||||||
struct mega : prefix<mega, si_prefix, ratio<std::mega::num>, "M"> {};
|
|
||||||
struct giga : prefix<giga, si_prefix, ratio<std::giga::num>, "G"> {};
|
|
||||||
struct tera : prefix<tera, si_prefix, ratio<std::tera::num>, "T"> {};
|
|
||||||
struct peta : prefix<peta, si_prefix, ratio<std::peta::num>, "P"> {};
|
|
||||||
struct exa : prefix<exa, si_prefix, ratio<std::exa::num>, "E"> {};
|
|
||||||
|
|
||||||
}
|
|
@@ -1,45 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/force.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct surface_tension : derived_dimension<surface_tension, exp<force, 1>, exp<length, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept SurfaceTension = QuantityOf<T, surface_tension>;
|
|
||||||
|
|
||||||
struct newton_per_metre : coherent_derived_unit<newton_per_metre, surface_tension> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// Nm
|
|
||||||
constexpr auto operator""Npm(unsigned long long l) { return quantity<newton_per_metre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""Npm(long double l) { return quantity<newton_per_metre, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,71 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/si_prefixes.h>
|
|
||||||
#include <units/quantity.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct time : derived_dimension<time, exp<base_dim_time, 1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Time = QuantityOf<T, time>;
|
|
||||||
|
|
||||||
struct second : named_coherent_derived_unit<second, time, "s", si_prefix> {};
|
|
||||||
struct nanosecond : prefixed_derived_unit<nanosecond, nano, second> {};
|
|
||||||
struct microsecond : prefixed_derived_unit<microsecond, micro, second> {};
|
|
||||||
struct millisecond : prefixed_derived_unit<millisecond, milli, second> {};
|
|
||||||
struct minute : named_scaled_derived_unit<minute, time, "min", ratio<60>> {};
|
|
||||||
struct hour : named_scaled_derived_unit<hour, time, "h", ratio<3600>> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// ns
|
|
||||||
constexpr auto operator""ns(unsigned long long l) { return quantity<nanosecond, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""ns(long double l) { return quantity<nanosecond, long double>(l); }
|
|
||||||
|
|
||||||
// us
|
|
||||||
constexpr auto operator""us(unsigned long long l) { return quantity<microsecond, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""us(long double l) { return quantity<microsecond, long double>(l); }
|
|
||||||
|
|
||||||
// ms
|
|
||||||
constexpr auto operator""ms(unsigned long long l) { return quantity<millisecond, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""ms(long double l) { return quantity<millisecond, long double>(l); }
|
|
||||||
|
|
||||||
// s
|
|
||||||
constexpr auto operator""s(unsigned long long l) { return quantity<second, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""s(long double l) { return quantity<second, long double>(l); }
|
|
||||||
|
|
||||||
// min
|
|
||||||
constexpr auto operator""min(unsigned long long l) { return quantity<minute, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""min(long double l) { return quantity<minute, long double>(l); }
|
|
||||||
|
|
||||||
// h
|
|
||||||
constexpr auto operator""h(unsigned long long l) { return quantity<hour, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""h(long double l) { return quantity<hour, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,55 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/length.h>
|
|
||||||
#include <units/dimensions/time.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct velocity : derived_dimension<velocity, exp<length, 1>, exp<time, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Velocity = QuantityOf<T, velocity>;
|
|
||||||
|
|
||||||
struct metre_per_second : coherent_derived_unit<metre_per_second, velocity> {};
|
|
||||||
struct kilometre_per_hour : deduced_derived_unit<kilometre_per_hour, velocity, kilometre, hour> {};
|
|
||||||
struct mile_per_hour : deduced_derived_unit<mile_per_hour, velocity, mile, hour> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// mps
|
|
||||||
constexpr auto operator""mps(unsigned long long l) { return quantity<metre_per_second, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mps(long double l) { return quantity<metre_per_second, long double>(l); }
|
|
||||||
|
|
||||||
// kmph
|
|
||||||
constexpr auto operator""kmph(unsigned long long l) { return quantity<kilometre_per_hour, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""kmph(long double l) { return quantity<kilometre_per_hour, long double>(l); }
|
|
||||||
|
|
||||||
// mph
|
|
||||||
constexpr auto operator""mph(unsigned long long l) { return quantity<mile_per_hour, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""mph(long double l) { return quantity<mile_per_hour, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,48 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
|
||||||
#include <units/dimensions/power.h>
|
|
||||||
#include <units/dimensions/current.h>
|
|
||||||
#include <units/dimensions/energy.h>
|
|
||||||
#include <units/dimensions/electric_charge.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct voltage : derived_dimension<voltage, exp<power, 1>, exp<current, -1>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Voltage = QuantityOf<T, voltage>;
|
|
||||||
|
|
||||||
struct volt : named_coherent_derived_unit<volt, voltage, "V", si_prefix> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// V
|
|
||||||
constexpr auto operator""V(unsigned long long l) { return quantity<volt, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""V(long double l) { return quantity<volt, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
@@ -1,64 +0,0 @@
|
|||||||
// The MIT License (MIT)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Mateusz Pusz
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <units/dimensions/length.h>
|
|
||||||
|
|
||||||
namespace units {
|
|
||||||
|
|
||||||
struct volume : derived_dimension<volume, exp<length, 3>> {};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Volume = QuantityOf<T, volume>;
|
|
||||||
|
|
||||||
struct cubic_metre : coherent_derived_unit<cubic_metre, volume> {};
|
|
||||||
struct cubic_millimetre : deduced_derived_unit<cubic_millimetre, volume, millimetre> {};
|
|
||||||
struct cubic_centimetre : deduced_derived_unit<cubic_centimetre, volume, centimetre> {};
|
|
||||||
struct cubic_kilometre : deduced_derived_unit<cubic_kilometre, volume, kilometre> {};
|
|
||||||
struct cubic_foot : deduced_derived_unit<cubic_foot, volume, foot> {};
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
// cub_mm
|
|
||||||
constexpr auto operator""cub_mm(unsigned long long l) { return quantity<cubic_millimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cub_mm(long double l) { return quantity<cubic_millimetre, long double>(l); }
|
|
||||||
|
|
||||||
// cub_cm
|
|
||||||
constexpr auto operator""cub_cm(unsigned long long l) { return quantity<cubic_centimetre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cub_cm(long double l) { return quantity<cubic_centimetre, long double>(l); }
|
|
||||||
|
|
||||||
// cub_m
|
|
||||||
constexpr auto operator""cub_m(unsigned long long l) { return quantity<cubic_metre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cub_m(long double l) { return quantity<cubic_metre, long double>(l); }
|
|
||||||
|
|
||||||
// cub_km
|
|
||||||
constexpr auto operator""cub_km(unsigned long long l) { return quantity<cubic_kilometre, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cub_km(long double l) { return quantity<cubic_kilometre, long double>(l); }
|
|
||||||
|
|
||||||
// cub_ft
|
|
||||||
constexpr auto operator""cub_ft(unsigned long long l) { return quantity<cubic_foot, std::int64_t>(l); }
|
|
||||||
constexpr auto operator""cub_ft(long double l) { return quantity<cubic_foot, long double>(l); }
|
|
||||||
|
|
||||||
} // namespace literals
|
|
||||||
|
|
||||||
} // namespace units
|
|
87
src/include/units/exp.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/base_dimension.h>
|
||||||
|
#include <units/ratio.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A power of factor corresponding to the dimension of a quantity
|
||||||
|
*
|
||||||
|
* @tparam Dim component dimension of a derived quantity
|
||||||
|
* @tparam Num numinator of the factor
|
||||||
|
* @tparam Den denominator of the factor
|
||||||
|
*/
|
||||||
|
template<Dimension Dim, int Num, int Den = 1>
|
||||||
|
struct exp {
|
||||||
|
using dimension = Dim;
|
||||||
|
static constexpr int num = Num;
|
||||||
|
static constexpr int den = Den;
|
||||||
|
};
|
||||||
|
|
||||||
|
// is_exp
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename Dim, int Num, int Den>
|
||||||
|
inline constexpr bool is_exp<exp<Dim, Num, Den>> = true;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// exp_less
|
||||||
|
template<Exponent E1, Exponent E2>
|
||||||
|
requires BaseDimension<typename E1::dimension> && BaseDimension<typename E2::dimension>
|
||||||
|
struct exp_less : base_dimension_less<typename E1::dimension, typename E2::dimension> {};
|
||||||
|
|
||||||
|
// exp_invert
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename Dim, int Num, int Den>
|
||||||
|
constexpr exp<Dim, -Num, Den> exp_invert_impl(exp<Dim, Num, Den>);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Exponent E>
|
||||||
|
using exp_invert = decltype(detail::exp_invert_impl(E()));
|
||||||
|
|
||||||
|
// exp_multiply
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<Exponent E, int Num, int Den>
|
||||||
|
struct exp_multiply_impl {
|
||||||
|
using r1 = ratio<E::num, E::den>;
|
||||||
|
using r2 = ratio<Num, Den>;
|
||||||
|
using r = ratio_multiply<r1, r2>;
|
||||||
|
using type = exp<typename E::dimension, r::num, r::den>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<Exponent E, int Num, int Den>
|
||||||
|
using exp_multiply = detail::exp_multiply_impl<E, Num, Den>::type;
|
||||||
|
|
||||||
|
template<Exponent... Es>
|
||||||
|
struct exp_list {};
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/customization_points.h>
|
#include <units/customization_points.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@@ -116,20 +116,20 @@ namespace units {
|
|||||||
return format_to(out, treat_as_floating_point<Rep> ? "{:" + sign_text + "g}" : "{:" + sign_text + "}", val);
|
return format_to(out, treat_as_floating_point<Rep> ? "{:" + sign_text + "g}" : "{:" + sign_text + "}", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Unit, typename OutputIt>
|
template<typename Dimension, typename Unit, typename OutputIt>
|
||||||
inline static OutputIt format_units_quantity_unit(OutputIt out)
|
inline static OutputIt format_units_quantity_unit(OutputIt out)
|
||||||
{
|
{
|
||||||
return format_to(out, "{}", unit_text<Unit>().c_str());
|
return format_to(out, "{}", unit_text<Dimension, Unit>().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutputIt, typename Unit, typename Rep>
|
template<typename OutputIt, typename Dimension, typename Unit, typename Rep>
|
||||||
struct units_formatter {
|
struct units_formatter {
|
||||||
OutputIt out;
|
OutputIt out;
|
||||||
Rep val;
|
Rep val;
|
||||||
fmt::sign_t sign;
|
fmt::sign_t sign;
|
||||||
int precision;
|
int precision;
|
||||||
|
|
||||||
explicit units_formatter(OutputIt o, quantity<Unit, Rep> q, fmt::sign_t s, int prec):
|
explicit units_formatter(OutputIt o, quantity<Dimension, Unit, Rep> q, fmt::sign_t s, int prec):
|
||||||
out(o), val(q.count()), sign(s), precision(prec)
|
out(o), val(q.count()), sign(s), precision(prec)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ namespace units {
|
|||||||
|
|
||||||
void on_quantity_unit()
|
void on_quantity_unit()
|
||||||
{
|
{
|
||||||
out = format_units_quantity_unit<Unit>(out);
|
out = format_units_quantity_unit<Dimension, Unit>(out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,11 +155,11 @@ namespace units {
|
|||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
|
||||||
template<typename Unit, typename Rep, typename CharT>
|
template<typename Dimension, typename Unit, typename Rep, typename CharT>
|
||||||
struct fmt::formatter<units::quantity<Unit, Rep>, CharT> {
|
struct fmt::formatter<units::quantity<Dimension, Unit, Rep>, CharT> {
|
||||||
private:
|
private:
|
||||||
using quantity = units::quantity<Unit, Rep>;
|
using quantity = units::quantity<Dimension, Unit, Rep>;
|
||||||
using iterator = fmt::basic_parse_context<CharT>::iterator;
|
using iterator = fmt::basic_format_parse_context<CharT>::iterator;
|
||||||
using arg_ref_type = fmt::internal::arg_ref<CharT>;
|
using arg_ref_type = fmt::internal::arg_ref<CharT>;
|
||||||
|
|
||||||
fmt::basic_format_specs<CharT> specs;
|
fmt::basic_format_specs<CharT> specs;
|
||||||
@@ -172,7 +172,7 @@ private:
|
|||||||
|
|
||||||
struct spec_handler {
|
struct spec_handler {
|
||||||
formatter& f;
|
formatter& f;
|
||||||
fmt::basic_parse_context<CharT>& context;
|
fmt::basic_format_parse_context<CharT>& context;
|
||||||
fmt::basic_string_view<CharT> format_str;
|
fmt::basic_string_view<CharT> format_str;
|
||||||
|
|
||||||
template<typename Id>
|
template<typename Id>
|
||||||
@@ -185,8 +185,7 @@ private:
|
|||||||
constexpr arg_ref_type make_arg_ref(fmt::basic_string_view<CharT> arg_id)
|
constexpr arg_ref_type make_arg_ref(fmt::basic_string_view<CharT> arg_id)
|
||||||
{
|
{
|
||||||
context.check_arg_id(arg_id);
|
context.check_arg_id(arg_id);
|
||||||
const auto str_val = fmt::internal::string_view_metadata(format_str, arg_id);
|
return arg_ref_type(arg_id);
|
||||||
return arg_ref_type(str_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr arg_ref_type make_arg_ref(fmt::internal::auto_id)
|
constexpr arg_ref_type make_arg_ref(fmt::internal::auto_id)
|
||||||
@@ -226,7 +225,7 @@ private:
|
|||||||
iterator end;
|
iterator end;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr parse_range do_parse(fmt::basic_parse_context<CharT>& ctx)
|
constexpr parse_range do_parse(fmt::basic_format_parse_context<CharT>& ctx)
|
||||||
{
|
{
|
||||||
auto begin = ctx.begin(), end = ctx.end();
|
auto begin = ctx.begin(), end = ctx.end();
|
||||||
if(begin == end || *begin == '}')
|
if(begin == end || *begin == '}')
|
||||||
@@ -285,7 +284,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr auto parse(fmt::basic_parse_context<CharT>& ctx)
|
constexpr auto parse(fmt::basic_format_parse_context<CharT>& ctx)
|
||||||
{
|
{
|
||||||
auto range = do_parse(ctx);
|
auto range = do_parse(ctx);
|
||||||
format_str = fmt::basic_string_view<CharT>(&*range.begin, fmt::internal::to_unsigned(range.end - range.begin));
|
format_str = fmt::basic_string_view<CharT>(&*range.begin, fmt::internal::to_unsigned(range.end - range.begin));
|
||||||
@@ -293,7 +292,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename FormatContext>
|
template<typename FormatContext>
|
||||||
auto format(const units::quantity<Unit, Rep>& q, FormatContext& ctx)
|
auto format(const units::quantity<Dimension, Unit, Rep>& q, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
auto begin = format_str.begin(), end = format_str.end();
|
auto begin = format_str.begin(), end = format_str.end();
|
||||||
|
|
||||||
@@ -302,15 +301,15 @@ public:
|
|||||||
auto out = std::back_inserter(buf);
|
auto out = std::back_inserter(buf);
|
||||||
|
|
||||||
// process dynamic width and precision
|
// process dynamic width and precision
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(specs.width, width_ref, ctx, format_str.begin());
|
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(specs.width, width_ref, ctx);
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(precision, precision_ref, ctx, format_str.begin());
|
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(precision, precision_ref, ctx);
|
||||||
|
|
||||||
// deal with quantity content
|
// deal with quantity content
|
||||||
if(begin == end || *begin == '}') {
|
if(begin == end || *begin == '}') {
|
||||||
// default format should print value followed by the unit separeted with 1 space
|
// default format should print value followed by the unit separeted with 1 space
|
||||||
out = units::detail::format_units_quantity_value(out, q.count(), specs.sign, precision);
|
out = units::detail::format_units_quantity_value(out, q.count(), specs.sign, precision);
|
||||||
*out++ = CharT(' ');
|
*out++ = CharT(' ');
|
||||||
units::detail::format_units_quantity_unit<Unit>(out);
|
units::detail::format_units_quantity_unit<Dimension, Unit>(out);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// user provided format
|
// user provided format
|
||||||
|
@@ -27,27 +27,29 @@
|
|||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
template<std::size_t N, typename U, typename Rep>
|
template<std::size_t N, typename D, typename U, typename Rep>
|
||||||
requires N == 0
|
requires (N == 0)
|
||||||
inline Rep AUTO pow(const quantity<U, Rep>&) noexcept
|
inline Rep pow(const quantity<D, U, Rep>&) noexcept
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t N, typename U, typename Rep>
|
template<std::size_t N, typename D, typename U, typename Rep>
|
||||||
inline Quantity AUTO pow(const quantity<U, Rep>& q) noexcept
|
inline Quantity AUTO pow(const quantity<D, U, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
using dim = dimension_pow<typename U::dimension, N>;
|
using dim = dimension_pow<D, N>;
|
||||||
using r = ratio_pow<typename U::ratio, N>;
|
using ratio = ratio_pow<typename U::ratio, N>;
|
||||||
return quantity<downcast<unit<dim, r>>, Rep>(static_cast<Rep>(std::pow(q.count(), N)));
|
using unit = downcast_unit<dim, ratio>;
|
||||||
|
return quantity<dim, unit, Rep>(static_cast<Rep>(std::pow(q.count(), N)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename Rep>
|
template<typename D, typename U, typename Rep>
|
||||||
inline Quantity AUTO sqrt(const quantity<U, Rep>& q) noexcept
|
inline Quantity AUTO sqrt(const quantity<D, U, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
using dim = dimension_sqrt<typename U::dimension>;
|
using dim = dimension_sqrt<D>;
|
||||||
using r = ratio_sqrt<typename U::ratio>;
|
using ratio = ratio_sqrt<typename U::ratio>;
|
||||||
return quantity<downcast<unit<dim, r>>, Rep>(static_cast<Rep>(std::sqrt(q.count())));
|
using unit = downcast_unit<dim, ratio>;
|
||||||
|
return quantity<dim, unit, Rep>(static_cast<Rep>(std::sqrt(q.count())));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
45
src/include/units/physical/cgs/acceleration.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/velocity.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct gal : named_unit<gal, "Gal", si::prefix> {};
|
||||||
|
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, gal, dim_length, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// Gal
|
||||||
|
constexpr auto operator""Gal(unsigned long long l) { return acceleration<gal, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Gal(long double l) { return acceleration<gal, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
47
src/include/units/physical/cgs/area.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/length.h>
|
||||||
|
#include <units/physical/si/area.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
using si::square_centimetre;
|
||||||
|
|
||||||
|
struct dim_area : physical::dim_area<dim_area, square_centimetre, dim_length> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using area = quantity<dim_area, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// sq_cm
|
||||||
|
constexpr auto operator"" sq_cm(unsigned long long l) { return area<square_centimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_cm(long double l) { return area<square_centimetre, long double>(l); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
47
src/include/units/physical/cgs/energy.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/force.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct erg : named_unit<erg, "erg", si::prefix> {};
|
||||||
|
|
||||||
|
struct dim_energy : physical::dim_energy<dim_energy, erg, dim_force, dim_length> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using energy = quantity<dim_energy, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// erg
|
||||||
|
constexpr auto operator""_erg(unsigned long long l) { return energy<erg, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_erg(long double l) { return energy<erg, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
48
src/include/units/physical/cgs/force.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/acceleration.h>
|
||||||
|
#include <units/physical/cgs/mass.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct dyne : named_unit<dyne, "dyn", si::prefix> {};
|
||||||
|
|
||||||
|
struct dim_force : physical::dim_force<dim_force, dyne, dim_mass, dim_acceleration> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using force = quantity<dim_force, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// dyn
|
||||||
|
constexpr auto operator""dyn(unsigned long long l) { return force<dyne, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""dyn(long double l) { return force<dyne, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
@@ -22,24 +22,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/length.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::cgs {
|
||||||
|
|
||||||
struct current : derived_dimension<current, exp<base_dim_current, 1>> {};
|
using si::centimetre;
|
||||||
|
|
||||||
template<typename T>
|
struct dim_length : physical::dim_length<centimetre> {};
|
||||||
concept Current = QuantityOf<T, current>;
|
|
||||||
|
|
||||||
struct ampere : named_coherent_derived_unit<ampere, current, "A", si_prefix> {};
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
// A
|
// cm
|
||||||
constexpr auto operator""A(unsigned long long l) { return quantity<ampere, std::int64_t>(l); }
|
constexpr auto operator"" cm(unsigned long long l) { return length<centimetre, std::int64_t>(l); }
|
||||||
constexpr auto operator""A(long double l) { return quantity<ampere, long double>(l); }
|
constexpr auto operator"" cm(long double l) { return length<centimetre, long double>(l); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units::cgs
|
@@ -22,16 +22,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimension.h>
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/mass.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::cgs {
|
||||||
|
|
||||||
struct base_dim_length : base_dimension<"length", "m"> {};
|
using si::gram;
|
||||||
struct base_dim_mass : base_dimension<"mass", "kg"> {};
|
|
||||||
struct base_dim_time : base_dimension<"time", "s"> {};
|
|
||||||
struct base_dim_current : base_dimension<"current", "A"> {};
|
|
||||||
struct base_dim_temperature : base_dimension<"temperature", "K"> {};
|
|
||||||
struct base_dim_substance : base_dimension<"substance", "mol"> {};
|
|
||||||
struct base_dim_luminous_intensity : base_dimension<"luminous intensity", "cd"> {};
|
|
||||||
|
|
||||||
} // namespace units
|
struct dim_mass : physical::dim_mass<gram> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using mass = quantity<dim_mass, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// g
|
||||||
|
constexpr auto operator""g(unsigned long long l) { return mass<gram, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""g(long double l) { return mass<gram, long double>(l); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
47
src/include/units/physical/cgs/power.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/energy.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct erg_per_second : unit<erg_per_second> {};
|
||||||
|
|
||||||
|
struct dim_power : physical::dim_power<dim_power, erg_per_second, dim_energy, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using power = quantity<dim_power, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// ergps
|
||||||
|
constexpr auto operator""_ergps(unsigned long long l) { return power<erg_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_ergps(long double l) { return power<erg_per_second, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
48
src/include/units/physical/cgs/pressure.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/area.h>
|
||||||
|
#include <units/physical/cgs/force.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct barye : named_unit<barye, "Ba", si::prefix> {};
|
||||||
|
|
||||||
|
struct dim_pressure : physical::dim_pressure<dim_pressure, barye, dim_force, dim_area> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using pressure = quantity<dim_pressure, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// Ba
|
||||||
|
constexpr auto operator""Ba(unsigned long long l) { return pressure<barye, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Ba(long double l) { return pressure<barye, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
@@ -22,27 +22,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::cgs {
|
||||||
|
|
||||||
namespace detail {
|
using si::second;
|
||||||
|
|
||||||
template<bool>
|
using si::dim_time;
|
||||||
struct conditional_impl {
|
using si::time;
|
||||||
template<typename T, typename F>
|
|
||||||
using type = F;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
inline namespace literals {
|
||||||
struct conditional_impl<true> {
|
|
||||||
template<typename T, typename F>
|
|
||||||
using type = T;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
using si::literals::operator"" s;
|
||||||
|
|
||||||
template<bool B, typename T, typename F>
|
|
||||||
using conditional = detail::conditional_impl<B>::template type<T, F>;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
46
src/include/units/physical/cgs/velocity.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/cgs/length.h>
|
||||||
|
#include <units/physical/cgs/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::cgs {
|
||||||
|
|
||||||
|
struct centimetre_per_second : unit<centimetre_per_second> {};
|
||||||
|
struct dim_velocity : physical::dim_velocity<dim_velocity, centimetre_per_second, dim_length, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using velocity = quantity<dim_velocity, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// cmps
|
||||||
|
constexpr auto operator"" cmps(unsigned long long l) { return velocity<centimetre_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" cmps(long double l) { return velocity<centimetre_per_second, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::cgs
|
166
src/include/units/physical/dimensions.h
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/base_dimension.h>
|
||||||
|
#include <units/bits/external/type_traits.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
#include <units/unit.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
namespace physical {
|
||||||
|
|
||||||
|
template<typename Dim, template<typename...> typename DimTemplate>
|
||||||
|
concept DimensionOf = (Dimension<Dim> || BaseDimension<Dim>) && is_derived_from_instantiation<Dim, DimTemplate>;
|
||||||
|
|
||||||
|
template<typename Q, template<typename...> typename DimTemplate>
|
||||||
|
concept QuantityOf = Quantity<Q> && is_derived_from_instantiation<typename Q::dimension, DimTemplate>;
|
||||||
|
|
||||||
|
// ------------------------ base dimensions -----------------------------
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_length : base_dimension<"L", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_mass : base_dimension<"M", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_time : base_dimension<"T", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_electric_current : base_dimension<"I", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_thermodynamic_temperature : base_dimension<"Θ", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_substance : base_dimension<"N", U> {};
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
struct dim_luminous_intensity : base_dimension<"J", U> {};
|
||||||
|
|
||||||
|
// ------------------------ derived dimensions -----------------------------
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_time> T>
|
||||||
|
struct dim_frequency : derived_dimension<Child, U, exp<T, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_length> L>
|
||||||
|
struct dim_area : derived_dimension<Child, U, exp<L, 2>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_length> L>
|
||||||
|
struct dim_volume : derived_dimension<Child, U, exp<L, 3>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_length> L, DimensionOf<dim_time> T>
|
||||||
|
struct dim_velocity : derived_dimension<Child, U, exp<L, 1>, exp<T, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_length> L, DimensionOf<dim_time> T>
|
||||||
|
struct dim_acceleration : derived_dimension<Child, U, exp<L, 1>, exp<T, -2>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_mass> M, DimensionOf<dim_acceleration> A>
|
||||||
|
struct dim_force : derived_dimension<Child, U, exp<M, 1>, exp<A, 1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_length> L>
|
||||||
|
struct dim_energy : derived_dimension<Child, U, exp<F, 1>, exp<L, 1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_energy> E, DimensionOf<dim_time> T>
|
||||||
|
struct dim_power : derived_dimension<Child, U, exp<E, 1>, exp<T, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_power> P, DimensionOf<dim_electric_current> C>
|
||||||
|
struct dim_voltage : derived_dimension<Child, U, exp<P, 1>, exp<C, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_time> T, DimensionOf<dim_electric_current> C>
|
||||||
|
struct dim_electric_charge : derived_dimension<Child, U, exp<T, 1>, exp<C, 1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_electric_charge> C, DimensionOf<dim_voltage> V>
|
||||||
|
struct dim_capacitance : derived_dimension<Child, U, exp<C, 1>, exp<V, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_length> L>
|
||||||
|
struct dim_surface_tension : derived_dimension<Child, U, exp<F, 1>, exp<L, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_area> A>
|
||||||
|
struct dim_pressure : derived_dimension<Child, U, exp<F, 1>, exp<A, -1>> {};
|
||||||
|
|
||||||
|
} // namespace physical
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Length = physical::QuantityOf<T, physical::dim_length>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Mass = physical::QuantityOf<T, physical::dim_mass>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Time = physical::QuantityOf<T, physical::dim_time>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Current = physical::QuantityOf<T, physical::dim_electric_current>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Temperature = physical::QuantityOf<T, physical::dim_thermodynamic_temperature>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Substance = physical::QuantityOf<T, physical::dim_substance>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept LuminousIntensity = physical::QuantityOf<T, physical::dim_luminous_intensity>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Frequency = physical::QuantityOf<T, physical::dim_frequency>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Area = physical::QuantityOf<T, physical::dim_area>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Volume = physical::QuantityOf<T, physical::dim_volume>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Velocity = physical::QuantityOf<T, physical::dim_velocity>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Acceleration = physical::QuantityOf<T, physical::dim_acceleration>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Force = physical::QuantityOf<T, physical::dim_force>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Energy = physical::QuantityOf<T, physical::dim_energy>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Power = physical::QuantityOf<T, physical::dim_power>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Voltage = physical::QuantityOf<T, physical::dim_voltage>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept ElectricCharge = physical::QuantityOf<T, physical::dim_electric_charge>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Capacitance = physical::QuantityOf<T, physical::dim_capacitance>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept SurfaceTension = physical::QuantityOf<T, physical::dim_surface_tension>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Pressure = physical::QuantityOf<T, physical::dim_pressure>;
|
||||||
|
|
||||||
|
} // namespace units
|
45
src/include/units/physical/si/acceleration.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/velocity.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct metre_per_second_sq : unit<metre_per_second_sq> {};
|
||||||
|
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, metre_per_second_sq, dim_length, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// mps_sq
|
||||||
|
constexpr auto operator""mps_sq(unsigned long long l) { return acceleration<metre_per_second_sq, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""mps_sq(long double l) { return acceleration<metre_per_second_sq, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
66
src/include/units/physical/si/area.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/length.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct square_metre : unit<square_metre> {};
|
||||||
|
struct dim_area : physical::dim_area<dim_area, square_metre, dim_length> {};
|
||||||
|
|
||||||
|
struct square_millimetre : deduced_unit<square_millimetre, dim_area, millimetre> {};
|
||||||
|
struct square_centimetre : deduced_unit<square_centimetre, dim_area, centimetre> {};
|
||||||
|
struct square_kilometre : deduced_unit<square_kilometre, dim_area, kilometre> {};
|
||||||
|
struct square_foot : deduced_unit<square_foot, dim_area, foot> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using area = quantity<dim_area, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// sq_m
|
||||||
|
constexpr auto operator"" sq_m(unsigned long long l) { return area<square_metre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_m(long double l) { return area<square_metre, long double>(l); }
|
||||||
|
|
||||||
|
// sq_mm
|
||||||
|
constexpr auto operator"" sq_mm(unsigned long long l) { return area<square_millimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_mm(long double l) { return area<square_millimetre, long double>(l); }
|
||||||
|
|
||||||
|
// sq_cm
|
||||||
|
constexpr auto operator"" sq_cm(unsigned long long l) { return area<square_centimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_cm(long double l) { return area<square_centimetre, long double>(l); }
|
||||||
|
|
||||||
|
// sq_km
|
||||||
|
constexpr auto operator"" sq_km(unsigned long long l) { return area<square_kilometre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_km(long double l) { return area<square_kilometre, long double>(l); }
|
||||||
|
|
||||||
|
// sq_ft
|
||||||
|
constexpr auto operator"" sq_ft(unsigned long long l) { return area<square_foot, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" sq_ft(long double l) { return area<square_foot, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
48
src/include/units/physical/si/capacitance.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/electric_charge.h>
|
||||||
|
#include <units/physical/si/voltage.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct farad : named_unit<farad, "F", prefix> {};
|
||||||
|
|
||||||
|
struct dim_capacitance : physical::dim_capacitance<dim_capacitance, farad, dim_electric_charge, dim_voltage> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using capacitance = quantity<dim_capacitance, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// F
|
||||||
|
constexpr auto operator""F(unsigned long long l) { return capacitance<farad, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_F(long double l) { return capacitance<farad, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
46
src/include/units/physical/si/current.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct ampere : named_unit<ampere, "m", prefix> {};
|
||||||
|
|
||||||
|
struct dim_electric_current : physical::dim_electric_current<ampere> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using current = quantity<dim_electric_current, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// A
|
||||||
|
constexpr auto operator""A(unsigned long long l) { return current<ampere, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""A(long double l) { return current<ampere, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
47
src/include/units/physical/si/electric_charge.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/current.h>
|
||||||
|
#include <units/physical/si/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct coulomb : named_unit<coulomb, "C", prefix> {};
|
||||||
|
|
||||||
|
struct dim_electric_charge : physical::dim_electric_charge<dim_electric_charge, coulomb, dim_time, dim_electric_current> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using electric_charge = quantity<dim_electric_charge, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// C
|
||||||
|
constexpr auto operator""C(unsigned long long l) { return electric_charge<coulomb, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""C(long double l) { return electric_charge<coulomb, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
67
src/include/units/physical/si/energy.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/force.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct joule : named_unit<joule, "J", prefix> {};
|
||||||
|
struct millijoule : prefixed_unit<millijoule, milli, joule> {};
|
||||||
|
struct kilojoule : prefixed_unit<kilojoule, kilo, joule> {};
|
||||||
|
struct megajoule : prefixed_unit<megajoule, mega, joule> {};
|
||||||
|
struct gigajoule : prefixed_unit<gigajoule, giga, joule> {};
|
||||||
|
|
||||||
|
struct dim_energy : physical::dim_energy<dim_energy, joule, dim_force, dim_length> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using energy = quantity<dim_energy, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// J
|
||||||
|
constexpr auto operator""_J(unsigned long long l) { return energy<joule, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_J(long double l) { return energy<joule, long double>(l); }
|
||||||
|
|
||||||
|
// mJ
|
||||||
|
constexpr auto operator""mJ(unsigned long long l) { return energy<millijoule, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""mJ(long double l) { return energy<millijoule, long double>(l); }
|
||||||
|
|
||||||
|
// kJ
|
||||||
|
constexpr auto operator""kJ(unsigned long long l) { return energy<kilojoule, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""kJ(long double l) { return energy<kilojoule, long double>(l); }
|
||||||
|
|
||||||
|
// MJ
|
||||||
|
constexpr auto operator""MJ(unsigned long long l) { return energy<megajoule, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""MJ(long double l) { return energy<megajoule, long double>(l); }
|
||||||
|
|
||||||
|
// GJ
|
||||||
|
constexpr auto operator""GJ(unsigned long long l) { return energy<gigajoule, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""GJ(long double l) { return energy<gigajoule, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
48
src/include/units/physical/si/force.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/acceleration.h>
|
||||||
|
#include <units/physical/si/mass.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct newton : named_unit<newton, "N", prefix> {};
|
||||||
|
|
||||||
|
struct dim_force : physical::dim_force<dim_force, newton, dim_mass, dim_acceleration> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using force = quantity<dim_force, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// N
|
||||||
|
constexpr auto operator""N(unsigned long long l) { return force<newton, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""N(long double l) { return force<newton, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
71
src/include/units/physical/si/frequency.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct hertz : named_unit<hertz, "Hz", prefix> {};
|
||||||
|
struct millihertz : prefixed_unit<millihertz, milli, hertz> {};
|
||||||
|
struct kilohertz : prefixed_unit<kilohertz, kilo, hertz> {};
|
||||||
|
struct megahertz : prefixed_unit<megahertz, mega, hertz> {};
|
||||||
|
struct gigahertz : prefixed_unit<gigahertz, giga, hertz> {};
|
||||||
|
struct terahertz : prefixed_unit<terahertz, tera, hertz> {};
|
||||||
|
|
||||||
|
struct dim_frequency : physical::dim_frequency<dim_frequency, hertz, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using frequency = quantity<dim_frequency, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// Hz
|
||||||
|
constexpr auto operator"" Hz(unsigned long long l) { return frequency<hertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" Hz(long double l) { return frequency<hertz, long double>(l); }
|
||||||
|
|
||||||
|
// mHz
|
||||||
|
constexpr auto operator"" mHz(unsigned long long l) { return frequency<millihertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" mHz(long double l) { return frequency<millihertz, long double>(l); }
|
||||||
|
|
||||||
|
// kHz
|
||||||
|
constexpr auto operator"" kHz(unsigned long long l) { return frequency<kilohertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" kHz(long double l) { return frequency<kilohertz, long double>(l); }
|
||||||
|
|
||||||
|
// MHz
|
||||||
|
constexpr auto operator"" MHz(unsigned long long l) { return frequency<megahertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" MHz(long double l) { return frequency<megahertz, long double>(l); }
|
||||||
|
|
||||||
|
// GHz
|
||||||
|
constexpr auto operator"" GHz(unsigned long long l) { return frequency<gigahertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" GHz(long double l) { return frequency<gigahertz, long double>(l); }
|
||||||
|
|
||||||
|
// THz
|
||||||
|
constexpr auto operator"" THz(unsigned long long l) { return frequency<terahertz, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" THz(long double l) { return frequency<terahertz, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
87
src/include/units/physical/si/length.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct metre : named_unit<metre, "m", prefix> {};
|
||||||
|
struct millimetre : prefixed_unit<millimetre, milli, metre> {};
|
||||||
|
struct centimetre : prefixed_unit<centimetre, centi, metre> {};
|
||||||
|
struct kilometre : prefixed_unit<kilometre, kilo, metre> {};
|
||||||
|
|
||||||
|
struct dim_length : physical::dim_length<metre> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// m
|
||||||
|
constexpr auto operator"" m(unsigned long long l) { return length<metre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" m(long double l) { return length<metre, long double>(l); }
|
||||||
|
|
||||||
|
// mm
|
||||||
|
constexpr auto operator"" mm(unsigned long long l) { return length<millimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" mm(long double l) { return length<millimetre, long double>(l); }
|
||||||
|
|
||||||
|
// cm
|
||||||
|
constexpr auto operator"" cm(unsigned long long l) { return length<centimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" cm(long double l) { return length<centimetre, long double>(l); }
|
||||||
|
|
||||||
|
// km
|
||||||
|
constexpr auto operator"" km(unsigned long long l) { return length<kilometre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" km(long double l) { return length<kilometre, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
// US customary units
|
||||||
|
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio<9'144, 10'000>, metre> {};
|
||||||
|
struct foot : named_scaled_unit<foot, "ft", no_prefix, ratio<1, 3>, yard> {};
|
||||||
|
struct inch : named_scaled_unit<inch, "in", no_prefix, ratio<1, 12>, foot> {};
|
||||||
|
struct mile : named_scaled_unit<mile, "mi", no_prefix, ratio<1'760>, yard> {};
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// yd
|
||||||
|
constexpr auto operator"" yd(unsigned long long l) { return length<yard, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" yd(long double l) { return length<yard, long double>(l); }
|
||||||
|
|
||||||
|
// ft
|
||||||
|
constexpr auto operator"" ft(unsigned long long l) { return length<foot, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" ft(long double l) { return length<foot, long double>(l); }
|
||||||
|
|
||||||
|
// in
|
||||||
|
constexpr auto operator"" in(unsigned long long l) { return length<inch, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" in(long double l) { return length<inch, long double>(l); }
|
||||||
|
|
||||||
|
// mi
|
||||||
|
constexpr auto operator"" mi(unsigned long long l) { return length<mile, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" mi(long double l) { return length<mile, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
@@ -22,24 +22,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::si {
|
||||||
|
|
||||||
struct luminous_intensity : derived_dimension<luminous_intensity, exp<base_dim_luminous_intensity, 1>> {};
|
struct candela : named_unit<candela, "cd", prefix> {};
|
||||||
|
|
||||||
template<typename T>
|
struct dim_luminous_intensity : physical::dim_luminous_intensity<candela> {};
|
||||||
concept LuminousIntensity = QuantityOf<T, luminous_intensity>;
|
|
||||||
|
|
||||||
struct candela : named_coherent_derived_unit<candela, luminous_intensity, "cd", si_prefix> {};
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using luminous_intensity = quantity<dim_luminous_intensity, U, Rep>;
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
// cd
|
// cd
|
||||||
constexpr auto operator""cd(unsigned long long l) { return quantity<candela, std::int64_t>(l); }
|
constexpr auto operator""cd(unsigned long long l) { return luminous_intensity<candela, std::int64_t>(l); }
|
||||||
constexpr auto operator""cd(long double l) { return quantity<candela, long double>(l); }
|
constexpr auto operator""cd(long double l) { return luminous_intensity<candela, long double>(l); }
|
||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units::si
|
51
src/include/units/physical/si/mass.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct gram : named_unit<gram, "g", prefix> {};
|
||||||
|
struct kilogram : prefixed_unit<kilogram, kilo, gram> {};
|
||||||
|
|
||||||
|
struct dim_mass : physical::dim_mass<kilogram> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using mass = quantity<dim_mass, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// g
|
||||||
|
constexpr auto operator""g(unsigned long long l) { return mass<gram, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""g(long double l) { return mass<gram, long double>(l); }
|
||||||
|
|
||||||
|
// kg
|
||||||
|
constexpr auto operator""kg(unsigned long long l) { return mass<kilogram, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""kg(long double l) { return mass<kilogram, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
67
src/include/units/physical/si/power.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/energy.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct watt : named_unit<watt, "W", prefix> {};
|
||||||
|
struct milliwatt : prefixed_unit<milliwatt, milli, watt> {};
|
||||||
|
struct kilowatt : prefixed_unit<kilowatt, kilo, watt> {};
|
||||||
|
struct megawatt : prefixed_unit<megawatt, mega, watt> {};
|
||||||
|
struct gigawatt : prefixed_unit<gigawatt, giga, watt> {};
|
||||||
|
|
||||||
|
struct dim_power : physical::dim_power<dim_power, watt, dim_energy, dim_time> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using power = quantity<dim_power, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// W
|
||||||
|
constexpr auto operator""W(unsigned long long l) { return power<watt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""_W(long double l) { return power<watt, long double>(l); }
|
||||||
|
|
||||||
|
// mW
|
||||||
|
constexpr auto operator""mW(unsigned long long l) { return power<milliwatt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""mW(long double l) { return power<milliwatt, long double>(l); }
|
||||||
|
|
||||||
|
// kW
|
||||||
|
constexpr auto operator""kW(unsigned long long l) { return power<kilowatt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""kW(long double l) { return power<kilowatt, long double>(l); }
|
||||||
|
|
||||||
|
// MW
|
||||||
|
constexpr auto operator""MW(unsigned long long l) { return power<megawatt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""MW(long double l) { return power<megawatt, long double>(l); }
|
||||||
|
|
||||||
|
// GW
|
||||||
|
constexpr auto operator""GW(unsigned long long l) { return power<gigawatt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""GW(long double l) { return power<gigawatt, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
51
src/include/units/physical/si/prefixes.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/prefix.h>
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct prefix : prefix_type {};
|
||||||
|
|
||||||
|
// TODO Remove dependency on std::ratio
|
||||||
|
|
||||||
|
struct atto : units::prefix<atto, prefix, "a", ratio<1, std::atto::den>> {};
|
||||||
|
struct femto : units::prefix<femto, prefix, "f", ratio<1, std::femto::den>> {};
|
||||||
|
struct pico : units::prefix<pico, prefix, "p", ratio<1, std::pico::den>> {};
|
||||||
|
struct nano : units::prefix<nano, prefix, "n", ratio<1, std::nano::den>> {};
|
||||||
|
struct micro : units::prefix<micro, prefix, "\u00b5", ratio<1, std::micro::den>> {};
|
||||||
|
struct milli : units::prefix<milli, prefix, "m", ratio<1, std::milli::den>> {};
|
||||||
|
struct centi : units::prefix<centi, prefix, "c", ratio<1, std::centi::den>> {};
|
||||||
|
struct deci : units::prefix<deci, prefix, "d", ratio<1, std::deci::den>> {};
|
||||||
|
struct deca : units::prefix<deca, prefix, "da", ratio<std::deca::num>> {};
|
||||||
|
struct hecto : units::prefix<hecto, prefix, "h", ratio<std::hecto::num>> {};
|
||||||
|
struct kilo : units::prefix<kilo, prefix, "k", ratio<std::kilo::num>> {};
|
||||||
|
struct mega : units::prefix<mega, prefix, "M", ratio<std::mega::num>> {};
|
||||||
|
struct giga : units::prefix<giga, prefix, "G", ratio<std::giga::num>> {};
|
||||||
|
struct tera : units::prefix<tera, prefix, "T", ratio<std::tera::num>> {};
|
||||||
|
struct peta : units::prefix<peta, prefix, "P", ratio<std::peta::num>> {};
|
||||||
|
struct exa : units::prefix<exa, prefix, "E", ratio<std::exa::num>> {};
|
||||||
|
|
||||||
|
} // namespace units::si
|
48
src/include/units/physical/si/pressure.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/area.h>
|
||||||
|
#include <units/physical/si/force.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct pascal : named_unit<pascal, "Pa", prefix> {};
|
||||||
|
|
||||||
|
struct dim_pressure : physical::dim_pressure<dim_pressure, pascal, dim_force, dim_area> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using pressure = quantity<dim_pressure, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// Pa
|
||||||
|
constexpr auto operator""Pa(unsigned long long l) { return pressure<pascal, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Pa(long double l) { return pressure<pascal, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
@@ -22,24 +22,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::si {
|
||||||
|
|
||||||
struct substance : derived_dimension<substance, exp<base_dim_substance, 1>> {};
|
struct mole : named_unit<metre, "mol", prefix> {};
|
||||||
|
|
||||||
template<typename T>
|
struct dim_substance : physical::dim_substance<mole> {};
|
||||||
concept Substance = QuantityOf<T, substance>;
|
|
||||||
|
|
||||||
struct mole : named_coherent_derived_unit<mole, substance, "mol", si_prefix> {};
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using substance = quantity<dim_substance, U, Rep>;
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
// mol
|
// mol
|
||||||
constexpr auto operator""mol(unsigned long long l) { return quantity<mole, std::int64_t>(l); }
|
constexpr auto operator"" mol(unsigned long long l) { return substance<mole, std::int64_t>(l); }
|
||||||
constexpr auto operator""mol(long double l) { return quantity<mole, long double>(l); }
|
constexpr auto operator"" mol(long double l) { return substance<mole, long double>(l); }
|
||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units::si
|
46
src/include/units/physical/si/surface_tension.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/force.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct newton_per_metre : unit<newton_per_metre> {};
|
||||||
|
|
||||||
|
struct dim_surface_tension : physical::dim_surface_tension<dim_surface_tension, newton_per_metre, dim_force, dim_length> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using surface_tension = quantity<dim_surface_tension, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// Nm
|
||||||
|
constexpr auto operator""Npm(unsigned long long l) { return surface_tension<newton_per_metre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""Npm(long double l) { return surface_tension<newton_per_metre, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
@@ -22,24 +22,24 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/si_base_dimensions.h>
|
#include <units/physical/dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units::si {
|
||||||
|
|
||||||
struct temperature : derived_dimension<temperature, exp<base_dim_temperature, 1>> {};
|
struct kelvin : named_unit<kelvin, "K", no_prefix> {};
|
||||||
|
|
||||||
template<typename T>
|
struct dim_thermodynamic_temperature : physical::dim_thermodynamic_temperature<kelvin> {};
|
||||||
concept ThermodynamicTemperature = QuantityOf<T, temperature>;
|
|
||||||
|
|
||||||
struct kelvin : named_coherent_derived_unit<kelvin, temperature, "K", no_prefix> {};
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using temperature = quantity<dim_thermodynamic_temperature, U, Rep>;
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
// K
|
// K
|
||||||
constexpr auto operator""K(unsigned long long l) { return quantity<kelvin, std::int64_t>(l); }
|
constexpr auto operator""K(unsigned long long l) { return temperature<kelvin, std::int64_t>(l); }
|
||||||
constexpr auto operator""_K(long double l) { return quantity<kelvin, long double>(l); } // TODO: conflicts with gcc GNU extension
|
constexpr auto operator""_K(long double l) { return temperature<kelvin, long double>(l); } // TODO: conflicts with gcc GNU extension
|
||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units::si
|
71
src/include/units/physical/si/time.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct second : named_unit<second, "s", prefix> {};
|
||||||
|
struct nanosecond : prefixed_unit<nanosecond, nano, second> {};
|
||||||
|
struct microsecond : prefixed_unit<microsecond, micro, second> {};
|
||||||
|
struct millisecond : prefixed_unit<millisecond, milli, second> {};
|
||||||
|
struct minute : named_scaled_unit<minute, "min", no_prefix, ratio<60>, second> {};
|
||||||
|
struct hour : named_scaled_unit<hour, "h", no_prefix, ratio<3600>, second> {};
|
||||||
|
|
||||||
|
struct dim_time : physical::dim_time<second> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using time = quantity<dim_time, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// ns
|
||||||
|
constexpr auto operator""ns(unsigned long long l) { return time<nanosecond, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""ns(long double l) { return time<nanosecond, long double>(l); }
|
||||||
|
|
||||||
|
// us
|
||||||
|
constexpr auto operator""us(unsigned long long l) { return time<microsecond, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""us(long double l) { return time<microsecond, long double>(l); }
|
||||||
|
|
||||||
|
// ms
|
||||||
|
constexpr auto operator""ms(unsigned long long l) { return time<millisecond, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""ms(long double l) { return time<millisecond, long double>(l); }
|
||||||
|
|
||||||
|
// s
|
||||||
|
constexpr auto operator""s(unsigned long long l) { return time<second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""s(long double l) { return time<second, long double>(l); }
|
||||||
|
|
||||||
|
// min
|
||||||
|
constexpr auto operator""min(unsigned long long l) { return time<minute, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""min(long double l) { return time<minute, long double>(l); }
|
||||||
|
|
||||||
|
// h
|
||||||
|
constexpr auto operator""h(unsigned long long l) { return time<hour, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""h(long double l) { return time<hour, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
57
src/include/units/physical/si/velocity.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/length.h>
|
||||||
|
#include <units/physical/si/time.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct metre_per_second : unit<metre_per_second> {};
|
||||||
|
struct dim_velocity : physical::dim_velocity<dim_velocity, metre_per_second, dim_length, dim_time> {};
|
||||||
|
|
||||||
|
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_velocity, kilometre, hour> {};
|
||||||
|
struct mile_per_hour : deduced_unit<mile_per_hour, dim_velocity, mile, hour> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using velocity = quantity<dim_velocity, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// mps
|
||||||
|
constexpr auto operator"" mps(unsigned long long l) { return velocity<metre_per_second, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" mps(long double l) { return velocity<metre_per_second, long double>(l); }
|
||||||
|
|
||||||
|
// kmph
|
||||||
|
constexpr auto operator"" kmph(unsigned long long l) { return velocity<kilometre_per_hour, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" kmph(long double l) { return velocity<kilometre_per_hour, long double>(l); }
|
||||||
|
|
||||||
|
// mph
|
||||||
|
constexpr auto operator"" mph(unsigned long long l) { return velocity<mile_per_hour, std::int64_t>(l); }
|
||||||
|
constexpr auto operator"" mph(long double l) { return velocity<mile_per_hour, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
48
src/include/units/physical/si/voltage.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/current.h>
|
||||||
|
#include <units/physical/si/power.h>
|
||||||
|
#include <units/physical/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct volt : named_unit<volt, "V", prefix> {};
|
||||||
|
|
||||||
|
struct dim_voltage : physical::dim_voltage<dim_voltage, volt, dim_power, dim_electric_current> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using voltage = quantity<dim_voltage, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// V
|
||||||
|
constexpr auto operator""V(unsigned long long l) { return voltage<volt, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""V(long double l) { return voltage<volt, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
66
src/include/units/physical/si/volume.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/physical/dimensions.h>
|
||||||
|
#include <units/physical/si/length.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
|
||||||
|
namespace units::si {
|
||||||
|
|
||||||
|
struct cubic_metre : unit<cubic_metre> {};
|
||||||
|
struct dim_volume : physical::dim_volume<dim_volume, cubic_metre, dim_length> {};
|
||||||
|
|
||||||
|
struct cubic_millimetre : deduced_unit<cubic_millimetre, dim_volume, millimetre> {};
|
||||||
|
struct cubic_centimetre : deduced_unit<cubic_centimetre, dim_volume, centimetre> {};
|
||||||
|
struct cubic_kilometre : deduced_unit<cubic_kilometre, dim_volume, kilometre> {};
|
||||||
|
struct cubic_foot : deduced_unit<cubic_foot, dim_volume, foot> {};
|
||||||
|
|
||||||
|
template<Unit U, Scalar Rep = double>
|
||||||
|
using volume = quantity<dim_volume, U, Rep>;
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
// cub_mm
|
||||||
|
constexpr auto operator""cub_mm(unsigned long long l) { return volume<cubic_millimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""cub_mm(long double l) { return volume<cubic_millimetre, long double>(l); }
|
||||||
|
|
||||||
|
// cub_cm
|
||||||
|
constexpr auto operator""cub_cm(unsigned long long l) { return volume<cubic_centimetre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""cub_cm(long double l) { return volume<cubic_centimetre, long double>(l); }
|
||||||
|
|
||||||
|
// cub_m
|
||||||
|
constexpr auto operator""cub_m(unsigned long long l) { return volume<cubic_metre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""cub_m(long double l) { return volume<cubic_metre, long double>(l); }
|
||||||
|
|
||||||
|
// cub_km
|
||||||
|
constexpr auto operator""cub_km(unsigned long long l) { return volume<cubic_kilometre, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""cub_km(long double l) { return volume<cubic_kilometre, long double>(l); }
|
||||||
|
|
||||||
|
// cub_ft
|
||||||
|
constexpr auto operator""cub_ft(unsigned long long l) { return volume<cubic_foot, std::int64_t>(l); }
|
||||||
|
constexpr auto operator""cub_ft(long double l) { return volume<cubic_foot, long double>(l); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace units::si
|
@@ -22,49 +22,56 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/downcasting.h>
|
#include <units/bits/external/downcasting.h>
|
||||||
#include <units/bits/fixed_string.h>
|
#include <units/bits/external/fixed_string.h>
|
||||||
#include <units/ratio.h>
|
#include <units/ratio.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
struct prefix_type {};
|
/**
|
||||||
|
* @brief The base for all prefix types
|
||||||
|
*
|
||||||
|
* Every prefix type should inherit from this type to satisfy PrefixType concept.
|
||||||
|
*/
|
||||||
|
struct prefix_type {};
|
||||||
|
|
||||||
template<typename T>
|
/**
|
||||||
concept PrefixType = std::derived_from<T, prefix_type>;
|
* @brief No prefix possible for the unit
|
||||||
|
*
|
||||||
|
* This is a special prefix type tag specifying that the unit can not be scaled with any kind
|
||||||
|
* of the prefix.
|
||||||
|
*/
|
||||||
|
struct no_prefix : prefix_type {};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<PrefixType PT, Ratio R>
|
template<PrefixType PT, Ratio R>
|
||||||
struct prefix_base : downcast_base<prefix_base<PT, R>> {
|
struct prefix_base : downcast_base<prefix_base<PT, R>> {
|
||||||
using prefix_type = PT;
|
using prefix_type = PT;
|
||||||
using ratio = R;
|
using ratio = R;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<typename Child, PrefixType PT, Ratio R, basic_fixed_string Symbol>
|
/**
|
||||||
struct prefix : downcast_child<Child, detail::prefix_base<PT, R>> {
|
* @brief A prefix used to scale units
|
||||||
|
*
|
||||||
|
* Data from a prefix class is used in two cases:
|
||||||
|
* - when defining a prefixed_unit its ratio is used to scale the reference unit and its
|
||||||
|
* symbol is used to prepend to the symbol of referenced unit
|
||||||
|
* - when printing the symbol of a scaled unit that was not predefined by the user but its
|
||||||
|
* factor matches ratio of a prefix from the specified prefix family, its symbol will be
|
||||||
|
* prepended to the symbol of the unit
|
||||||
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
* @tparam PT a type of prefix family
|
||||||
|
* @tparam Symbol a text representation of the prefix
|
||||||
|
* @tparam R factor to be used to scale a unit
|
||||||
|
*/
|
||||||
|
template<typename Child, PrefixType PT, basic_fixed_string Symbol, Ratio R>
|
||||||
|
requires (!std::same_as<PT, no_prefix>)
|
||||||
|
struct prefix : downcast_child<Child, detail::prefix_base<PT, ratio<R::num, R::den>>> {
|
||||||
static constexpr auto symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// TODO gcc:92150
|
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92150
|
|
||||||
// namespace detail {
|
|
||||||
|
|
||||||
// template<typename T>
|
|
||||||
// inline constexpr bool is_prefix = false;
|
|
||||||
|
|
||||||
// template<typename PrefixType, Ratio R, basic_fixed_string Symbol>
|
|
||||||
// inline constexpr bool is_prefix<prefix<PrefixType, R, Symbol>> = true;
|
|
||||||
|
|
||||||
// } // namespace detail
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
// concept Prefix = detail::is_prefix<T>;
|
|
||||||
concept Prefix = true;
|
|
||||||
|
|
||||||
struct no_prefix : prefix_type {};
|
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -22,182 +22,51 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/concepts.h>
|
#include <units/bits/common_quantity.h>
|
||||||
#include <units/unit.h>
|
#include <units/bits/dimension_op.h>
|
||||||
#include <limits>
|
#include <units/bits/unit_text.h>
|
||||||
|
#include <units/quantity_cast.h>
|
||||||
|
|
||||||
|
#if __GNUC__ >= 10
|
||||||
|
#include <compare>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
// is_quantity
|
namespace detail {
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename From, typename To>
|
||||||
inline constexpr bool is_quantity = false;
|
concept safe_convertible = // exposition only
|
||||||
|
std::convertible_to<From, To> &&
|
||||||
|
(treat_as_floating_point<To> || (!treat_as_floating_point<From>));
|
||||||
|
|
||||||
// partial specialization below after the first quantity forward declaration
|
template<typename Rep, typename UnitFrom, typename UnitTo>
|
||||||
|
concept safe_divisible = // exposition only
|
||||||
|
treat_as_floating_point<Rep> ||
|
||||||
|
ratio_divide<typename UnitFrom::ratio, typename UnitTo::ratio>::den == 1;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<typename T>
|
/**
|
||||||
concept Quantity = detail::is_quantity<T>;
|
* @brief A quantity
|
||||||
|
*
|
||||||
template<typename T, typename Dim>
|
* Property of a phenomenon, body, or substance, where the property has a magnitude that can be
|
||||||
concept QuantityOf = Quantity<T> && Dimension<Dim> && same_dim<typename T::dimension, Dim>;
|
* expressed by means of a number and a measurement unit.
|
||||||
|
*
|
||||||
// Scalar
|
* @tparam D a dimension of the quantity (can be either a BaseDimension or a DerivedDimension)
|
||||||
template<typename T>
|
* @tparam U a measurement unit of the quantity
|
||||||
concept Scalar =
|
* @tparam Rep a type to be used to represent values of a quantity
|
||||||
(!Quantity<T>) &&
|
*/
|
||||||
std::regular<T> &&
|
template<Dimension D, UnitOf<D> U, Scalar Rep = double>
|
||||||
std::totally_ordered<T> &&
|
class quantity {
|
||||||
detail::basic_arithmetic<T>;
|
|
||||||
|
|
||||||
template<Unit U, Scalar Rep>
|
|
||||||
class quantity;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename U, typename Rep>
|
|
||||||
inline constexpr bool is_quantity<quantity<U, Rep>> = true;
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// common_quantity
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename Q1, typename Q2, typename Rep>
|
|
||||||
struct common_quantity_impl;
|
|
||||||
|
|
||||||
template<typename U, typename Rep1, typename Rep2, typename Rep>
|
|
||||||
struct common_quantity_impl<quantity<U, Rep1>, quantity<U, Rep2>, Rep> {
|
|
||||||
using type = quantity<U, Rep>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2, typename Rep>
|
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension>
|
|
||||||
struct common_quantity_impl<quantity<U1, Rep1>, quantity<U2, Rep2>, Rep> {
|
|
||||||
using type =
|
|
||||||
quantity<downcast<unit<typename U1::dimension, common_ratio<typename U1::ratio, typename U2::ratio>>>,
|
|
||||||
Rep>;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
|
||||||
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
|
||||||
|
|
||||||
// quantity_cast
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename To, typename CRatio, typename CRep, bool NumIsOne = false, bool DenIsOne = false>
|
|
||||||
struct quantity_cast_impl {
|
|
||||||
template<typename Q>
|
|
||||||
static constexpr To cast(const Q& q)
|
|
||||||
{
|
|
||||||
if constexpr(treat_as_floating_point<CRep>) {
|
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
|
||||||
(static_cast<CRep>(CRatio::num) / static_cast<CRep>(CRatio::den))));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return To(
|
|
||||||
static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) / static_cast<CRep>(CRatio::den)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename To, typename CRatio, typename CRep>
|
|
||||||
struct quantity_cast_impl<To, CRatio, CRep, true, true> {
|
|
||||||
template<Quantity Q>
|
|
||||||
static constexpr To cast(const Q& q)
|
|
||||||
{
|
|
||||||
return To(static_cast<To::rep>(q.count()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename To, typename CRatio, typename CRep>
|
|
||||||
struct quantity_cast_impl<To, CRatio, CRep, true, false> {
|
|
||||||
template<Quantity Q>
|
|
||||||
static constexpr To cast(const Q& q)
|
|
||||||
{
|
|
||||||
if constexpr(treat_as_floating_point<CRep>) {
|
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * (CRep{1} / static_cast<CRep>(CRatio::den))));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio::den)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename To, typename CRatio, typename CRep>
|
|
||||||
struct quantity_cast_impl<To, CRatio, CRep, false, true> {
|
|
||||||
template<Quantity Q>
|
|
||||||
static constexpr To cast(const Q& q)
|
|
||||||
{
|
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template<Quantity To, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
|
||||||
requires same_dim<typename To::dimension, typename U::dimension> &&
|
|
||||||
detail::basic_arithmetic<std::common_type_t<typename To::rep, Rep, intmax_t>>
|
|
||||||
{
|
|
||||||
using c_ratio = ratio_divide<typename U::ratio, typename To::unit::ratio>;
|
|
||||||
using c_rep = std::common_type_t<typename To::rep, Rep, intmax_t>;
|
|
||||||
using ret_dim = downcast<typename To::unit::dimension>;
|
|
||||||
using ret_unit = downcast<unit<ret_dim, typename To::unit::ratio>>;
|
|
||||||
using ret = quantity<ret_unit, typename To::rep>;
|
|
||||||
using cast = detail::quantity_cast_impl<ret, c_ratio, c_rep, c_ratio::num == 1, c_ratio::den == 1>;
|
|
||||||
return cast::cast(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Unit ToU, Scalar ToRep, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
|
||||||
requires same_dim<typename ToU::dimension, typename U::dimension> &&
|
|
||||||
detail::basic_arithmetic<std::common_type_t<ToRep, Rep, intmax_t>>
|
|
||||||
{
|
|
||||||
return quantity_cast<quantity<ToU, ToRep>>(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Unit ToU, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
|
||||||
requires same_dim<typename ToU::dimension, typename U::dimension>
|
|
||||||
{
|
|
||||||
return quantity_cast<quantity<ToU, Rep>>(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Scalar ToRep, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
|
||||||
requires detail::basic_arithmetic<std::common_type_t<ToRep, Rep, intmax_t>>
|
|
||||||
{
|
|
||||||
return quantity_cast<quantity<U, ToRep>>(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
// quantity_values
|
|
||||||
|
|
||||||
template<Scalar Rep>
|
|
||||||
struct quantity_values {
|
|
||||||
static constexpr Rep zero() noexcept { return Rep(0); }
|
|
||||||
static constexpr Rep one() noexcept { return Rep(1); }
|
|
||||||
static constexpr Rep max() noexcept { return std::numeric_limits<Rep>::max(); }
|
|
||||||
static constexpr Rep min() noexcept { return std::numeric_limits<Rep>::lowest(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// quantity
|
|
||||||
|
|
||||||
template<Unit U, Scalar Rep = double>
|
|
||||||
class quantity {
|
|
||||||
Rep value_;
|
Rep value_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using dimension = D;
|
||||||
using unit = U;
|
using unit = U;
|
||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
using dimension = U::dimension;
|
|
||||||
|
|
||||||
quantity() = default;
|
quantity() = default;
|
||||||
quantity(const quantity&) = default;
|
quantity(const quantity&) = default;
|
||||||
@@ -205,17 +74,13 @@ namespace units {
|
|||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
requires detail::safe_convertible<Value, rep>
|
requires detail::safe_convertible<Value, rep>
|
||||||
constexpr explicit quantity(const Value& v): value_{static_cast<rep>(v)}
|
constexpr explicit quantity(const Value& v) : value_{static_cast<rep>(v)} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Quantity Q2>
|
template<Quantity Q2>
|
||||||
requires same_dim<dimension, typename Q2::dimension> &&
|
requires equivalent_dim<D, typename Q2::dimension> &&
|
||||||
detail::safe_convertible<typename Q2::rep, rep> &&
|
detail::safe_convertible<typename Q2::rep, rep> &&
|
||||||
detail::safe_divisible<rep, typename Q2::unit, unit>
|
detail::safe_divisible<rep, typename Q2::unit, unit>
|
||||||
constexpr quantity(const Q2& q): value_{quantity_cast<quantity>(q).count()}
|
constexpr quantity(const Q2& q) : value_{quantity_cast<quantity>(q).count()} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
quantity& operator=(const quantity&) = default;
|
quantity& operator=(const quantity&) = default;
|
||||||
quantity& operator=(quantity&&) = default;
|
quantity& operator=(quantity&&) = default;
|
||||||
@@ -233,7 +98,7 @@ namespace units {
|
|||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
[[nodiscard]] static constexpr quantity one() noexcept
|
[[nodiscard]] static constexpr quantity one() noexcept
|
||||||
requires requires { quantity_values<T>::one(); }
|
requires requires { quantity_values<T>::one(); }
|
||||||
// requires requires { quantity_values<Rep>::one(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires { quantity_values<Rep>::one(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::one());
|
return quantity(quantity_values<Rep>::one());
|
||||||
}
|
}
|
||||||
@@ -241,7 +106,7 @@ namespace units {
|
|||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
[[nodiscard]] static constexpr quantity min() noexcept
|
[[nodiscard]] static constexpr quantity min() noexcept
|
||||||
requires requires { quantity_values<T>::min(); }
|
requires requires { quantity_values<T>::min(); }
|
||||||
// requires requires { quantity_values<Rep>::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires { quantity_values<Rep>::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::min());
|
return quantity(quantity_values<Rep>::min());
|
||||||
}
|
}
|
||||||
@@ -249,7 +114,7 @@ namespace units {
|
|||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
[[nodiscard]] static constexpr quantity max() noexcept
|
[[nodiscard]] static constexpr quantity max() noexcept
|
||||||
requires requires { quantity_values<T>::max(); }
|
requires requires { quantity_values<T>::max(); }
|
||||||
// requires requires { quantity_values<Rep>::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires { quantity_values<Rep>::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::max());
|
return quantity(quantity_values<Rep>::max());
|
||||||
}
|
}
|
||||||
@@ -259,7 +124,7 @@ namespace units {
|
|||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
[[nodiscard]] constexpr quantity operator-() const
|
[[nodiscard]] constexpr quantity operator-() const
|
||||||
requires std::regular_invocable<std::ranges::negate, T>
|
requires std::regular_invocable<std::ranges::negate, T>
|
||||||
// requires std::regular_invocable<std::ranges::negate, rep> // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires std::regular_invocable<std::ranges::negate, rep> // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{
|
{
|
||||||
return quantity(-count());
|
return quantity(-count());
|
||||||
}
|
}
|
||||||
@@ -267,7 +132,7 @@ namespace units {
|
|||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
constexpr quantity& operator++()
|
constexpr quantity& operator++()
|
||||||
requires requires(T v) { { ++v } -> SAME_AS(T&); }
|
requires requires(T v) { { ++v } -> SAME_AS(T&); }
|
||||||
// requires requires(rep v) { { ++v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires(rep v) { { ++v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{
|
{
|
||||||
++value_;
|
++value_;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -277,7 +142,9 @@ namespace units {
|
|||||||
requires requires(T v) { { v++ } -> SAME_AS(T); }
|
requires requires(T v) { { v++ } -> SAME_AS(T); }
|
||||||
constexpr quantity operator++(int)
|
constexpr quantity operator++(int)
|
||||||
// requires requires(rep v) { { v++ } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires(rep v) { { v++ } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{ return quantity(value_++); }
|
{
|
||||||
|
return quantity(value_++);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
requires requires(T v) { { --v } -> SAME_AS(T&); }
|
requires requires(T v) { { --v } -> SAME_AS(T&); }
|
||||||
@@ -292,7 +159,9 @@ namespace units {
|
|||||||
requires requires(T v) { { v-- } -> SAME_AS(T); }
|
requires requires(T v) { { v-- } -> SAME_AS(T); }
|
||||||
constexpr quantity operator--(int)
|
constexpr quantity operator--(int)
|
||||||
// requires requires(rep v) { { v-- } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
// requires requires(rep v) { { v-- } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||||
{ return quantity(value_--); }
|
{
|
||||||
|
return quantity(value_--);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
template<typename T = Rep>
|
||||||
requires requires(T v1, T v2) { { v1 += v2 } -> SAME_AS(T&); }
|
requires requires(T v1, T v2) { { v1 += v2 } -> SAME_AS(T&); }
|
||||||
@@ -351,189 +220,232 @@ namespace units {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class CharT, class Traits>
|
#if __GNUC__ >= 10
|
||||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
|
||||||
{
|
|
||||||
return os << q.count() << " " << detail::unit_text<quantity::unit>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator+(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> && detail::basic_arithmetic<Rep1, Rep2>
|
requires equivalent_dim<D, D2> &&
|
||||||
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::totally_ordered_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() + rhs.count());
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
return cq(lhs).count() <=> cq(rhs).count();
|
||||||
return ret(ret(lhs).count() + ret(rhs).count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
// TODO op== not needed (gcc bug)
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator-(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
template<typename D2, typename U2, typename Rep2>
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
[[nodiscard]] friend constexpr auto operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
detail::basic_arithmetic<Rep1, Rep2>
|
requires equivalent_dim<D, D2> &&
|
||||||
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::equality_comparable_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() - rhs.count());
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
|
||||||
return ret(ret(lhs).count() - ret(rhs).count());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U, typename Rep, Scalar Value>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U, Rep>& q, const Value& v)
|
|
||||||
requires std::magma<std::ranges::times, Rep, Value>
|
|
||||||
{
|
|
||||||
using common_rep = decltype(q.count() * v);
|
|
||||||
using ret = quantity<U, common_rep>;
|
|
||||||
return ret(q.count() * v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Scalar Value, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator*(const Value& v, const quantity<U, Rep>& q)
|
|
||||||
requires std::magma<std::ranges::times, Value, Rep>
|
|
||||||
{
|
|
||||||
return q * v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr Scalar AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires same_dim<typename U1::dimension, dim_invert<typename U2::dimension>> &&
|
|
||||||
detail::basic_arithmetic<Rep1, Rep2>
|
|
||||||
{
|
|
||||||
using common_rep = decltype(lhs.count() * rhs.count());
|
|
||||||
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
|
||||||
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) / common_rep(ratio::den);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires (!same_dim<typename U1::dimension, dim_invert<typename U2::dimension>>) &&
|
|
||||||
(treat_as_floating_point<decltype(lhs.count() * rhs.count())> ||
|
|
||||||
(std::ratio_multiply<typename U1::ratio, typename U2::ratio>::den == 1)) &&
|
|
||||||
detail::basic_arithmetic<Rep1, Rep2>
|
|
||||||
{
|
|
||||||
using dim = dimension_multiply<typename U1::dimension, typename U2::dimension>;
|
|
||||||
using common_rep = decltype(lhs.count() * rhs.count());
|
|
||||||
using ret = quantity<downcast<unit<dim, ratio_multiply<typename U1::ratio, typename U2::ratio>>>, common_rep>;
|
|
||||||
return ret(lhs.count() * rhs.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Scalar Value, typename U, typename Rep>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const Value& v, const quantity<U, Rep>& q)
|
|
||||||
requires std::magma<std::ranges::divided_by, Value, Rep>
|
|
||||||
{
|
|
||||||
Expects(q != std::remove_cvref_t<decltype(q)>(0));
|
|
||||||
|
|
||||||
using dim = dim_invert<typename U::dimension>;
|
|
||||||
using common_rep = decltype(v / q.count());
|
|
||||||
using ret = quantity<downcast<unit<dim, ratio<U::ratio::den, U::ratio::num>>>, common_rep>;
|
|
||||||
return ret(v / q.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U, typename Rep, Scalar Value>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U, Rep>& q, const Value& v)
|
|
||||||
requires std::magma<std::ranges::divided_by, Rep, Value>
|
|
||||||
{
|
|
||||||
Expects(v != Value{0});
|
|
||||||
|
|
||||||
using common_rep = decltype(q.count() / v);
|
|
||||||
using ret = quantity<U, common_rep>;
|
|
||||||
return ret(q.count() / v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr Scalar AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
|
||||||
detail::basic_arithmetic<Rep1, Rep2>
|
|
||||||
{
|
|
||||||
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
|
||||||
|
|
||||||
using common_rep = decltype(lhs.count() / rhs.count());
|
|
||||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
|
||||||
return cq(lhs).count() / cq(rhs).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires (!same_dim<typename U1::dimension, typename U2::dimension>) &&
|
|
||||||
(treat_as_floating_point<decltype(lhs.count() / rhs.count())> ||
|
|
||||||
(ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1)) &&
|
|
||||||
detail::basic_arithmetic<Rep1, Rep2>
|
|
||||||
{
|
|
||||||
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
|
||||||
|
|
||||||
using common_rep = decltype(lhs.count() / rhs.count());
|
|
||||||
using dim = dimension_divide<typename U1::dimension, typename U2::dimension>;
|
|
||||||
using ret = quantity<downcast<unit<dim, ratio_divide<typename U1::ratio, typename U2::ratio>>>, common_rep>;
|
|
||||||
return ret(lhs.count() / rhs.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U, typename Rep, Scalar Value>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U, Rep>& q, const Value& v)
|
|
||||||
requires (!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Value>) &&
|
|
||||||
std::magma<std::ranges::modulus, Rep, Value>
|
|
||||||
{
|
|
||||||
using common_rep = decltype(q.count() % v);
|
|
||||||
using ret = quantity<U, common_rep>;
|
|
||||||
return ret(q.count() % v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires (!treat_as_floating_point<Rep1>) && (!treat_as_floating_point<Rep2>) &&
|
|
||||||
std::magma<std::ranges::modulus, Rep1, Rep2>
|
|
||||||
{
|
|
||||||
using common_rep = decltype(lhs.count() % rhs.count());
|
|
||||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
|
||||||
return ret(ret(lhs).count() % ret(rhs).count());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] constexpr bool operator==(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::equality_comparable_with<Rep1, Rep2>
|
|
||||||
{
|
|
||||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>>;
|
|
||||||
return cq(lhs).count() == cq(rhs).count();
|
return cq(lhs).count() == cq(rhs).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
#else
|
||||||
[[nodiscard]] constexpr bool operator!=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
template<typename D2, typename U2, typename Rep2>
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::equality_comparable_with<Rep1, Rep2>
|
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires equivalent_dim<D, D2> &&
|
||||||
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::equality_comparable_with<Rep, Rep2>
|
||||||
|
{
|
||||||
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
|
return cq(lhs).count() == cq(rhs).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D2, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] friend constexpr bool operator!=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires equivalent_dim<D, D2> &&
|
||||||
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::equality_comparable_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr bool operator<(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr bool operator<(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::totally_ordered_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>>;
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
return cq(lhs).count() < cq(rhs).count();
|
return cq(lhs).count() < cq(rhs).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr bool operator<=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr bool operator<=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::totally_ordered_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
return !(rhs < lhs);
|
return !(rhs < lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr bool operator>(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr bool operator>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::totally_ordered_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
return rhs < lhs;
|
return rhs < lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr bool operator>=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr bool operator>=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
detail::basic_arithmetic<Rep, Rep2> &&
|
||||||
|
std::totally_ordered_with<Rep, Rep2>
|
||||||
{
|
{
|
||||||
return !(lhs < rhs);
|
return !(lhs < rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class CharT, class Traits>
|
||||||
|
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
||||||
|
{
|
||||||
|
return os << q.count() << " " << detail::unit_text<quantity::dimension, quantity::unit>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator+(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(lhs.count() + rhs.count());
|
||||||
|
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||||
|
return ret(ret(lhs).count() + ret(rhs).count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator-(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(lhs.count() - rhs.count());
|
||||||
|
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||||
|
return ret(ret(lhs).count() - ret(rhs).count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D, typename U, typename Rep, Scalar Value>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<D, U, Rep>& q, const Value& v)
|
||||||
|
requires std::magma<std::ranges::times, Rep, Value>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(q.count() * v);
|
||||||
|
using ret = quantity<D, U, common_rep>;
|
||||||
|
return ret(q.count() * v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Scalar Value, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator*(const Value& v, const quantity<D, U, Rep>& q)
|
||||||
|
requires std::magma<std::ranges::times, Value, Rep>
|
||||||
|
{
|
||||||
|
return q * v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Scalar AUTO operator*(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2> && equivalent_dim<D1, dim_invert<D2>>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(lhs.count() * rhs.count());
|
||||||
|
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
||||||
|
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) / common_rep(ratio::den);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent_dim<D1, dim_invert<D2>>) // TODO equivalent_derived_dim?
|
||||||
|
{
|
||||||
|
using dim = dimension_multiply<D1, D2>;
|
||||||
|
using ratio1 = ratio_divide<typename U1::ratio, typename dimension_unit<D1>::ratio>;
|
||||||
|
using ratio2 = ratio_divide<typename U2::ratio, typename dimension_unit<D2>::ratio>;
|
||||||
|
using ratio = ratio_multiply<ratio_multiply<ratio1, ratio2>, typename dimension_unit<dim>::ratio>;
|
||||||
|
using unit = downcast_unit<dim, ratio>;
|
||||||
|
using common_rep = decltype(lhs.count() * rhs.count());
|
||||||
|
using ret = quantity<dim, unit, common_rep>;
|
||||||
|
return ret(lhs.count() * rhs.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Scalar Value, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator/(const Value& v, const quantity<D, U, Rep>& q)
|
||||||
|
requires std::magma<std::ranges::divided_by, Value, Rep>
|
||||||
|
{
|
||||||
|
Expects(q.count() != 0);
|
||||||
|
|
||||||
|
using dim = dim_invert<D>;
|
||||||
|
using ratio = ratio<U::ratio::den, U::ratio::num>;
|
||||||
|
using unit = downcast_unit<dim, ratio>;
|
||||||
|
using common_rep = decltype(v / q.count());
|
||||||
|
using ret = quantity<dim, unit, common_rep>;
|
||||||
|
return ret(v / q.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D, typename U, typename Rep, Scalar Value>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<D, U, Rep>& q, const Value& v)
|
||||||
|
requires std::magma<std::ranges::divided_by, Rep, Value>
|
||||||
|
{
|
||||||
|
Expects(v != Value{0});
|
||||||
|
|
||||||
|
using common_rep = decltype(q.count() / v);
|
||||||
|
using ret = quantity<D, U, common_rep>;
|
||||||
|
return ret(q.count() / v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Scalar AUTO operator/(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2> && equivalent_dim<D1, D2>
|
||||||
|
{
|
||||||
|
Expects(rhs.count() != 0);
|
||||||
|
|
||||||
|
using common_rep = decltype(lhs.count() / rhs.count());
|
||||||
|
using cq = common_quantity<quantity<D1, U1, Rep1>, quantity<D2, U2, Rep2>, common_rep>;
|
||||||
|
return cq(lhs).count() / cq(rhs).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
|
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent_dim<D1, D2>) // TODO equivalent_derived_dim?
|
||||||
|
{
|
||||||
|
Expects(rhs.count() != 0);
|
||||||
|
|
||||||
|
using common_rep = decltype(lhs.count() / rhs.count());
|
||||||
|
using dim = dimension_divide<D1, D2>;
|
||||||
|
using ratio1 = ratio_divide<typename U1::ratio, typename dimension_unit<D1>::ratio>;
|
||||||
|
using ratio2 = ratio_divide<typename U2::ratio, typename dimension_unit<D2>::ratio>;
|
||||||
|
using ratio = ratio_multiply<ratio_divide<ratio1, ratio2>, typename dimension_unit<dim>::ratio>;
|
||||||
|
using unit = downcast_unit<dim, ratio>;
|
||||||
|
using ret = quantity<dim, unit, common_rep>;
|
||||||
|
return ret(lhs.count() / rhs.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D, typename U, typename Rep, Scalar Value>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<D, U, Rep>& q, const Value& v)
|
||||||
|
requires (!treat_as_floating_point<Rep>) &&
|
||||||
|
(!treat_as_floating_point<Value>) &&
|
||||||
|
std::magma<std::ranges::modulus, Rep, Value>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(q.count() % v);
|
||||||
|
using ret = quantity<D, U, common_rep>;
|
||||||
|
return ret(q.count() % v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||||
|
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
|
requires (!treat_as_floating_point<Rep1>) &&
|
||||||
|
(!treat_as_floating_point<Rep2>) &&
|
||||||
|
std::magma<std::ranges::modulus, Rep1, Rep2>
|
||||||
|
{
|
||||||
|
using common_rep = decltype(lhs.count() % rhs.count());
|
||||||
|
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||||
|
return ret(ret(lhs).count() % ret(rhs).count());
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename D, typename U, typename Rep>
|
||||||
|
inline constexpr bool is_quantity<quantity<D, U, Rep>> = true;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
188
src/include/units/quantity_cast.h
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Mateusz Pusz
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <units/concepts.h>
|
||||||
|
#include <units/bits/dimension_op.h>
|
||||||
|
|
||||||
|
namespace units {
|
||||||
|
|
||||||
|
// QuantityOf
|
||||||
|
template<typename T, typename Dim>
|
||||||
|
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>;
|
||||||
|
|
||||||
|
// quantity_cast
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename To, typename CRatio, typename CRep, bool NumIsOne = false, bool DenIsOne = false>
|
||||||
|
struct quantity_cast_impl {
|
||||||
|
template<typename Q>
|
||||||
|
static constexpr To cast(const Q& q)
|
||||||
|
{
|
||||||
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
||||||
|
(static_cast<CRep>(CRatio::num) / static_cast<CRep>(CRatio::den))));
|
||||||
|
} else {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) /
|
||||||
|
static_cast<CRep>(CRatio::den)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename To, typename CRatio, typename CRep>
|
||||||
|
struct quantity_cast_impl<To, CRatio, CRep, true, true> {
|
||||||
|
template<Quantity Q>
|
||||||
|
static constexpr To cast(const Q& q)
|
||||||
|
{
|
||||||
|
return To(static_cast<To::rep>(q.count()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename To, typename CRatio, typename CRep>
|
||||||
|
struct quantity_cast_impl<To, CRatio, CRep, true, false> {
|
||||||
|
template<Quantity Q>
|
||||||
|
static constexpr To cast(const Q& q)
|
||||||
|
{
|
||||||
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * (CRep{1} / static_cast<CRep>(CRatio::den))));
|
||||||
|
} else {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio::den)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename To, typename CRatio, typename CRep>
|
||||||
|
struct quantity_cast_impl<To, CRatio, CRep, false, true> {
|
||||||
|
template<Quantity Q>
|
||||||
|
static constexpr To cast(const Q& q)
|
||||||
|
{
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Dimension FromD, Unit FromU, Dimension ToD, Unit ToU>
|
||||||
|
struct cast_ratio;
|
||||||
|
|
||||||
|
template<BaseDimension FromD, Unit FromU, BaseDimension ToD, Unit ToU>
|
||||||
|
struct cast_ratio<FromD, FromU, ToD, ToU> {
|
||||||
|
using type = ratio_divide<typename FromU::ratio, typename ToU::ratio>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension FromD, Unit FromU, DerivedDimension ToD, Unit ToU>
|
||||||
|
requires same_unit_reference<FromU, ToU>::value
|
||||||
|
struct cast_ratio<FromD, FromU, ToD, ToU> {
|
||||||
|
using type = ratio_divide<typename FromU::ratio, typename ToU::ratio>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<DerivedDimension FromD, Unit FromU, DerivedDimension ToD, Unit ToU>
|
||||||
|
struct cast_ratio<FromD, FromU, ToD, ToU> {
|
||||||
|
using from_ratio = ratio_multiply<typename FromD::base_units_ratio, typename FromU::ratio>;
|
||||||
|
using to_ratio = ratio_multiply<typename ToD::base_units_ratio, typename ToU::ratio>;
|
||||||
|
using type = ratio_divide<from_ratio, to_ratio>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Explcit cast of a quantity
|
||||||
|
*
|
||||||
|
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||||
|
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||||
|
*
|
||||||
|
* This cast gets the target quantity type to cast to. For example:
|
||||||
|
*
|
||||||
|
* auto q1 = units::quantity_cast<units::si::time<units::si::second>>(1ms);
|
||||||
|
*
|
||||||
|
* @tparam To a target quantity type to cast to
|
||||||
|
*/
|
||||||
|
template<Quantity To, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
|
requires QuantityOf<To, D> &&
|
||||||
|
detail::basic_arithmetic<std::common_type_t<typename To::rep, Rep, intmax_t>>
|
||||||
|
{
|
||||||
|
using c_ratio = detail::cast_ratio<D, U, typename To::dimension, typename To::unit>::type;
|
||||||
|
using c_rep = std::common_type_t<typename To::rep, Rep, intmax_t>;
|
||||||
|
using ret_unit = downcast_unit<typename To::dimension, typename To::unit::ratio>;
|
||||||
|
using ret = quantity<typename To::dimension, ret_unit, typename To::rep>;
|
||||||
|
using cast = detail::quantity_cast_impl<ret, c_ratio, c_rep, c_ratio::num == 1, c_ratio::den == 1>;
|
||||||
|
return cast::cast(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Explcit cast of a quantity
|
||||||
|
*
|
||||||
|
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||||
|
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||||
|
*
|
||||||
|
* This cast gets only the target dimension to cast to. For example:
|
||||||
|
*
|
||||||
|
* auto q1 = units::quantity_cast<units::si::acceleration>(200Gal);
|
||||||
|
*
|
||||||
|
* @tparam ToD a dimension type to use for a target quantity
|
||||||
|
*/
|
||||||
|
template<Dimension ToD, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
|
requires equivalent_dim<ToD, D>
|
||||||
|
{
|
||||||
|
return quantity_cast<quantity<ToD, dimension_unit<ToD>, Rep>>(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Explcit cast of a quantity
|
||||||
|
*
|
||||||
|
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||||
|
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||||
|
*
|
||||||
|
* This cast gets only the target unit to cast to. For example:
|
||||||
|
*
|
||||||
|
* auto q1 = units::quantity_cast<units::si::second>(1ms);
|
||||||
|
*
|
||||||
|
* @tparam ToU a unit type to use for a target quantity
|
||||||
|
*/
|
||||||
|
template<Unit ToU, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
|
requires UnitOf<ToU, D>
|
||||||
|
{
|
||||||
|
return quantity_cast<quantity<D, ToU, Rep>>(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Explcit cast of a quantity
|
||||||
|
*
|
||||||
|
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||||
|
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||||
|
*
|
||||||
|
* This cast gets only representation to cast to. For example:
|
||||||
|
*
|
||||||
|
* auto q1 = units::quantity_cast<int>(1ms);
|
||||||
|
*
|
||||||
|
* @tparam ToRep a representation type to use for a target quantity
|
||||||
|
*/
|
||||||
|
template<Scalar ToRep, typename D, typename U, typename Rep>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
|
requires detail::basic_arithmetic<std::common_type_t<ToRep, Rep, intmax_t>>
|
||||||
|
{
|
||||||
|
return quantity_cast<quantity<D, U, ToRep>>(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace units
|
@@ -22,23 +22,27 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/hacks.h>
|
#include <units/bits/external/hacks.h>
|
||||||
#include <type_traits>
|
#include <units/concepts.h>
|
||||||
#include <numeric>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <numeric>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] constexpr T abs(T v) noexcept { return v < 0 ? -v : v; }
|
[[nodiscard]] constexpr T abs(T v) noexcept
|
||||||
|
{
|
||||||
|
return v < 0 ? -v : v;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<std::intmax_t Num, std::intmax_t Den = 1>
|
template<std::intmax_t Num, std::intmax_t Den = 1>
|
||||||
requires (Den != 0)
|
requires(Den != 0)
|
||||||
struct ratio {
|
struct ratio {
|
||||||
static_assert(-INTMAX_MAX <= Num, "numerator too negative");
|
static_assert(-INTMAX_MAX <= Num, "numerator too negative");
|
||||||
static_assert(-INTMAX_MAX <= Den, "denominator too negative");
|
static_assert(-INTMAX_MAX <= Den, "denominator too negative");
|
||||||
|
|
||||||
@@ -46,29 +50,32 @@ namespace units {
|
|||||||
static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den);
|
static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den);
|
||||||
|
|
||||||
using type = ratio<num, den>;
|
using type = ratio<num, den>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// is_ratio
|
namespace detail {
|
||||||
|
|
||||||
namespace detail {
|
template<intmax_t Num, intmax_t Den>
|
||||||
|
inline constexpr bool is_ratio<ratio<Num, Den>> = true;
|
||||||
|
|
||||||
template<typename T>
|
} // namespace detail
|
||||||
inline constexpr bool is_ratio = false;
|
|
||||||
|
|
||||||
template<intmax_t Num, intmax_t Den>
|
|
||||||
inline constexpr bool is_ratio<ratio<Num, Den>> = true;
|
|
||||||
|
|
||||||
} // namespace detail
|
// ratio_add
|
||||||
|
// TODO implement ratio_add
|
||||||
|
// template<Ratio R1, Ratio R2>
|
||||||
|
// using ratio_add = detail::ratio_add_impl<R1, R2>::type;
|
||||||
|
|
||||||
template<typename T>
|
// ratio_subtract
|
||||||
concept Ratio = detail::is_ratio<T>;
|
// TODO implement ratio_subtract
|
||||||
|
// template<Ratio R1, Ratio R2>
|
||||||
|
// using ratio_subtract = detail::ratio_subtract_impl<R1, R2>::type;
|
||||||
|
|
||||||
// ratio_multiply
|
// ratio_multiply
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs)
|
static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs)
|
||||||
{
|
{
|
||||||
constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4);
|
constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4);
|
||||||
|
|
||||||
const std::uintmax_t a0 = detail::abs(lhs) % c;
|
const std::uintmax_t a0 = detail::abs(lhs) % c;
|
||||||
@@ -82,118 +89,113 @@ namespace units {
|
|||||||
Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication
|
Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication
|
||||||
|
|
||||||
return lhs * rhs;
|
return lhs * rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R1, typename R2>
|
template<typename R1, typename R2>
|
||||||
struct ratio_multiply_impl {
|
struct ratio_multiply_impl {
|
||||||
private:
|
private:
|
||||||
static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den);
|
static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den);
|
||||||
static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den);
|
static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using type = ratio<safe_multiply(R1::num / gcd1, R2::num / gcd2), safe_multiply(R1::den / gcd2, R2::den / gcd1)>;
|
using type = ratio<safe_multiply(R1::num / gcd1, R2::num / gcd2), safe_multiply(R1::den / gcd2, R2::den / gcd1)>;
|
||||||
static constexpr std::intmax_t num = type::num;
|
static constexpr std::intmax_t num = type::num;
|
||||||
static constexpr std::intmax_t den = type::den;
|
static constexpr std::intmax_t den = type::den;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<Ratio R1, Ratio R2>
|
template<Ratio R1, Ratio R2>
|
||||||
using ratio_multiply = detail::ratio_multiply_impl<R1, R2>::type;
|
using ratio_multiply = detail::ratio_multiply_impl<R1, R2>::type;
|
||||||
|
|
||||||
// ratio_divide
|
// ratio_divide
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename R1, typename R2>
|
template<typename R1, typename R2>
|
||||||
struct ratio_divide_impl {
|
struct ratio_divide_impl {
|
||||||
static_assert(R2::num != 0, "division by 0");
|
static_assert(R2::num != 0, "division by 0");
|
||||||
using type = ratio_multiply<R1, ratio<R2::den, R2::num>>;
|
using type = ratio_multiply<R1, ratio<R2::den, R2::num>>;
|
||||||
static constexpr std::intmax_t num = type::num;
|
static constexpr std::intmax_t num = type::num;
|
||||||
static constexpr std::intmax_t den = type::den;
|
static constexpr std::intmax_t den = type::den;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<Ratio R1, Ratio R2>
|
template<Ratio R1, Ratio R2>
|
||||||
using ratio_divide = detail::ratio_divide_impl<R1, R2>::type;
|
using ratio_divide = detail::ratio_divide_impl<R1, R2>::type;
|
||||||
|
|
||||||
// ratio_pow
|
// ratio_pow
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename R, std::size_t N>
|
template<typename R, std::size_t N>
|
||||||
struct ratio_pow_impl {
|
struct ratio_pow_impl {
|
||||||
using type = ratio_multiply<typename ratio_pow_impl<R, N - 1>::type, R>;
|
using type = ratio_multiply<typename ratio_pow_impl<R, N - 1>::type, R>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct ratio_pow_impl<R, 1> {
|
struct ratio_pow_impl<R, 1> {
|
||||||
using type = R;
|
using type = R;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct ratio_pow_impl<R, 0> {
|
struct ratio_pow_impl<R, 0> {
|
||||||
using type = ratio<1>;
|
using type = ratio<1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<Ratio R, std::size_t N>
|
template<Ratio R, std::size_t N>
|
||||||
using ratio_pow = detail::ratio_pow_impl<R, N>::type;
|
using ratio_pow = detail::ratio_pow_impl<R, N>::type;
|
||||||
|
|
||||||
// ratio_sqrt
|
// ratio_sqrt
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
constexpr std::intmax_t sqrt_impl(std::intmax_t v, std::intmax_t l, std::intmax_t r)
|
constexpr std::intmax_t sqrt_impl(std::intmax_t v, std::intmax_t l, std::intmax_t r)
|
||||||
{
|
{
|
||||||
if(l == r)
|
if (l == r) return r;
|
||||||
return r;
|
|
||||||
|
|
||||||
const auto mid = (r + l) / 2;
|
const auto mid = (r + l) / 2;
|
||||||
if(mid * mid >= v)
|
if (mid * mid >= v)
|
||||||
return sqrt_impl(v, l, mid);
|
return sqrt_impl(v, l, mid);
|
||||||
else
|
else
|
||||||
return sqrt_impl(v, mid + 1, r);
|
return sqrt_impl(v, mid + 1, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::intmax_t sqrt_impl(std::intmax_t v)
|
static constexpr std::intmax_t sqrt_impl(std::intmax_t v) { return sqrt_impl(v, 1, v); }
|
||||||
{
|
|
||||||
return sqrt_impl(v, 1, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct ratio_sqrt_impl {
|
struct ratio_sqrt_impl {
|
||||||
using type = ratio<detail::sqrt_impl(R::num), detail::sqrt_impl(R::den)>;
|
using type = ratio<detail::sqrt_impl(R::num), detail::sqrt_impl(R::den)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::intmax_t Den>
|
template<std::intmax_t Den>
|
||||||
struct ratio_sqrt_impl<ratio<0, Den>> {
|
struct ratio_sqrt_impl<ratio<0, Den>> {
|
||||||
using type = ratio<0>;
|
using type = ratio<0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<Ratio R>
|
template<Ratio R>
|
||||||
using ratio_sqrt = detail::ratio_sqrt_impl<R>::type;
|
using ratio_sqrt = detail::ratio_sqrt_impl<R>::type;
|
||||||
|
|
||||||
|
// common_ratio
|
||||||
|
|
||||||
// common_ratio
|
namespace detail {
|
||||||
|
|
||||||
namespace detail {
|
// TODO: simplified
|
||||||
|
template<typename R1, typename R2>
|
||||||
// TODO: simplified
|
struct common_ratio_impl {
|
||||||
template<typename R1, typename R2>
|
|
||||||
struct common_ratio_impl {
|
|
||||||
static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num);
|
static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num);
|
||||||
static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den);
|
static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den);
|
||||||
using type = ratio<gcd_num, (R1::den / gcd_den) * R2::den>;
|
using type = ratio<gcd_num, (R1::den / gcd_den) * R2::den>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
template<Ratio R1, Ratio R2>
|
template<Ratio R1, Ratio R2>
|
||||||
using common_ratio = detail::common_ratio_impl<R1, R2>::type;
|
using common_ratio = detail::common_ratio_impl<R1, R2>::type;
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -22,353 +22,157 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimension.h>
|
#include <units/bits/deduced_symbol_text.h>
|
||||||
|
#include <units/bits/deduced_unit.h>
|
||||||
|
#include <units/bits/external/downcasting.h>
|
||||||
|
#include <units/bits/external/fixed_string.h>
|
||||||
|
#include <units/bits/external/text_tools.h>
|
||||||
|
#include <units/bits/external/type_traits.h>
|
||||||
|
#include <units/derived_dimension.h>
|
||||||
#include <units/prefix.h>
|
#include <units/prefix.h>
|
||||||
#include <units/ratio.h>
|
#include <units/ratio.h>
|
||||||
#include <ratio>
|
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
template<Dimension D, Ratio R>
|
/**
|
||||||
requires (R::num * R::den > 0)
|
* @brief A common point for a hierarchy of units
|
||||||
struct unit : downcast_base<unit<D, R>> {
|
*
|
||||||
using dimension = D;
|
* A unit is an entity defined and adopted by convention, with which any other quantity of
|
||||||
|
* the same kind can be compared to express the ratio of the second quantity to the first
|
||||||
|
* one as a number.
|
||||||
|
*
|
||||||
|
* All units of the same dimension can be convereted between each other. To allow this all of
|
||||||
|
* them are expressed as different ratios of the same one proprietary chosen reference unit
|
||||||
|
* (i.e. all length units are expressed in terms of meter, all mass units are expressed in
|
||||||
|
* terms of gram, ...)
|
||||||
|
*
|
||||||
|
* @tparam U a unit to use as a reference for this dimension
|
||||||
|
* @tparam R a ratio of a reference unit
|
||||||
|
*/
|
||||||
|
template<UnitRatio R, typename U>
|
||||||
|
struct scaled_unit : downcast_base<scaled_unit<R, U>> {
|
||||||
using ratio = R;
|
using ratio = R;
|
||||||
};
|
using reference = U;
|
||||||
|
};
|
||||||
|
|
||||||
// is_unit
|
template<Dimension D, UnitRatio R>
|
||||||
|
using downcast_unit = downcast<scaled_unit<R, typename dimension_unit<D>::reference>>;
|
||||||
|
|
||||||
namespace detail {
|
template<Unit U1, Unit U2>
|
||||||
|
struct same_unit_reference : std::is_same<typename U1::reference, typename U2::reference> {};
|
||||||
|
|
||||||
template<typename T>
|
/**
|
||||||
inline constexpr bool is_unit = false;
|
* @brief An unnamed unit
|
||||||
|
*
|
||||||
template<typename D, typename R>
|
* Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension
|
||||||
inline constexpr bool is_unit<unit<D, R>> = true;
|
* and it should be passed in this dimension's definition.
|
||||||
|
*
|
||||||
}
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename Child>
|
||||||
concept Unit =
|
struct unit : downcast_child<Child, scaled_unit<ratio<1>, Child>> {
|
||||||
std::is_empty_v<T> &&
|
|
||||||
detail::is_unit<downcast_base_t<T>>;
|
|
||||||
|
|
||||||
// deduced_derived_unit
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename D>
|
|
||||||
struct get_unit_base_dim;
|
|
||||||
|
|
||||||
template<typename E, typename... Rest>
|
|
||||||
struct get_unit_base_dim<dimension<E, Rest...>> {
|
|
||||||
static_assert(sizeof...(Rest) == 0, "Base unit expected");
|
|
||||||
using dimension = E::dimension;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
|
|
||||||
struct ratio_op;
|
|
||||||
|
|
||||||
template<typename Result, int UnitExpDen, typename UnitRatio>
|
|
||||||
struct ratio_op<Result, 0, UnitExpDen, UnitRatio> {
|
|
||||||
using ratio = Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
|
|
||||||
struct ratio_op {
|
|
||||||
using calc_ratio = conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply<Result, UnitRatio>,
|
|
||||||
ratio_divide<Result, UnitRatio>>;
|
|
||||||
static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen);
|
|
||||||
using ratio = ratio_op<calc_ratio, value, UnitExpDen, UnitRatio>::ratio;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename D, typename... Us>
|
|
||||||
struct derived_ratio;
|
|
||||||
|
|
||||||
template<typename... Us>
|
|
||||||
struct derived_ratio<dimension<>, Us...> {
|
|
||||||
using ratio = ::units::ratio<1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename E, typename... ERest, typename U, typename... URest>
|
|
||||||
struct derived_ratio<dimension<E, ERest...>, U, URest...> {
|
|
||||||
static_assert(same_dim<typename E::dimension, typename U::dimension>, "The order and number of units in `deduced_derived_unit<Us...>` should match dimensions provided in a `derived_dimension<>`");
|
|
||||||
static_assert(sizeof...(ERest) == sizeof...(URest), "The number of `deduced_derived_unit<Us...>` units should match the number of exponents provided to `derived_dimension<>`");
|
|
||||||
using rest_ratio = derived_ratio<dimension<ERest...>, URest...>::ratio;
|
|
||||||
using ratio = ratio_op<rest_ratio, E::num, E::den, typename U::ratio>::ratio;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
constexpr auto exp_count(dimension<Es...>)
|
|
||||||
{
|
|
||||||
return sizeof...(Es);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
inline constexpr bool is_unit_of_base_dimension = (exp_count(typename U::dimension::base_type()) == 1);
|
|
||||||
|
|
||||||
template<Unit... Us>
|
|
||||||
inline constexpr bool are_units_of_base_dimension = (is_unit_of_base_dimension<Us> && ...);
|
|
||||||
|
|
||||||
template<Dimension D, Unit... Us>
|
|
||||||
using deduced_derived_unit =
|
|
||||||
unit<D, typename detail::derived_ratio<std::conditional_t<are_units_of_base_dimension<Us...>,
|
|
||||||
typename D::base_type, typename D::recipe>, Us...>::ratio>;
|
|
||||||
|
|
||||||
template<int Value>
|
|
||||||
requires (0 <= Value) && (Value < 10)
|
|
||||||
inline constexpr basic_fixed_string superscript_number = "\u2070";
|
|
||||||
|
|
||||||
// template<> inline constexpr basic_fixed_string superscript_number<0> = "\u2070";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<1> = "\u00b9";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<2> = "\u00b2";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<3> = "\u00b3";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<4> = "\u2074";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<5> = "\u2075";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<6> = "\u2076";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<7> = "\u2077";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<8> = "\u2078";
|
|
||||||
template<> inline constexpr basic_fixed_string superscript_number<9> = "\u2079";
|
|
||||||
|
|
||||||
template<int Value>
|
|
||||||
requires (Value >= 0)
|
|
||||||
constexpr auto superscript()
|
|
||||||
{
|
|
||||||
if constexpr(Value < 10)
|
|
||||||
return superscript_number<Value>;
|
|
||||||
else
|
|
||||||
return superscript<Value / 10>() + superscript<Value % 10>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int Value>
|
|
||||||
requires (Value >= 0)
|
|
||||||
constexpr auto regular()
|
|
||||||
{
|
|
||||||
if constexpr(Value < 10)
|
|
||||||
return basic_fixed_string(static_cast<char>('0' + Value));
|
|
||||||
else
|
|
||||||
return regular<Value / 10>() + regular<Value % 10>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Ratio>
|
|
||||||
constexpr auto ratio_text()
|
|
||||||
{
|
|
||||||
if constexpr(Ratio::num != 1 || Ratio::den != 1) {
|
|
||||||
auto txt = basic_fixed_string("[") + regular<Ratio::num>();
|
|
||||||
if constexpr(Ratio::den == 1) {
|
|
||||||
return txt + basic_fixed_string("]");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return txt + basic_fixed_string("/") + regular<Ratio::den>() + basic_fixed_string("]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return basic_fixed_string("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ratio, typename PrefixType>
|
|
||||||
constexpr auto prefix_or_ratio_text()
|
|
||||||
{
|
|
||||||
if constexpr(Ratio::num != 1 || Ratio::den != 1) {
|
|
||||||
if constexpr (!std::same_as<PrefixType, no_prefix>) {
|
|
||||||
using prefix = downcast<detail::prefix_base<PrefixType, Ratio>>;
|
|
||||||
|
|
||||||
if constexpr(!std::same_as<prefix, prefix_base<PrefixType, Ratio>>) {
|
|
||||||
// print as a prefixed unit
|
|
||||||
return prefix::symbol;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// print as a ratio of the coherent unit
|
|
||||||
return ratio_text<Ratio>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// print as a ratio of the coherent unit
|
|
||||||
return ratio_text<Ratio>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<bool Divide, std::size_t Idx>
|
|
||||||
constexpr auto operator_text()
|
|
||||||
{
|
|
||||||
if constexpr(Idx == 0) {
|
|
||||||
if constexpr(Divide) {
|
|
||||||
return basic_fixed_string("1/");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return basic_fixed_string("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if constexpr(Divide) {
|
|
||||||
return basic_fixed_string("/");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return basic_fixed_string("⋅");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename E, basic_fixed_string Symbol, std::size_t Idx>
|
|
||||||
constexpr auto exp_text()
|
|
||||||
{
|
|
||||||
// get calculation operator + symbol
|
|
||||||
const auto txt = operator_text<E::num < 0, Idx>() + Symbol;
|
|
||||||
if constexpr(E::den != 1) {
|
|
||||||
// add root part
|
|
||||||
return txt + basic_fixed_string("^(") + regular<abs(E::num)>() + basic_fixed_string("/") + regular<E::den>() + basic_fixed_string(")");
|
|
||||||
}
|
|
||||||
else if constexpr(abs(E::num) != 1) {
|
|
||||||
// add exponent part
|
|
||||||
return txt + superscript<abs(E::num)>();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return txt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Dim>
|
|
||||||
constexpr auto dimension_symbol()
|
|
||||||
{
|
|
||||||
if constexpr(BaseDimension<Dim>)
|
|
||||||
return Dim::symbol;
|
|
||||||
else
|
|
||||||
// coherent derived unit
|
|
||||||
return downcast<unit<Dim, ratio<1>>>::symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Es, std::size_t... Idxs>
|
|
||||||
constexpr auto base_symbol_text_impl(dimension<Es...>, std::index_sequence<Idxs...>)
|
|
||||||
{
|
|
||||||
return (exp_text<Es, dimension_symbol<typename Es::dimension>(), Idxs>() + ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
constexpr auto base_symbol_text(dimension<Es...> d)
|
|
||||||
{
|
|
||||||
return base_symbol_text_impl(d, std::index_sequence_for<Es...>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Es>
|
|
||||||
constexpr bool all_named(dimension<Es...>)
|
|
||||||
{
|
|
||||||
return (downcast<unit<typename Es::dimension, ratio<1>>>::is_named && ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Dim>
|
|
||||||
constexpr auto base_symbol_text()
|
|
||||||
{
|
|
||||||
using recipe = typename Dim::recipe;
|
|
||||||
if constexpr(all_named(recipe()))
|
|
||||||
return base_symbol_text(recipe());
|
|
||||||
else
|
|
||||||
return base_symbol_text(Dim());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename E, typename U, std::size_t Idx>
|
|
||||||
constexpr auto exp_validate_and_text()
|
|
||||||
{
|
|
||||||
static_assert(same_dim<typename E::dimension, typename U::dimension>, "The order and number of units in `deduced_derived_unit<Us...>` should match dimensions provided in a `derived_dimension<>`");
|
|
||||||
return exp_text<E, U::symbol, Idx>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Us, typename... Es, std::size_t... Idxs>
|
|
||||||
constexpr auto deduced_symbol_text_impl(dimension<Es...>, std::index_sequence<Idxs...>)
|
|
||||||
{
|
|
||||||
return (exp_validate_and_text<Es, Us, Idxs>() + ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Us, typename... Es>
|
|
||||||
constexpr auto deduced_symbol_text(dimension<Es...> d)
|
|
||||||
{
|
|
||||||
static_assert(sizeof...(Es) == sizeof...(Us), "The number of `deduced_derived_unit<Us...>` units should match the number of exponents provided to `derived_dimension<>`");
|
|
||||||
return deduced_symbol_text_impl<Us...>(d, std::index_sequence_for<Es...>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Dim, typename... Us>
|
|
||||||
constexpr auto deduced_symbol_text()
|
|
||||||
{
|
|
||||||
if constexpr(are_units_of_base_dimension<Us...>)
|
|
||||||
return deduced_symbol_text<Us...>(typename Dim::base_type());
|
|
||||||
else
|
|
||||||
return deduced_symbol_text<Us...>(typename Dim::recipe());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Unit>
|
|
||||||
constexpr auto unit_text()
|
|
||||||
{
|
|
||||||
if constexpr(!is_unit<Unit>) {
|
|
||||||
// Unit is a downcasted derived unit child class already so just print defined symbol immediately
|
|
||||||
return Unit::symbol;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we are dealing with a non-user-defined unit here
|
|
||||||
using ratio = Unit::ratio;
|
|
||||||
using dim = Unit::dimension;
|
|
||||||
if constexpr(!is_dimension<dim>) {
|
|
||||||
// downcasted user-defined dimension
|
|
||||||
// print as a prefix or ratio of a coherent unit symbol defined by the user
|
|
||||||
using coherent_unit = downcast<units::unit<dim, units::ratio<1>>>;
|
|
||||||
return prefix_or_ratio_text<ratio, typename coherent_unit::prefix_type>() + coherent_unit::symbol;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// print as a ratio of a coherent unit + coherent unit dimensions and their exponents
|
|
||||||
return ratio_text<ratio>() + base_symbol_text(dim{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
|
|
||||||
// derived_unit
|
|
||||||
|
|
||||||
template<typename Child, Dimension Dim, basic_fixed_string Symbol, PrefixType PT>
|
|
||||||
struct named_coherent_derived_unit : downcast_child<Child, unit<Dim, ratio<1>>> {
|
|
||||||
static constexpr bool is_named = true;
|
|
||||||
static constexpr auto symbol = Symbol;
|
|
||||||
using prefix_type = PT;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Child, Dimension Dim>
|
|
||||||
struct coherent_derived_unit : downcast_child<Child, unit<Dim, ratio<1>>> {
|
|
||||||
static constexpr bool is_named = false;
|
static constexpr bool is_named = false;
|
||||||
static constexpr auto symbol = detail::base_symbol_text<Dim>();
|
|
||||||
using prefix_type = no_prefix;
|
using prefix_type = no_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, Dimension Dim, basic_fixed_string Symbol, Ratio R, PrefixType PT = no_prefix>
|
/**
|
||||||
struct named_scaled_derived_unit : downcast_child<Child, unit<Dim, R>> {
|
* @brief Unknown unit
|
||||||
|
*
|
||||||
|
* Used as a coherent unit of an unknown dimension.
|
||||||
|
*/
|
||||||
|
struct unknown_unit : unit<unknown_unit> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A named unit
|
||||||
|
*
|
||||||
|
* Defines a named (in most cases coherent) unit that is then passed to a dimension definition.
|
||||||
|
* A named unit may be used by other units defined with the prefix of the same type, unless
|
||||||
|
* no_prefix is provided for PT template parameter (in such a case it is impossible to define
|
||||||
|
* a prefix unit based on this one).
|
||||||
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
* @tparam Symbol a short text representation of the unit
|
||||||
|
* @tparam PT no_prefix or a type of prefix family
|
||||||
|
*/
|
||||||
|
template<typename Child, basic_fixed_string Symbol, PrefixType PT>
|
||||||
|
struct named_unit : downcast_child<Child, scaled_unit<ratio<1>, Child>> {
|
||||||
static constexpr bool is_named = true;
|
static constexpr bool is_named = true;
|
||||||
static constexpr auto symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
using prefix_type = PT;
|
using prefix_type = PT;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, Dimension Dim, basic_fixed_string Symbol, PrefixType PT, Unit U, Unit... Us>
|
/**
|
||||||
struct named_deduced_derived_unit : downcast_child<Child, detail::deduced_derived_unit<Dim, U, Us...>> {
|
* @brief A scaled unit
|
||||||
|
*
|
||||||
|
* Defines a new named unit that is a scaled version of another unit. Such unit can be used by
|
||||||
|
* other units defined with the prefix of the same type, unless no_prefix is provided for PT
|
||||||
|
* template parameter (in such a case it is impossible to define a prefix unit based on this
|
||||||
|
* one).
|
||||||
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
* @tparam Symbol a short text representation of the unit
|
||||||
|
* @tparam PT no_prefix or a type of prefix family
|
||||||
|
* @tparam R a scale to apply to U
|
||||||
|
* @tparam U a reference unit to scale
|
||||||
|
*/
|
||||||
|
template<typename Child, basic_fixed_string Symbol, PrefixType PT, UnitRatio R, Unit U>
|
||||||
|
struct named_scaled_unit : downcast_child<Child, scaled_unit<ratio_multiply<R, typename U::ratio>, typename U::reference>> {
|
||||||
static constexpr bool is_named = true;
|
static constexpr bool is_named = true;
|
||||||
static constexpr auto symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
using prefix_type = PT;
|
using prefix_type = PT;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, Dimension Dim, Unit U, Unit... Us>
|
/**
|
||||||
requires U::is_named && (Us::is_named && ... && true)
|
* @brief A prefixed unit
|
||||||
struct deduced_derived_unit : downcast_child<Child, detail::deduced_derived_unit<Dim, U, Us...>> {
|
*
|
||||||
static constexpr bool is_named = false;
|
* Defines a new unit that is a scaled version of another unit by the provided prefix. It is
|
||||||
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, Us...>();
|
* only possible to create such a unit if the given prefix type matches the one defined in a
|
||||||
using prefix_type = no_prefix;
|
* reference unit.
|
||||||
};
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
template<typename Child, Prefix P, Unit U>
|
* @tparam P prefix to be appied to the reference unit
|
||||||
requires (!std::same_as<typename U::prefix_type, no_prefix>)
|
* @tparam U reference unit
|
||||||
struct prefixed_derived_unit : downcast_child<Child, unit<typename U::dimension, ratio_multiply<typename P::ratio, typename U::ratio>>> {
|
*/
|
||||||
|
template<typename Child, Prefix P, Unit U>
|
||||||
|
requires std::same_as<typename P::prefix_type, typename U::prefix_type>
|
||||||
|
// TODO replace with the below code when gcc will stop to crash on it ;-)
|
||||||
|
// struct prefixed_unit : named_scaled_unit<Child, P::symbol + U::symbol, typename P::prefix_type,
|
||||||
|
// ratio_multiply<typename P::ratio, typename U::ratio>,
|
||||||
|
// typename U::reference> {};
|
||||||
|
struct prefixed_unit :
|
||||||
|
downcast_child<Child, scaled_unit<ratio_multiply<typename P::ratio, typename U::ratio>, typename U::reference>> {
|
||||||
static constexpr bool is_named = true;
|
static constexpr bool is_named = true;
|
||||||
static constexpr auto symbol = P::symbol + U::symbol;
|
static constexpr auto symbol = P::symbol + U::symbol;
|
||||||
using prefix_type = P::prefix_type;
|
using prefix_type = P::prefix_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A unit with a deduced ratio and symbol
|
||||||
|
*
|
||||||
|
* Defines a new unit with a deduced ratio and symbol based on the recipe from the provided
|
||||||
|
* derived dimension. The number and order of provided units should match the recipe of the
|
||||||
|
* derived dimension. All of the units provided should also be a named ones so it is possible
|
||||||
|
* to create a deduced symbol text.
|
||||||
|
*
|
||||||
|
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||||
|
* @tparam Dim a derived dimension recipe to use for deduction
|
||||||
|
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
|
||||||
|
* @tparam URest the units for the rest of dimensions from the recipe
|
||||||
|
*/
|
||||||
|
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
|
||||||
|
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
||||||
|
(U::is_named && (URest::is_named && ... && true))
|
||||||
|
struct deduced_unit : downcast_child<Child, detail::deduced_unit<Dim, U, URest...>> {
|
||||||
|
static constexpr bool is_named = false;
|
||||||
|
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
|
||||||
|
using prefix_type = no_prefix;
|
||||||
|
};
|
||||||
|
|
||||||
|
// template<typename Child, Dimension Dim, basic_fixed_string Symbol, PrefixType PT, Unit U, Unit... Us>
|
||||||
|
// struct named_deduced_derived_unit : downcast_child<Child, detail::deduced_derived_unit<Dim, U, Us...>> {
|
||||||
|
// static constexpr bool is_named = true;
|
||||||
|
// static constexpr auto symbol = Symbol;
|
||||||
|
// using prefix_type = PT;
|
||||||
|
// };
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -22,4 +22,4 @@
|
|||||||
|
|
||||||
add_subdirectory(unit_test/runtime)
|
add_subdirectory(unit_test/runtime)
|
||||||
add_subdirectory(unit_test/static)
|
add_subdirectory(unit_test/static)
|
||||||
add_subdirectory(metabench)
|
#add_subdirectory(metabench)
|
||||||
|
@@ -131,7 +131,7 @@ namespace units {
|
|||||||
struct dim_invert<dimension<Es...>> : std::type_identity<downcast_traits_t<dimension<exp_invert_t<Es>...>>> {};
|
struct dim_invert<dimension<Es...>> : std::type_identity<downcast_traits_t<dimension<exp_invert_t<Es>...>>> {};
|
||||||
|
|
||||||
template<Dimension D>
|
template<Dimension D>
|
||||||
using dim_invert_t = dim_invert<typename D::base_type>::type;
|
using dim_invert_t = dim_invert<typename D::downcast_base_type>::type;
|
||||||
|
|
||||||
|
|
||||||
// make_dimension
|
// make_dimension
|
||||||
@@ -196,7 +196,7 @@ namespace units {
|
|||||||
struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<downcast_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {};
|
struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<downcast_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {};
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
using dimension_multiply_t = dimension_multiply<typename D1::base_type, typename D2::base_type>::type;
|
using dimension_multiply_t = dimension_multiply<typename D1::downcast_base_type, typename D2::downcast_base_type>::type;
|
||||||
|
|
||||||
// dimension_divide
|
// dimension_divide
|
||||||
|
|
||||||
@@ -209,6 +209,6 @@ namespace units {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
using dimension_divide_t = dimension_divide<typename D1::base_type, typename D2::base_type>::type;
|
using dimension_divide_t = dimension_divide<typename D1::downcast_base_type, typename D2::downcast_base_type>::type;
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -131,7 +131,7 @@ namespace units {
|
|||||||
struct dim_invert<dimension<Es...>> : std::type_identity<downcast_traits_t<dimension<exp_invert_t<Es>...>>> {};
|
struct dim_invert<dimension<Es...>> : std::type_identity<downcast_traits_t<dimension<exp_invert_t<Es>...>>> {};
|
||||||
|
|
||||||
template<Dimension D>
|
template<Dimension D>
|
||||||
using dim_invert_t = dim_invert<typename D::base_type>::type;
|
using dim_invert_t = dim_invert<typename D::downcast_base_type>::type;
|
||||||
|
|
||||||
|
|
||||||
// make_dimension
|
// make_dimension
|
||||||
@@ -196,7 +196,7 @@ namespace units {
|
|||||||
struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<downcast_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {};
|
struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<downcast_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {};
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
using dimension_multiply_t = dimension_multiply<typename D1::base_type, typename D2::base_type>::type;
|
using dimension_multiply_t = dimension_multiply<typename D1::downcast_base_type, typename D2::downcast_base_type>::type;
|
||||||
|
|
||||||
// dimension_divide
|
// dimension_divide
|
||||||
|
|
||||||
@@ -209,6 +209,6 @@ namespace units {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
using dimension_divide_t = dimension_divide<typename D1::base_type, typename D2::base_type>::type;
|
using dimension_divide_t = dimension_divide<typename D1::downcast_base_type, typename D2::downcast_base_type>::type;
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|