mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
refactor: References are now guarded UNITS_REFERENCES
with (ON by default) + examples duplicated to subdirectories
Now References can be disabled to meassure a compile time impact. Also the same examples are now provided in two subdirectories to be able to easily compare the pros and cons of every quantity construction technique.
This commit is contained in:
@ -64,8 +64,6 @@ and dimensional analysis can be performed without sacrificing on accuracy. Pleas
|
|||||||
the below example for a quick preview of basic library features:
|
the below example for a quick preview of basic library features:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#define UNITS_LITERALS
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/length.h>
|
#include <units/isq/si/length.h>
|
||||||
#include <units/isq/si/speed.h>
|
#include <units/isq/si/speed.h>
|
||||||
|
@ -41,11 +41,13 @@ class UnitsConan(ConanFile):
|
|||||||
"gsl-lite/0.37.0"
|
"gsl-lite/0.37.0"
|
||||||
)
|
)
|
||||||
options = {
|
options = {
|
||||||
|
"references": [True, False],
|
||||||
"literals": [True, False],
|
"literals": [True, False],
|
||||||
"downcast_mode": ["off", "on", "auto"],
|
"downcast_mode": ["off", "on", "auto"],
|
||||||
"build_docs": [True, False]
|
"build_docs": [True, False]
|
||||||
}
|
}
|
||||||
default_options = {
|
default_options = {
|
||||||
|
"references": True,
|
||||||
"literals": False,
|
"literals": False,
|
||||||
"downcast_mode": "on",
|
"downcast_mode": "on",
|
||||||
"build_docs": True
|
"build_docs": True
|
||||||
@ -118,7 +120,8 @@ class UnitsConan(ConanFile):
|
|||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
tc = CMakeToolchain(self)
|
tc = CMakeToolchain(self)
|
||||||
tc.variables["UNITS_LITERALS"] = self.options.udls
|
tc.variables["UNITS_REFERENCES"] = self.options.references
|
||||||
|
tc.variables["UNITS_LITERALS"] = self.options.literals
|
||||||
tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper()
|
tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper()
|
||||||
# if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain
|
# if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain
|
||||||
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
|
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
|
||||||
|
@ -91,3 +91,14 @@ WARN_AS_ERROR = NO
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
QUIET = YES
|
QUIET = YES
|
||||||
|
|
||||||
|
# The PREDEFINED tag can be used to specify one or more macro names that are
|
||||||
|
# defined before the preprocessor is started (similar to the -D option of e.g.
|
||||||
|
# gcc). The argument of the tag is a list of macros of the form: name or
|
||||||
|
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
|
||||||
|
# is assumed. To prevent a macro definition from being undefined via #undef or
|
||||||
|
# recursively expanded use the := operator instead of the = operator.
|
||||||
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
|
PREDEFINED = UNITS_REFERENCES \
|
||||||
|
UNITS_LITERALS
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
avg_speed
|
avg_speed
|
||||||
=========
|
=========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/avg_speed.cpp
|
.. literalinclude:: ../../example/references/avg_speed.cpp
|
||||||
:caption: avg_speed.cpp
|
:caption: avg_speed.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
box_example
|
box_example
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/box_example.cpp
|
.. literalinclude:: ../../example/references/box_example.cpp
|
||||||
:caption: box_example.cpp
|
:caption: box_example.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
capacitor_time_curve
|
capacitor_time_curve
|
||||||
====================
|
====================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/capacitor_time_curve.cpp
|
.. literalinclude:: ../../example/references/capacitor_time_curve.cpp
|
||||||
:caption: capacitor_time_curve.cpp
|
:caption: capacitor_time_curve.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
clcpp_response
|
clcpp_response
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/clcpp_response.cpp
|
.. literalinclude:: ../../example/references/clcpp_response.cpp
|
||||||
:caption: clcpp_response.cpp
|
:caption: clcpp_response.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
conversion_factor
|
conversion_factor
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/conversion_factor.cpp
|
.. literalinclude:: ../../example/references/conversion_factor.cpp
|
||||||
:caption: conversion_factor.cpp
|
:caption: conversion_factor.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
custom_systems
|
custom_systems
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/custom_systems.cpp
|
.. literalinclude:: ../../example/references/custom_systems.cpp
|
||||||
:caption: custom_systems.cpp
|
:caption: custom_systems.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
foot_pound_second
|
foot_pound_second
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/foot_pound_second.cpp
|
.. literalinclude:: ../../example/references/foot_pound_second.cpp
|
||||||
:caption: foot_pound_second.cpp
|
:caption: foot_pound_second.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -13,7 +13,7 @@ This example presents the usage of:
|
|||||||
- quantities text output formatting,
|
- quantities text output formatting,
|
||||||
- cooperation with `std::chrono`.
|
- cooperation with `std::chrono`.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer.h
|
.. literalinclude:: ../../example/references/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:end-before: using namespace units;
|
:end-before: using namespace units;
|
||||||
@ -35,7 +35,7 @@ For example we have 3 for a quantity of length:
|
|||||||
- ``height`` - a relative altitude difference between 2 points in the air
|
- ``height`` - a relative altitude difference between 2 points in the air
|
||||||
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
|
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer.h
|
.. literalinclude:: ../../example/references/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: using namespace units;
|
:start-at: using namespace units;
|
||||||
:end-before: // text output
|
:end-before: // text output
|
||||||
@ -44,7 +44,7 @@ For example we have 3 for a quantity of length:
|
|||||||
|
|
||||||
Next a custom text output is provided both for C++ output streams and the text formatting facility.
|
Next a custom text output is provided both for C++ output streams and the text formatting facility.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer.h
|
.. literalinclude:: ../../example/references/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: // text output
|
:start-at: // text output
|
||||||
:end-before: // definition of glide computer databases and utilities
|
:end-before: // definition of glide computer databases and utilities
|
||||||
@ -58,13 +58,13 @@ convert it to the one required by the engine interface.
|
|||||||
The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions,
|
The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions,
|
||||||
safety constraints, and a towing height.
|
safety constraints, and a towing height.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer.h
|
.. literalinclude:: ../../example/references/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: // definition of glide computer databases and utilities
|
:start-at: // definition of glide computer databases and utilities
|
||||||
:linenos:
|
:linenos:
|
||||||
:lineno-match:
|
:lineno-match:
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer_example.cpp
|
.. literalinclude:: ../../example/references/glide_computer_example.cpp
|
||||||
:caption: glide_computer_example.cpp
|
:caption: glide_computer_example.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
@ -74,7 +74,7 @@ Having all of that it estimates the number of flight phases (towing, circling, g
|
|||||||
needed to finish a task. As an output it provides the duration needed to finish the task while
|
needed to finish a task. As an output it provides the duration needed to finish the task while
|
||||||
flying a selected glider in the specific weather conditions.
|
flying a selected glider in the specific weather conditions.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer.cpp
|
.. literalinclude:: ../../example/references/glide_computer.cpp
|
||||||
:caption: glide_computer.cpp
|
:caption: glide_computer.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -4,7 +4,7 @@ kalman_filter-alpha_beta_filter_example2
|
|||||||
This example is based on the 1d aircraft α-β filter example 2 from the
|
This example is based on the 1d aircraft α-β filter example 2 from the
|
||||||
`Kalman Filter <https://www.kalmanfilter.net/alphabeta.html#ex2>`_ tutorial.
|
`Kalman Filter <https://www.kalmanfilter.net/alphabeta.html#ex2>`_ tutorial.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/kalman_filter-alpha_beta_filter_example2.cpp
|
.. literalinclude:: ../../example/references/kalman_filter-alpha_beta_filter_example2.cpp
|
||||||
:caption: kalman_filter-alpha_beta_filter_example2.cpp
|
:caption: kalman_filter-alpha_beta_filter_example2.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
linear_algebra
|
linear_algebra
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/linear_algebra.cpp
|
.. literalinclude:: ../../example/references/linear_algebra.cpp
|
||||||
:caption: linear_algebra.cpp
|
:caption: linear_algebra.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
measurement
|
measurement
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/measurement.cpp
|
.. literalinclude:: ../../example/references/measurement.cpp
|
||||||
:caption: measurement.cpp
|
:caption: measurement.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
total_energy
|
total_energy
|
||||||
============
|
============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/total_energy.cpp
|
.. literalinclude:: ../../example/references/total_energy.cpp
|
||||||
:caption: total_energy.cpp
|
:caption: total_energy.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
unknown_dimension
|
unknown_dimension
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/unknown_dimension.cpp
|
.. literalinclude:: ../../example/references/unknown_dimension.cpp
|
||||||
:caption: unknown_dimension.cpp
|
:caption: unknown_dimension.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -56,6 +56,8 @@ Quantity References
|
|||||||
Quantity References provide an alternative and simplified way to create quantities.
|
Quantity References provide an alternative and simplified way to create quantities.
|
||||||
They are defined using the `reference` class template::
|
They are defined using the `reference` class template::
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto km = reference<dim_length, kilometre>{};
|
inline constexpr auto km = reference<dim_length, kilometre>{};
|
||||||
@ -63,6 +65,8 @@ They are defined using the `reference` class template::
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
With the above our code can look as follows::
|
With the above our code can look as follows::
|
||||||
|
|
||||||
using namespace units::isq::si::references;
|
using namespace units::isq::si::references;
|
||||||
@ -103,8 +107,6 @@ Alternatively, to construct quantities with compile-time known values the librar
|
|||||||
|
|
||||||
Thanks to them the same code can be as simple as::
|
Thanks to them the same code can be as simple as::
|
||||||
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
|
|
||||||
using namespace units::isq::si::literals;
|
using namespace units::isq::si::literals;
|
||||||
auto d = 123._q_km; // si::length<si::kilometre, long double>
|
auto d = 123._q_km; // si::length<si::kilometre, long double>
|
||||||
auto v = 70_q_km_per_h; // si::speed<si::kilometre_per_hour, std::int64_t>
|
auto v = 70_q_km_per_h; // si::speed<si::kilometre_per_hour, std::int64_t>
|
||||||
@ -122,7 +124,7 @@ Thanks to them the same code can be as simple as::
|
|||||||
|
|
||||||
As one can read in the next section UDLs, are considered to be inferior to `Quantity References`_
|
As one can read in the next section UDLs, are considered to be inferior to `Quantity References`_
|
||||||
and their definition affects compile-time performance a lot. This is why they are an opt-in feature
|
and their definition affects compile-time performance a lot. This is why they are an opt-in feature
|
||||||
of the library and in order to use them one has to provide a `UNITS_UDL` preprocessor definition.
|
of the library and in order to use them one has to provide a `UNITS_LITERALS` preprocessor definition.
|
||||||
|
|
||||||
|
|
||||||
UDLs vs Quantity References
|
UDLs vs Quantity References
|
||||||
|
@ -40,8 +40,6 @@ but still easy to use interface where all unit conversions and dimensional analy
|
|||||||
performed without sacrificing on accuracy. Please see the below example for a quick preview
|
performed without sacrificing on accuracy. Please see the below example for a quick preview
|
||||||
of basic library features::
|
of basic library features::
|
||||||
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/length.h>
|
#include <units/isq/si/length.h>
|
||||||
#include <units/isq/si/speed.h>
|
#include <units/isq/si/speed.h>
|
||||||
|
@ -123,6 +123,15 @@ It also runs unit tests during Conan build.
|
|||||||
Conan Options
|
Conan Options
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
references
|
||||||
|
++++++++++
|
||||||
|
|
||||||
|
**Values**: ``True``/``False``
|
||||||
|
|
||||||
|
**Defaulted to**: ``True``
|
||||||
|
|
||||||
|
Determines if library should provide Quantity References for quantities of various units.
|
||||||
|
|
||||||
literals
|
literals
|
||||||
++++++++
|
++++++++
|
||||||
|
|
||||||
@ -158,6 +167,16 @@ Additionally, enables project documentation generation when the project is being
|
|||||||
CMake Options
|
CMake Options
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
UNITS_REFERENCES
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
**Values**: ``ON``/``OFF``
|
||||||
|
|
||||||
|
**Defaulted to**: ``ON``
|
||||||
|
|
||||||
|
Equivalent to `references`_.
|
||||||
|
|
||||||
|
|
||||||
UNITS_LITERALS
|
UNITS_LITERALS
|
||||||
++++++++++++++
|
++++++++++++++
|
||||||
|
|
||||||
|
@ -22,40 +22,13 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
#
|
|
||||||
# add_example(target <depependencies>...)
|
|
||||||
#
|
|
||||||
function(add_example target)
|
|
||||||
add_executable(${target} ${target}.cpp)
|
|
||||||
target_link_libraries(${target} PRIVATE ${ARGN})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
|
||||||
add_example(box_example mp-units::core-fmt mp-units::si)
|
|
||||||
add_example(capacitor_time_curve mp-units::core-io mp-units::si)
|
|
||||||
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-us)
|
|
||||||
add_example(conversion_factor mp-units::core-fmt mp-units::core-io mp-units::si)
|
|
||||||
add_example(custom_systems mp-units::core-io mp-units::si)
|
|
||||||
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
|
|
||||||
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
|
|
||||||
add_example(hello_units mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-international)
|
|
||||||
add_example(kalman_filter-alpha_beta_filter_example2 mp-units::core-fmt mp-units::si)
|
|
||||||
add_example(measurement mp-units::core-io mp-units::si)
|
|
||||||
add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural)
|
|
||||||
add_example(unknown_dimension mp-units::core-io mp-units::si)
|
|
||||||
|
|
||||||
if(NOT UNITS_LIBCXX)
|
|
||||||
add_executable(glide_computer
|
|
||||||
geographic.cpp geographic.h
|
|
||||||
glide_computer.cpp glide_computer.h
|
|
||||||
glide_computer_example.cpp
|
|
||||||
)
|
|
||||||
target_link_libraries(glide_computer PRIVATE mp-units::core-fmt mp-units::si mp-units::si-international)
|
|
||||||
target_include_directories(glide_computer PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
find_package(linear_algebra CONFIG REQUIRED)
|
|
||||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
|
||||||
target_link_libraries(linear_algebra PRIVATE linear_algebra::linear_algebra)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(alternative_namespaces)
|
add_subdirectory(alternative_namespaces)
|
||||||
|
add_subdirectory(literals)
|
||||||
|
add_subdirectory(references)
|
||||||
|
|
||||||
|
add_executable(hello_units hello_units.cpp)
|
||||||
|
target_link_libraries(hello_units PRIVATE mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-international)
|
||||||
|
target_compile_definitions(hello_units PRIVATE
|
||||||
|
UNITS_REFERENCES
|
||||||
|
UNITS_LITERALS
|
||||||
|
)
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/international/length.h>
|
#include <units/isq/si/international/length.h>
|
||||||
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
||||||
|
60
example/literals/CMakeLists.txt
Normal file
60
example/literals/CMakeLists.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
|
#
|
||||||
|
# add_example(target <depependencies>...)
|
||||||
|
#
|
||||||
|
function(add_example target)
|
||||||
|
add_executable(${target}-literals ${target}.cpp)
|
||||||
|
target_link_libraries(${target}-literals PRIVATE ${ARGN})
|
||||||
|
target_compile_definitions(${target}-literals PRIVATE UNITS_LITERALS)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
||||||
|
add_example(box_example mp-units::core-fmt mp-units::si)
|
||||||
|
add_example(capacitor_time_curve mp-units::core-io mp-units::si)
|
||||||
|
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-us)
|
||||||
|
add_example(conversion_factor mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
add_example(custom_systems mp-units::core-io mp-units::si)
|
||||||
|
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
|
||||||
|
add_example(kalman_filter-alpha_beta_filter_example2 mp-units::core-fmt mp-units::si)
|
||||||
|
add_example(measurement mp-units::core-io mp-units::si)
|
||||||
|
add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural)
|
||||||
|
add_example(unknown_dimension mp-units::core-io mp-units::si)
|
||||||
|
|
||||||
|
if(NOT UNITS_LIBCXX)
|
||||||
|
add_executable(glide_computer-literals
|
||||||
|
geographic.cpp geographic.h
|
||||||
|
glide_computer.cpp glide_computer.h
|
||||||
|
glide_computer_example.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(glide_computer-literals PRIVATE mp-units::core-fmt mp-units::si mp-units::si-international)
|
||||||
|
target_include_directories(glide_computer-literals PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
target_compile_definitions(glide_computer-literals PRIVATE UNITS_LITERALS)
|
||||||
|
|
||||||
|
find_package(linear_algebra CONFIG REQUIRED)
|
||||||
|
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
target_link_libraries(linear_algebra-literals PRIVATE linear_algebra::linear_algebra)
|
||||||
|
endif()
|
193
example/literals/avg_speed.cpp
Normal file
193
example/literals/avg_speed.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
// 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/isq/si/cgs/length.h>
|
||||||
|
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/international/length.h>
|
||||||
|
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/length.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/isq/si/speed.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
constexpr si::speed<si::metre_per_second, int>
|
||||||
|
fixed_int_si_avg_speed(si::length<si::metre, int> d,
|
||||||
|
si::time<si::second, int> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr si::speed<si::metre_per_second>
|
||||||
|
fixed_double_si_avg_speed(si::length<si::metre> d,
|
||||||
|
si::time<si::second> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U1, typename R1, typename U2, typename R2>
|
||||||
|
constexpr Speed auto si_avg_speed(si::length<U1, R1> d,
|
||||||
|
si::time<U2, R2> t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Length D, Time T, Speed V>
|
||||||
|
void print_result(D distance, T duration, V speed)
|
||||||
|
{
|
||||||
|
const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed);
|
||||||
|
std::cout << "Average speed of a car that makes " << distance << " in "
|
||||||
|
<< duration << " is " << result_in_kmph << ".\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
// SI (int)
|
||||||
|
{
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
constexpr Length auto distance = 220_q_km; // 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::isq::si::literals;
|
||||||
|
constexpr Length auto distance = 220._q_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::isq::si::international::literals;
|
||||||
|
constexpr Length auto distance = 140_q_mi; // 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::isq::si::international::literals;
|
||||||
|
constexpr Length auto distance = 140._q_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::isq::si::cgs::literals;
|
||||||
|
constexpr Length auto distance = 22'000'000_q_cm; // constructed from a UDL
|
||||||
|
constexpr si::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::isq::si::cgs::literals;
|
||||||
|
constexpr Length auto distance = 22'000'000._q_cm; // constructed from a UDL
|
||||||
|
constexpr si::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";
|
||||||
|
}
|
||||||
|
}
|
113
example/literals/box_example.cpp
Normal file
113
example/literals/box_example.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// 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/format.h>
|
||||||
|
#include <units/generic/dimensionless.h>
|
||||||
|
#include <units/isq/si/amount_of_substance.h>
|
||||||
|
#include <units/isq/si/area.h>
|
||||||
|
#include <units/isq/si/constants.h>
|
||||||
|
#include <units/isq/si/density.h>
|
||||||
|
#include <units/isq/si/force.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/mass.h>
|
||||||
|
#include <units/isq/si/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/isq/si/volume.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
using m = si::metre;
|
||||||
|
using m2 = si::square_metre;
|
||||||
|
using m3 = si::cubic_metre;
|
||||||
|
using kg = si::kilogram;
|
||||||
|
using N = si::newton;
|
||||||
|
using kgpm3 = si::kilogram_per_metre_cub;
|
||||||
|
|
||||||
|
inline constexpr auto g = si::si2019::standard_gravity<>;
|
||||||
|
inline constexpr si::density<kgpm3> air_density(1.225);
|
||||||
|
|
||||||
|
|
||||||
|
class Box {
|
||||||
|
si::area<m2> base_;
|
||||||
|
si::length<m> height_;
|
||||||
|
si::density<kgpm3> density_ = air_density;
|
||||||
|
public:
|
||||||
|
constexpr Box(const si::length<m>& length, const si::length<m>& width, si::length<m> height) : base_(length * width), height_(std::move(height)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr si::force<N> filled_weight() const
|
||||||
|
{
|
||||||
|
const si::volume<m3> volume = base_ * height_;
|
||||||
|
const si::mass<kg> mass = density_ * volume;
|
||||||
|
return mass * g;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr si::length<m> fill_level(const si::mass<kg>& measured_mass) const
|
||||||
|
{
|
||||||
|
return height_ * measured_mass * g / filled_weight();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr si::volume<m3> spare_capacity(const si::mass<kg>& measured_mass) const
|
||||||
|
{
|
||||||
|
return (height_ - fill_level(measured_mass)) * base_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void set_contents_density(const si::density<kgpm3>& density_in)
|
||||||
|
{
|
||||||
|
assert(density_in > air_density);
|
||||||
|
density_ = density_in;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace units;
|
||||||
|
using namespace si::literals;
|
||||||
|
|
||||||
|
const si::length<m> height(200.0_q_mm);
|
||||||
|
auto box = Box(1000.0_q_mm, 500.0_q_mm, height);
|
||||||
|
box.set_contents_density(1000.0_q_kg_per_m3);
|
||||||
|
|
||||||
|
const auto fill_time = 200.0_q_s; // time since starting fill
|
||||||
|
const auto measured_mass = 20.0_q_kg; // measured mass at fill_time
|
||||||
|
|
||||||
|
const Length auto fill_level = box.fill_level(measured_mass);
|
||||||
|
const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height);
|
||||||
|
const Volume auto spare_capacity = box.spare_capacity(measured_mass);
|
||||||
|
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
|
||||||
|
const Speed auto float_rise_rate = fill_level / fill_time;
|
||||||
|
const Time auto fill_time_left = (height / fill_level - 1) * fill_time;
|
||||||
|
|
||||||
|
std::cout << "mp-units box example...\n";
|
||||||
|
std::cout << fmt::format("fill height at {} = {} ({} full)\n", fill_time, fill_level, fill_percent);
|
||||||
|
std::cout << fmt::format("spare_capacity at {} = {}\n", fill_time, spare_capacity);
|
||||||
|
std::cout << fmt::format("input flow rate after {} = {}\n", fill_time, input_flow_rate);
|
||||||
|
std::cout << fmt::format("float rise rate = {}\n", float_rise_rate);
|
||||||
|
std::cout << fmt::format("box full E.T.A. at current flow rate = {}\n", fill_time_left);
|
||||||
|
}
|
63
example/literals/capacitor_time_curve.cpp
Normal file
63
example/literals/capacitor_time_curve.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2020 Andy Little.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see http://www.gnu.org/licenses./
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
capacitor discharge curve using compile_time
|
||||||
|
physical_quantities
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <units/generic/dimensionless.h>
|
||||||
|
#include <units/isq/dimensions/electric_current.h>
|
||||||
|
#include <units/isq/si/capacitance.h>
|
||||||
|
#include <units/isq/si/resistance.h>
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/isq/si/voltage.h>
|
||||||
|
#include <units/math.h> // IWYU pragma: keep
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si;
|
||||||
|
|
||||||
|
std::cout << "mp-units capacitor time curve example...\n";
|
||||||
|
std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
|
||||||
|
std::cout.precision(3);
|
||||||
|
|
||||||
|
constexpr auto C = 0.47_q_uF;
|
||||||
|
constexpr auto V0 = 5.0_q_V;
|
||||||
|
constexpr auto R = 4.7_q_kR;
|
||||||
|
|
||||||
|
for (auto t = 0_q_ms; t <= 50_q_ms; ++t) {
|
||||||
|
const Voltage auto Vt = V0 * units::exp(-t / (R * C));
|
||||||
|
|
||||||
|
std::cout << "at " << t << " voltage is ";
|
||||||
|
|
||||||
|
if (Vt >= 1_q_V)
|
||||||
|
std::cout << Vt;
|
||||||
|
else if (Vt >= 1_q_mV)
|
||||||
|
std::cout << quantity_cast<millivolt>(Vt);
|
||||||
|
else if (Vt >= 1_q_uV)
|
||||||
|
std::cout << quantity_cast<microvolt>(Vt);
|
||||||
|
else if (Vt >= 1_q_nV)
|
||||||
|
std::cout << quantity_cast<nanovolt>(Vt);
|
||||||
|
else
|
||||||
|
std::cout << quantity_cast<picovolt>(Vt);
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
}
|
150
example/literals/clcpp_response.cpp
Normal file
150
example/literals/clcpp_response.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2019 Andy Little.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see http://www.gnu.org/licenses./
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <units/format.h>
|
||||||
|
#include <units/isq/si/area.h>
|
||||||
|
#include <units/isq/si/iau/length.h>
|
||||||
|
#include <units/isq/si/imperial/length.h>
|
||||||
|
#include <units/isq/si/international/length.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/isq/si/typographic/length.h>
|
||||||
|
#include <units/isq/si/us/length.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units;
|
||||||
|
|
||||||
|
void simple_quantities()
|
||||||
|
{
|
||||||
|
using namespace units::isq::si;
|
||||||
|
using namespace units::isq::si::international;
|
||||||
|
|
||||||
|
using distance = length<metre>;
|
||||||
|
using duration = isq::si::time<second>;
|
||||||
|
|
||||||
|
constexpr distance km = 1.0_q_km;
|
||||||
|
constexpr distance miles = 1.0_q_mi;
|
||||||
|
|
||||||
|
constexpr duration sec = 1_q_s;
|
||||||
|
constexpr duration min = 1_q_min;
|
||||||
|
constexpr duration hr = 1_q_h;
|
||||||
|
|
||||||
|
std::cout << "A physical quantities library can choose the simple\n";
|
||||||
|
std::cout << "option to provide output using a single type for each base unit:\n\n";
|
||||||
|
std::cout << km << '\n';
|
||||||
|
std::cout << miles << '\n';
|
||||||
|
std::cout << sec << '\n';
|
||||||
|
std::cout << min << '\n';
|
||||||
|
std::cout << hr << "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantities_with_typed_units()
|
||||||
|
{
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si;
|
||||||
|
using namespace units::isq::si::international;
|
||||||
|
|
||||||
|
constexpr length<kilometre> km = 1.0_q_km;
|
||||||
|
constexpr length<mile> miles = 1.0_q_mi;
|
||||||
|
|
||||||
|
std::cout.precision(6);
|
||||||
|
|
||||||
|
constexpr si::time<second> sec = 1_q_s;
|
||||||
|
constexpr si::time<minute> min = 1_q_min;
|
||||||
|
constexpr si::time<hour> hr = 1_q_h;
|
||||||
|
|
||||||
|
std::cout << "A more flexible option is to provide separate types for each unit,\n\n";
|
||||||
|
std::cout << km << '\n';
|
||||||
|
std::cout << miles << '\n';
|
||||||
|
std::cout << sec << '\n';
|
||||||
|
std::cout << min << '\n';
|
||||||
|
std::cout << hr << "\n\n";
|
||||||
|
|
||||||
|
constexpr length<metre> meter = 1_q_m;
|
||||||
|
std::cout << "then a wide range of pre-defined units can be defined and converted,\n"
|
||||||
|
" for consistency and repeatability across applications:\n\n";
|
||||||
|
|
||||||
|
std::cout << meter << '\n';
|
||||||
|
|
||||||
|
std::cout << " = " << quantity_cast<si::astronomical_unit>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::iau::angstrom>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::imperial::chain>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::fathom>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::us::fathom>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::foot>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::us::foot>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::inch>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::iau::light_year>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::mile>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::nautical_mile>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::iau::parsec>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::typographic::pica_comp>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::typographic::pica_prn>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::typographic::point_comp>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::typographic::point_prn>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::imperial::rod>(meter) << '\n';
|
||||||
|
std::cout << " = " << quantity_cast<si::international::yard>(meter) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcs_comparison()
|
||||||
|
{
|
||||||
|
using namespace units::isq::si;
|
||||||
|
|
||||||
|
std::cout << "\nA distinct unit for each type is efficient and accurate\n"
|
||||||
|
"when adding two values of the same very big\n"
|
||||||
|
"or very small type:\n\n";
|
||||||
|
|
||||||
|
length<femtometre, float> L1A = 2._q_fm;
|
||||||
|
length<femtometre, float> L2A = 3._q_fm;
|
||||||
|
length<femtometre, float> LrA = L1A + L2A;
|
||||||
|
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, LrA);
|
||||||
|
|
||||||
|
std::cout << "The single unit method must convert large\n"
|
||||||
|
"or small values in other units to the base unit.\n"
|
||||||
|
"This is both inefficient and inaccurate\n\n";
|
||||||
|
|
||||||
|
length<metre, float> L1B = L1A;
|
||||||
|
length<metre, float> L2B = L2A;
|
||||||
|
length<metre, float> LrB = L1B + L2B;
|
||||||
|
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1B, L2B, LrB);
|
||||||
|
|
||||||
|
std::cout << "In multiplication and division:\n\n";
|
||||||
|
|
||||||
|
area<square_femtometre, float> ArA = L1A * L2A;
|
||||||
|
fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1A, L2A, ArA);
|
||||||
|
|
||||||
|
std::cout << "similar problems arise\n\n";
|
||||||
|
|
||||||
|
area<square_metre, float> ArB = L1B * L2B;
|
||||||
|
fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n", L1B, L2B, ArB);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << "This demo was originally posted on com.lang.c++.moderated in 2006\n";
|
||||||
|
std::cout << "http://compgroups.net/comp.lang.c++.moderated/dimensional-analysis-units/51712\n";
|
||||||
|
std::cout << "Here converted to use mp-units library.\n\n";
|
||||||
|
|
||||||
|
simple_quantities();
|
||||||
|
quantities_with_typed_units();
|
||||||
|
calcs_comparison();
|
||||||
|
}
|
60
example/literals/conversion_factor.cpp
Normal file
60
example/literals/conversion_factor.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2020 Andy Little.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see http://www.gnu.org/licenses./
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <units/format.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
/*
|
||||||
|
get conversion factor from one dimensionally equivalent
|
||||||
|
quantity type to another
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<units::Quantity Target, units::Quantity Source>
|
||||||
|
requires units::equivalent<typename Source::dimension, typename Target::dimension>
|
||||||
|
inline constexpr std::common_type_t<typename Target::rep, typename Source::rep> conversion_factor(Target, Source)
|
||||||
|
{
|
||||||
|
// get quantities looking like inputs but with Q::rep that doesn't have narrowing conversion
|
||||||
|
typedef std::common_type_t<typename Target::rep, typename Source::rep> rep;
|
||||||
|
typedef units::quantity<typename Source::dimension, typename Source::unit, rep> source;
|
||||||
|
typedef units::quantity<typename Target::dimension, typename Target::unit, rep> target;
|
||||||
|
return target{source{1}}.number();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace units::isq::si;
|
||||||
|
|
||||||
|
std::cout << "conversion factor in mp-units...\n\n";
|
||||||
|
|
||||||
|
constexpr length<metre> lengthA = 2.0_q_m;
|
||||||
|
constexpr length<millimetre> lengthB = lengthA;
|
||||||
|
|
||||||
|
std::cout << fmt::format("lengthA( {} ) and lengthB( {} )\n", lengthA, lengthB)
|
||||||
|
<< "represent the same length in different units.\n\n";
|
||||||
|
|
||||||
|
std::cout << fmt::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB);
|
||||||
|
|
||||||
|
std::cout << fmt::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n", lengthA, lengthB)
|
||||||
|
<< fmt::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
|
||||||
|
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
|
||||||
|
}
|
44
example/literals/experimental_angle.cpp
Normal file
44
example/literals/experimental_angle.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// 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/generic/angle.h>
|
||||||
|
#include <units/isq/si/energy.h>
|
||||||
|
#include <units/isq/si/force.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/torque.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace units::literals;
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
|
||||||
|
Torque auto torque = 20.0_q_Nm_per_rad;
|
||||||
|
Energy auto energy = 20.0_q_J;
|
||||||
|
|
||||||
|
units::Angle auto angle = energy / torque;
|
||||||
|
|
||||||
|
std::cout << angle << '\n';
|
||||||
|
}
|
99
example/literals/foot_pound_second.cpp
Normal file
99
example/literals/foot_pound_second.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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/format.h>
|
||||||
|
#include <units/isq/si/fps/density.h>
|
||||||
|
#include <units/isq/si/fps/length.h>
|
||||||
|
#include <units/isq/si/fps/mass.h>
|
||||||
|
#include <units/isq/si/fps/power.h>
|
||||||
|
#include <units/isq/si/fps/speed.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/mass.h>
|
||||||
|
#include <units/isq/si/power.h>
|
||||||
|
#include <units/isq/si/speed.h>
|
||||||
|
#include <units/isq/si/volume.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
|
||||||
|
// Some basic specs for the warship
|
||||||
|
struct Ship {
|
||||||
|
si::fps::length<si::fps::foot> length;
|
||||||
|
si::fps::length<si::fps::foot> draft;
|
||||||
|
si::fps::length<si::fps::foot> beam;
|
||||||
|
|
||||||
|
si::fps::speed<si::fps::foot_per_second> speed;
|
||||||
|
si::fps::mass<si::fps::pound> mass;
|
||||||
|
|
||||||
|
si::fps::length<si::fps::inch> mainGuns;
|
||||||
|
si::fps::mass<si::fps::pound> shellMass;
|
||||||
|
si::fps::speed<si::fps::foot_per_second> shellSpeed;
|
||||||
|
si::fps::power<si::fps::foot_poundal_per_second> power;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Print 'a' in its current units and print its value cast to the units in each of Args
|
||||||
|
template<class ...Args, units::Quantity Q>
|
||||||
|
auto fmt_line(const Q a)
|
||||||
|
{
|
||||||
|
return fmt::format("{:22}", a) + (fmt::format(",{:20}", units::quantity_cast<Args>(a)) + ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the ship details in the units as defined in the Ship struct, in other si::imperial units, and in SI
|
||||||
|
void print_details(std::string_view description, const Ship& ship)
|
||||||
|
{
|
||||||
|
using namespace units::isq::si::fps::literals;
|
||||||
|
const auto waterDensity = 62.4_q_lb_per_ft3;
|
||||||
|
std::cout << fmt::format("{}\n", description);
|
||||||
|
std::cout << fmt::format("{:20} : {}\n", "length", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length))
|
||||||
|
<< fmt::format("{:20} : {}\n", "draft", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
|
||||||
|
<< fmt::format("{:20} : {}\n", "beam", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam))
|
||||||
|
<< fmt::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
|
||||||
|
<< fmt::format("{:20} : {}\n", "speed", fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
|
||||||
|
<< fmt::format("{:20} : {}\n", "power", fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power))
|
||||||
|
<< fmt::format("{:20} : {}\n", "main guns", fmt_line<si::fps::length<si::fps::inch>, si::length<si::millimetre>>(ship.mainGuns))
|
||||||
|
<< fmt::format("{:20} : {}\n", "fire shells weighing",fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::kilogram>>(ship.shellMass))
|
||||||
|
<< fmt::format("{:20} : {}\n", "fire shells at",fmt_line<si::fps::speed<si::fps::mile_per_hour>, si::speed<si::kilometre_per_hour>>(ship.shellSpeed))
|
||||||
|
<< fmt::format("{:20} : {}\n", "volume underwater", fmt_line<si::volume<si::cubic_metre>, si::volume<si::litre>>(ship.mass / waterDensity));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
using namespace units::isq::si::fps::literals;
|
||||||
|
|
||||||
|
// KMS Bismark, using the units the Germans would use, taken from Wiki
|
||||||
|
auto bismark = Ship{.length{251._q_m}, .draft{9.3_q_m}, .beam{36_q_m}, .speed{56_q_km_per_h}, .mass{50'300_q_t}, .mainGuns{380_q_mm}, .shellMass{800_q_kg}, .shellSpeed{820._q_m_per_s}, .power{110.45_q_kW}};
|
||||||
|
|
||||||
|
// USS Iowa, using units from the foot-pound-second system
|
||||||
|
auto iowa = Ship{.length{860._q_ft}, .draft{37._q_ft + 2._q_in}, .beam{108._q_ft + 2._q_in}, .speed{33_q_knot}, .mass{57'540_q_lton}, .mainGuns{16_q_in}, .shellMass{2700_q_lb}, .shellSpeed{2690._q_ft_per_s}, .power{212'000_q_hp}};
|
||||||
|
|
||||||
|
// HMS King George V, using units from the foot-pound-second system
|
||||||
|
auto kgv = Ship{.length{745.1_q_ft}, .draft{33._q_ft + 7.5_q_in}, .beam{103.2_q_ft + 2.5_q_in}, .speed{28.3_q_knot}, .mass{42'245_q_lton}, .mainGuns{14_q_in}, .shellMass{1'590_q_lb}, .shellSpeed{2483._q_ft_per_s}, .power{110'000_q_hp}};
|
||||||
|
|
||||||
|
print_details("KMS Bismark, defined in appropriate units from the SI system", bismark);
|
||||||
|
std::cout << "\n\n";
|
||||||
|
print_details("USS Iowa, defined in appropriate units foot-pound-second system", iowa);
|
||||||
|
std::cout << "\n\n";
|
||||||
|
print_details("HMS King George V, defined in appropriate units foot-pound-second system", kgv);
|
||||||
|
}
|
63
example/literals/geographic.cpp
Normal file
63
example/literals/geographic.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// 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 "geographic.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include <numbers>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
inline constexpr auto earth_radius = 6371._q_km;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace geographic {
|
||||||
|
|
||||||
|
distance spherical_distance(position from, position to)
|
||||||
|
{
|
||||||
|
using rep = std::common_type_t<latitude::value_type, longitude::value_type>;
|
||||||
|
constexpr auto p = std::numbers::pi_v<rep> / 180;
|
||||||
|
const auto lat1 = from.lat.value() * p;
|
||||||
|
const auto lon1 = from.lon.value() * p;
|
||||||
|
const auto lat2 = to.lat.value() * p;
|
||||||
|
const auto lon2 = to.lon.value() * p;
|
||||||
|
|
||||||
|
using std::sin, std::cos, std::asin, std::sqrt;
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Great-circle_distance#Formulae
|
||||||
|
if constexpr (sizeof(rep) >= 8) {
|
||||||
|
// spherical law of cosines
|
||||||
|
const auto central_angle = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1));
|
||||||
|
// const auto central_angle = 2 * asin(sqrt(0.5 - cos(lat2 - lat1) / 2 + cos(lat1) * cos(lat2) * (1 - cos(lon2 - lon1)) / 2));
|
||||||
|
return distance(earth_radius * central_angle);
|
||||||
|
} else {
|
||||||
|
// the haversine formula
|
||||||
|
const auto sin_lat = sin(lat2 - lat1) / 2;
|
||||||
|
const auto sin_lon = sin(lon2 - lon1) / 2;
|
||||||
|
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
|
||||||
|
return distance(earth_radius * central_angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geographic
|
139
example/literals/geographic.h
Normal file
139
example/literals/geographic.h
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// 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/isq/si/length.h>
|
||||||
|
#include <units/quantity_kind.h>
|
||||||
|
|
||||||
|
UNITS_DIAGNOSTIC_PUSH
|
||||||
|
UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||||
|
#include <fmt/format.h>
|
||||||
|
UNITS_DIAGNOSTIC_POP
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
// IWYU pragma: begin_exports
|
||||||
|
#include <compare>
|
||||||
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
namespace geographic {
|
||||||
|
|
||||||
|
template<typename Derived, typename Rep>
|
||||||
|
struct coordinate {
|
||||||
|
using value_type = Rep;
|
||||||
|
constexpr explicit coordinate(value_type v) : value_(v) {}
|
||||||
|
value_type value() const { return value_; }
|
||||||
|
auto operator<=>(const coordinate&) const = default;
|
||||||
|
private:
|
||||||
|
value_type value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct latitude : coordinate<struct latitude_, double> {
|
||||||
|
using coordinate::coordinate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct longitude : coordinate<struct longitude_, double> {
|
||||||
|
using coordinate::coordinate;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class CharT, class Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const latitude& lat)
|
||||||
|
{
|
||||||
|
if (lat.value() > 0)
|
||||||
|
return os << "N" << lat.value();
|
||||||
|
else
|
||||||
|
return os << "S" << -lat.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class CharT, class Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const longitude& lon)
|
||||||
|
{
|
||||||
|
if (lon.value() > 0)
|
||||||
|
return os << "E" << lon.value();
|
||||||
|
else
|
||||||
|
return os << "W" << -lon.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline namespace literals {
|
||||||
|
|
||||||
|
constexpr auto operator"" _N(unsigned long long v) { return latitude(static_cast<latitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _N(long double v) { return latitude(static_cast<latitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _S(unsigned long long v) { return latitude(-static_cast<latitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _S(long double v) { return latitude(-static_cast<latitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _E(unsigned long long v) { return longitude(static_cast<longitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _E(long double v) { return longitude(static_cast<longitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _W(unsigned long long v) { return longitude(-static_cast<longitude::value_type>(v)); }
|
||||||
|
constexpr auto operator"" _W(long double v) { return longitude(-static_cast<longitude::value_type>(v)); }
|
||||||
|
|
||||||
|
} // namespace literals
|
||||||
|
|
||||||
|
} // namespace geographic
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class std::numeric_limits<geographic::latitude> : public numeric_limits<geographic::latitude::value_type> {
|
||||||
|
static constexpr auto min() noexcept { return geographic::latitude(-90); }
|
||||||
|
static constexpr auto lowest() noexcept { return geographic::latitude(-90); }
|
||||||
|
static constexpr auto max() noexcept { return geographic::latitude(90); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class std::numeric_limits<geographic::longitude> : public numeric_limits<geographic::longitude::value_type> {
|
||||||
|
static constexpr auto min() noexcept { return geographic::longitude(-180); }
|
||||||
|
static constexpr auto lowest() noexcept { return geographic::longitude(-180); }
|
||||||
|
static constexpr auto max() noexcept { return geographic::longitude(180); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<geographic::latitude> : formatter<geographic::latitude::value_type> {
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(geographic::latitude lat, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
format_to(ctx.out(), lat.value() > 0 ? "N" : "S");
|
||||||
|
return formatter<geographic::latitude::value_type>::format(lat.value() > 0 ? lat.value() : -lat.value(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<geographic::longitude> : formatter<geographic::longitude::value_type> {
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(geographic::longitude lon, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
format_to(ctx.out(), lon.value() > 0 ? "E" : "W");
|
||||||
|
return formatter<geographic::longitude::value_type>::format(lon.value() > 0 ? lon.value() : -lon.value(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace geographic {
|
||||||
|
|
||||||
|
struct horizontal_kind : units::kind<horizontal_kind, units::isq::si::dim_length> {};
|
||||||
|
using distance = units::quantity_kind<horizontal_kind, units::isq::si::kilometre>;
|
||||||
|
|
||||||
|
struct position {
|
||||||
|
latitude lat;
|
||||||
|
longitude lon;
|
||||||
|
};
|
||||||
|
|
||||||
|
distance spherical_distance(position from, position to);
|
||||||
|
|
||||||
|
} // namespace geographic
|
202
example/literals/glide_computer_example.cpp
Normal file
202
example/literals/glide_computer_example.cpp
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// 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 "glide_computer.h"
|
||||||
|
#include <units/bits/external/hacks.h>
|
||||||
|
#include <units/chrono.h>
|
||||||
|
#include <units/generic/dimensionless.h>
|
||||||
|
#include <units/isq/si/international/length.h>
|
||||||
|
|
||||||
|
UNITS_DIAGNOSTIC_PUSH
|
||||||
|
UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||||
|
#include <fmt/format.h>
|
||||||
|
UNITS_DIAGNOSTIC_POP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace glide_computer;
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
auto get_gliders()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
UNITS_DIAGNOSTIC_PUSH
|
||||||
|
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
|
||||||
|
static const std::array gliders = {
|
||||||
|
glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}},
|
||||||
|
glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}},
|
||||||
|
glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}},
|
||||||
|
glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}};
|
||||||
|
UNITS_DIAGNOSTIC_POP
|
||||||
|
return gliders;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get_weather_conditions()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
static const std::array weather_conditions = {
|
||||||
|
std::pair("Good", weather{height(1900_q_m), rate_of_climb(4.3_q_m_per_s)}),
|
||||||
|
std::pair("Medium", weather{height(1550_q_m), rate_of_climb(2.8_q_m_per_s)}),
|
||||||
|
std::pair("Bad", weather{height(850_q_m), rate_of_climb(1.8_q_m_per_s)})};
|
||||||
|
return weather_conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get_waypoints()
|
||||||
|
{
|
||||||
|
using namespace geographic::literals;
|
||||||
|
using namespace units::isq::si::international::literals;
|
||||||
|
static const std::array waypoints = {
|
||||||
|
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16_q_ft)}, // N54°14'51.8" E18°40'28.2"
|
||||||
|
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115_q_ft)} // N53°31'27.9" E18°50'58.1"
|
||||||
|
};
|
||||||
|
return waypoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::ranges::forward_range R>
|
||||||
|
requires std::same_as<std::ranges::range_value_t<R>, glider>
|
||||||
|
void print(const R& gliders)
|
||||||
|
{
|
||||||
|
std::cout << "Gliders:\n";
|
||||||
|
std::cout << "========\n";
|
||||||
|
for (const auto& g : gliders) {
|
||||||
|
std::cout << "- Name: " << g.name << "\n";
|
||||||
|
std::cout << "- Polar:\n";
|
||||||
|
for (const auto& p : g.polar)
|
||||||
|
fmt::print(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::ranges::forward_range R>
|
||||||
|
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>
|
||||||
|
void print(const R& conditions)
|
||||||
|
{
|
||||||
|
std::cout << "Weather:\n";
|
||||||
|
std::cout << "========\n";
|
||||||
|
for (const auto& c : conditions) {
|
||||||
|
std::cout << "- " << c.first << "\n";
|
||||||
|
const auto& w = c.second;
|
||||||
|
std::cout << " * Cloud base: " << fmt::format("{:%.0Q %q}", w.cloud_base) << " AGL\n";
|
||||||
|
std::cout << " * Thermals strength: " << fmt::format("{:%.1Q %q}", w.thermal_strength) << "\n";
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::ranges::forward_range R>
|
||||||
|
requires std::same_as<std::ranges::range_value_t<R>, waypoint>
|
||||||
|
void print(const R& waypoints)
|
||||||
|
{
|
||||||
|
std::cout << "Waypoints:\n";
|
||||||
|
std::cout << "==========\n";
|
||||||
|
for (const auto& w : waypoints)
|
||||||
|
std::cout << fmt::format("- {}: {} {}, {:%.1Q %q}\n", w.name, w.pos.lat, w.pos.lon, w.alt);
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const task& t)
|
||||||
|
{
|
||||||
|
std::cout << "Task:\n";
|
||||||
|
std::cout << "=====\n";
|
||||||
|
|
||||||
|
std::cout << "- Start: " << t.get_start().name << "\n";
|
||||||
|
std::cout << "- Finish: " << t.get_finish().name << "\n";
|
||||||
|
std::cout << "- Length: " << fmt::format("{:%.1Q %q}", t.get_length()) << "\n";
|
||||||
|
|
||||||
|
std::cout << "- Legs: " << "\n";
|
||||||
|
for (const auto& l : t.get_legs())
|
||||||
|
std::cout << fmt::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const safety& s)
|
||||||
|
{
|
||||||
|
std::cout << "Safety:\n";
|
||||||
|
std::cout << "=======\n";
|
||||||
|
std::cout << "- Min AGL separation: " << fmt::format("{:%.0Q %q}", s.min_agl_height) << "\n";
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const aircraft_tow& tow)
|
||||||
|
{
|
||||||
|
std::cout << "Tow:\n";
|
||||||
|
std::cout << "====\n";
|
||||||
|
std::cout << "- Type: aircraft\n";
|
||||||
|
std::cout << "- Height: " << fmt::format("{:%.0Q %q}", tow.height_agl) << "\n";
|
||||||
|
std::cout << "- Performance: " << fmt::format("{:%.1Q %q}", tow.performance) << "\n";
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace si::literals;
|
||||||
|
|
||||||
|
const safety sfty = {height(300_q_m)};
|
||||||
|
const auto gliders = get_gliders();
|
||||||
|
const auto waypoints = get_waypoints();
|
||||||
|
const auto weather_conditions = get_weather_conditions();
|
||||||
|
const task t = {waypoints[0], waypoints[1], waypoints[0]};
|
||||||
|
const aircraft_tow tow = {height(400_q_m), rate_of_climb(1.6_q_m_per_s)};
|
||||||
|
// TODO use C++20 date library when available
|
||||||
|
// set `start_time` to 11:00 am today
|
||||||
|
const timestamp start_time(std::chrono::system_clock::now());
|
||||||
|
|
||||||
|
print(sfty);
|
||||||
|
print(gliders);
|
||||||
|
print(waypoints);
|
||||||
|
print(weather_conditions);
|
||||||
|
print(t);
|
||||||
|
print(tow);
|
||||||
|
|
||||||
|
for (const auto& g : gliders) {
|
||||||
|
for (const auto& c : weather_conditions) {
|
||||||
|
std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first;
|
||||||
|
std::cout << txt << "\n";
|
||||||
|
fmt::print("{0:=^{1}}\n\n", "", txt.size());
|
||||||
|
|
||||||
|
estimate(start_time, g, c.second, t, sfty, tow);
|
||||||
|
|
||||||
|
std::cout << "\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // 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";
|
||||||
|
}
|
||||||
|
}
|
100
example/literals/kalman_filter-alpha_beta_filter_example2.cpp
Normal file
100
example/literals/kalman_filter-alpha_beta_filter_example2.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// 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/format.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/speed.h>
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
/*
|
||||||
|
kalman filter tutorial
|
||||||
|
1d aircraft α-β filter example2 from https://www.kalmanfilter.net/alphabeta.html#ex2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<units::Quantity Q>
|
||||||
|
struct state_variable {
|
||||||
|
Q estimated_current_state;
|
||||||
|
Q predicted_next_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
|
||||||
|
constexpr auto radar_transmit_interval = 5.0_q_s;
|
||||||
|
constexpr double kalman_range_gain = 0.2;
|
||||||
|
constexpr double kalman_speed_gain = 0.1;
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
state_variable<si::length<si::metre>> range;
|
||||||
|
state_variable<si::speed<si::metre_per_second>> speed;
|
||||||
|
|
||||||
|
constexpr void estimate(const state& previous_state, const si::length<si::metre>& measurement)
|
||||||
|
{
|
||||||
|
auto const innovation = measurement - previous_state.range.predicted_next_state;
|
||||||
|
range.estimated_current_state = previous_state.range.predicted_next_state + kalman_range_gain * innovation;
|
||||||
|
speed.estimated_current_state =
|
||||||
|
previous_state.speed.predicted_next_state + kalman_speed_gain * innovation / radar_transmit_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void predict()
|
||||||
|
{
|
||||||
|
range.predicted_next_state =
|
||||||
|
range.estimated_current_state + speed.estimated_current_state * radar_transmit_interval;
|
||||||
|
speed.predicted_next_state = speed.estimated_current_state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << "\n\n1d aircraft α-β filter example2 from https://www.kalmanfilter.net/alphabeta.html#ex2";
|
||||||
|
std::cout << "\n\n";
|
||||||
|
|
||||||
|
constexpr auto measurements = std::array{0.0_q_m, // N.B measurement[0] is unknown and unused
|
||||||
|
30110.0_q_m, 30265.0_q_m, 30740.0_q_m, 30750.0_q_m, 31135.0_q_m,
|
||||||
|
31015.0_q_m, 31180.0_q_m, 31610.0_q_m, 31960.0_q_m, 31865.0_q_m};
|
||||||
|
|
||||||
|
constexpr auto num_measurements = measurements.size();
|
||||||
|
|
||||||
|
std::array<state, num_measurements> track;
|
||||||
|
// We need an initial estimate of track[0] as there is no previous state to get a prediction from
|
||||||
|
track[0].range.estimated_current_state = 30'000_q_m;
|
||||||
|
track[0].speed.estimated_current_state = 40.0_q_m_per_s;
|
||||||
|
|
||||||
|
for (auto n = 0U; n < num_measurements; ++n) {
|
||||||
|
if (n > 0) {
|
||||||
|
track[n].estimate(track[n - 1], measurements[n]);
|
||||||
|
}
|
||||||
|
track[n].predict();
|
||||||
|
|
||||||
|
std::cout << fmt::format("measurement[{}] = {:.0}\n", n, measurements[n]);
|
||||||
|
std::cout << fmt::format("range.estimated_current_state[{}] = {:.1}\n", n, track[n].range.estimated_current_state);
|
||||||
|
std::cout << fmt::format("speed.estimated_current_state[{}] = {:.1}\n", n, track[n].speed.estimated_current_state);
|
||||||
|
std::cout << fmt::format("range.predicted_next_state[{}] = {:.1}\n", n, track[n].range.predicted_next_state);
|
||||||
|
std::cout << fmt::format("speed.predicted_next_state[{}] = {:.1}\n\n", n, track[n].speed.predicted_next_state);
|
||||||
|
}
|
||||||
|
}
|
361
example/literals/linear_algebra.cpp
Normal file
361
example/literals/linear_algebra.cpp
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
// 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/isq/si/energy.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/force.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/format.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <linear_algebra.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace STD_LA {
|
||||||
|
|
||||||
|
template<class ET, class OT>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const vector<ET, OT>& v)
|
||||||
|
{
|
||||||
|
os << "|";
|
||||||
|
for (auto i = 0U; i < v.size(); ++i) {
|
||||||
|
os << fmt::format(" {:>9}", v(i));
|
||||||
|
}
|
||||||
|
os << " |";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ET, class OT>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const matrix<ET, OT>& v)
|
||||||
|
{
|
||||||
|
for (auto i = 0U; i < v.rows(); ++i) {
|
||||||
|
os << "|";
|
||||||
|
for (auto j = 0U; j < v.columns(); ++j) {
|
||||||
|
os << fmt::format(" {:>9}", v(i, j));
|
||||||
|
}
|
||||||
|
os << (i != v.rows() - 1U ? " |\n" : " |");
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace STD_LA
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
|
||||||
|
template<typename Rep = double>
|
||||||
|
using vector = std::math::fs_vector<Rep, 3>;
|
||||||
|
|
||||||
|
template<typename Rep = double>
|
||||||
|
using matrix = std::math::fs_matrix<Rep, 3, 3>;
|
||||||
|
|
||||||
|
|
||||||
|
void vector_of_quantity_add()
|
||||||
|
{
|
||||||
|
std::cout << "\nvector_of_quantity_add:\n";
|
||||||
|
|
||||||
|
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m };
|
||||||
|
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
|
||||||
|
vector<si::length<si::kilometre>> t = { 3_q_km, 2_q_km, 1_q_km };
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
std::cout << "t = " << t << "\n";
|
||||||
|
|
||||||
|
std::cout << "v + u = " << v + u << "\n";
|
||||||
|
std::cout << "v + t = " << v + t << "\n";
|
||||||
|
std::cout << "t[m] = " << vector<si::length<si::metre>>(t) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void vector_of_quantity_multiply_same()
|
||||||
|
{
|
||||||
|
std::cout << "\nvector_of_quantity_multiply_same:\n";
|
||||||
|
|
||||||
|
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m };
|
||||||
|
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u = " << v * u << "\n";
|
||||||
|
std::cout << "2_q_m * v = " << 2._q_m * v << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void vector_of_quantity_multiply_different()
|
||||||
|
{
|
||||||
|
std::cout << "\nvector_of_quantity_multiply_different:\n";
|
||||||
|
|
||||||
|
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N };
|
||||||
|
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u = " << v * u << "\n";
|
||||||
|
std::cout << "2_q_N * u = " << 2._q_N * u << "\n";
|
||||||
|
std::cout << "2 * u = " << 2 * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void vector_of_quantity_divide_by_scalar()
|
||||||
|
{
|
||||||
|
std::cout << "\nvector_of_quantity_divide_by_scalar:\n";
|
||||||
|
|
||||||
|
vector<si::length<si::metre>> v = { 4_q_m, 8_q_m, 12_q_m };
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when bug in the LA is fixed
|
||||||
|
// std::cout << "v / 2_q_s = " << v / 2_q_s << "\n";
|
||||||
|
// std::cout << "v / 2 = " << v / 2 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void vector_of_quantity_tests()
|
||||||
|
{
|
||||||
|
vector_of_quantity_add();
|
||||||
|
vector_of_quantity_multiply_same();
|
||||||
|
vector_of_quantity_multiply_different();
|
||||||
|
vector_of_quantity_divide_by_scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_of_quantity_add()
|
||||||
|
{
|
||||||
|
std::cout << "\nmatrix_of_quantity_add:\n";
|
||||||
|
|
||||||
|
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
|
||||||
|
matrix<si::length<si::metre>> u = {{ 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }};
|
||||||
|
matrix<si::length<si::millimetre>> t = {{ 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }};
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
std::cout << "t =\n" << t << "\n";
|
||||||
|
|
||||||
|
std::cout << "v + u =\n" << v + u << "\n";
|
||||||
|
std::cout << "v + t =\n" << v + t << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when fixed in the LA lib
|
||||||
|
// std::cout << "v[mm] =\n" << matrix<si::length<si::millimetre>>(v) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_of_quantity_multiply_same()
|
||||||
|
{
|
||||||
|
std::cout << "\nmatrix_of_quantity_multiply_same:\n";
|
||||||
|
|
||||||
|
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
|
||||||
|
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u =\n" << v * u << "\n";
|
||||||
|
std::cout << "2_q_m * u =\n" << 2._q_m * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_of_quantity_multiply_different()
|
||||||
|
{
|
||||||
|
std::cout << "\nmatrix_of_quantity_multiply_different:\n";
|
||||||
|
|
||||||
|
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N };
|
||||||
|
matrix<si::length<si::metre>> u = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u =\n" << v * u << "\n";
|
||||||
|
std::cout << "2_q_N * u =\n" << 2._q_N * u << "\n";
|
||||||
|
std::cout << "2 * u =\n" << 2 * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_of_quantity_divide_by_scalar()
|
||||||
|
{
|
||||||
|
std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n";
|
||||||
|
|
||||||
|
matrix<si::length<si::metre>> v = {{ 2_q_m, 4_q_m, 6_q_m }, { 4_q_m, 6_q_m, 8_q_m }, { 8_q_m, 4_q_m, 2_q_m }};
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when bug in the LA is fixed
|
||||||
|
// std::cout << "v / 2_q_s =\n" << v / 2_q_s << "\n";
|
||||||
|
// std::cout << "v / 2 =\n" << v / 2 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_of_quantity_tests()
|
||||||
|
{
|
||||||
|
matrix_of_quantity_add();
|
||||||
|
matrix_of_quantity_multiply_same();
|
||||||
|
matrix_of_quantity_multiply_different();
|
||||||
|
matrix_of_quantity_divide_by_scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<units::Unit U = si::metre, units::Representation Rep = double>
|
||||||
|
using length_v = si::length<U, vector<Rep>>;
|
||||||
|
|
||||||
|
template<units::Unit U = si::newton, units::Representation Rep = double>
|
||||||
|
using force_v = si::force<U, vector<Rep>>;
|
||||||
|
|
||||||
|
void quantity_of_vector_add()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_vector_add:\n";
|
||||||
|
|
||||||
|
length_v<> v(vector<>{ 1, 2, 3 });
|
||||||
|
length_v<> u(vector<>{ 3, 2, 1 });
|
||||||
|
length_v<si::kilometre> t(vector<>{ 3, 2, 1 });
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
std::cout << "t = " << t << "\n";
|
||||||
|
|
||||||
|
std::cout << "v + u = " << v + u << "\n";
|
||||||
|
std::cout << "v + t = " << v + t << "\n";
|
||||||
|
std::cout << "t[m] = " << quantity_cast<si::metre>(t) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_vector_multiply_same()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_vector_multiply_same:\n";
|
||||||
|
|
||||||
|
length_v<> v(vector<>{ 1, 2, 3 });
|
||||||
|
length_v<> u(vector<>{ 3, 2, 1 });
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u = " << v * u << "\n";
|
||||||
|
std::cout << "2_q_m * v = " << 2._q_m * v << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_vector_multiply_different()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_vector_multiply_different:\n";
|
||||||
|
|
||||||
|
force_v<> v(vector<>{ 1, 2, 3 });
|
||||||
|
length_v<> u(vector<>{ 3, 2, 1 });
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
std::cout << "u = " << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u = " << v * u << "\n";
|
||||||
|
std::cout << "2_q_N * u = " << 2._q_N * u << "\n";
|
||||||
|
std::cout << "2 * u = " << 2 * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_vector_divide_by_scalar()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_vector_divide_by_scalar:\n";
|
||||||
|
|
||||||
|
length_v<> v(vector<>{ 4, 8, 12 });
|
||||||
|
|
||||||
|
std::cout << "v = " << v << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when bug in the LA is fixed
|
||||||
|
// std::cout << "v / 2_q_s = " << v / 2_q_s << "\n";
|
||||||
|
// std::cout << "v / 2 = " << v / 2 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_vector_tests()
|
||||||
|
{
|
||||||
|
quantity_of_vector_add();
|
||||||
|
quantity_of_vector_multiply_same();
|
||||||
|
quantity_of_vector_multiply_different();
|
||||||
|
quantity_of_vector_divide_by_scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<units::Unit U = si::metre, units::Representation Rep = double>
|
||||||
|
using length_m = si::length<U, matrix<Rep>>;
|
||||||
|
|
||||||
|
void quantity_of_matrix_add()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_matrix_add:\n";
|
||||||
|
|
||||||
|
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
|
||||||
|
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
|
||||||
|
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
std::cout << "t =\n" << t << "\n";
|
||||||
|
|
||||||
|
std::cout << "v + u =\n" << v + u << "\n";
|
||||||
|
std::cout << "v + t =\n" << v + t << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when fixed in the LA lib
|
||||||
|
// std::cout << "v[mm] =\n" << matrix<si::length<si::millimetre>>(v) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_matrix_multiply_same()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_matrix_multiply_same:\n";
|
||||||
|
|
||||||
|
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
|
||||||
|
length_v<> u(vector<>{ 3, 2, 1 });
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u =\n" << v * u << "\n";
|
||||||
|
std::cout << "2_q_m * u =\n" << 2._q_m * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_matrix_multiply_different()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_matrix_multiply_different:\n";
|
||||||
|
|
||||||
|
force_v<> v(vector<>{ 1, 2, 3 });
|
||||||
|
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
std::cout << "u =\n" << u << "\n";
|
||||||
|
|
||||||
|
std::cout << "v * u =\n" << v * u << "\n";
|
||||||
|
std::cout << "2_q_N * u =\n" << 2._q_N * u << "\n";
|
||||||
|
std::cout << "2 * u =\n" << 2 * u << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_matrix_divide_by_scalar()
|
||||||
|
{
|
||||||
|
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
|
||||||
|
|
||||||
|
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }});
|
||||||
|
|
||||||
|
std::cout << "v =\n" << v << "\n";
|
||||||
|
|
||||||
|
// TODO Uncomment when bug in the LA is fixed
|
||||||
|
// std::cout << "v / 2_q_s =\n" << v / 2_q_s << "\n";
|
||||||
|
// std::cout << "v / 2 =\n" << v / 2 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void quantity_of_matrix_tests()
|
||||||
|
{
|
||||||
|
quantity_of_matrix_add();
|
||||||
|
quantity_of_matrix_multiply_same();
|
||||||
|
quantity_of_matrix_multiply_different();
|
||||||
|
quantity_of_matrix_divide_by_scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
vector_of_quantity_tests();
|
||||||
|
matrix_of_quantity_tests();
|
||||||
|
quantity_of_vector_tests();
|
||||||
|
quantity_of_matrix_tests();
|
||||||
|
}
|
104
example/literals/total_energy.cpp
Normal file
104
example/literals/total_energy.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// 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/isq/natural/natural.h>
|
||||||
|
#include <units/isq/si/energy.h>
|
||||||
|
#include <units/isq/si/mass.h>
|
||||||
|
#include <units/isq/si/momentum.h>
|
||||||
|
#include <units/isq/si/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/constants.h>
|
||||||
|
#include <units/math.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
Energy auto total_energy(Momentum auto p, Mass auto m, Speed auto c)
|
||||||
|
{
|
||||||
|
return sqrt(pow<2>(p * c) + pow<2>(m * pow<2>(c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void si_example()
|
||||||
|
{
|
||||||
|
using namespace units::isq::si;
|
||||||
|
using GeV = gigaelectronvolt;
|
||||||
|
|
||||||
|
constexpr Speed auto c = si2019::speed_of_light<>;
|
||||||
|
|
||||||
|
std::cout << "\n*** SI units (c = " << c << ") ***\n";
|
||||||
|
|
||||||
|
const Momentum auto p = 4._q_GeV / c;
|
||||||
|
const Mass auto m = 3._q_GeV / pow<2>(c);
|
||||||
|
const Energy auto E = total_energy(p, m, c);
|
||||||
|
|
||||||
|
std::cout << "[in GeV]\n"
|
||||||
|
<< "p = " << p << "\n"
|
||||||
|
<< "m = " << m << "\n"
|
||||||
|
<< "E = " << E << "\n";
|
||||||
|
|
||||||
|
const momentum<kilogram_metre_per_second> p_si = p;
|
||||||
|
const mass<kilogram> m_si = m;
|
||||||
|
const energy<joule> E_si = total_energy(p_si, m_si, c);
|
||||||
|
|
||||||
|
std::cout << "\n[in SI units]\n"
|
||||||
|
<< "p = " << p_si << "\n"
|
||||||
|
<< "m = " << m_si << "\n"
|
||||||
|
<< "E = " << E_si << "\n";
|
||||||
|
|
||||||
|
std::cout << "\n[converted from SI units back to GeV]\n"
|
||||||
|
<< "E = " << quantity_cast<GeV>(E_si) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void natural_example()
|
||||||
|
{
|
||||||
|
using namespace units::isq::natural;
|
||||||
|
using GeV = gigaelectronvolt;
|
||||||
|
|
||||||
|
constexpr Speed auto c = speed_of_light<>;
|
||||||
|
const momentum<GeV> p(4);
|
||||||
|
const mass<GeV> m(3);
|
||||||
|
const Energy auto E = total_energy(p, m, c);
|
||||||
|
|
||||||
|
std::cout << "\n*** Natural units (c = " << c << ") ***\n"
|
||||||
|
<< "p = " << p << "\n"
|
||||||
|
<< "m = " << m << "\n"
|
||||||
|
<< "E = " << E << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
si_example();
|
||||||
|
natural_example();
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex) {
|
||||||
|
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cerr << "Unhandled unknown exception caught\n";
|
||||||
|
}
|
||||||
|
}
|
72
example/literals/unknown_dimension.cpp
Normal file
72
example/literals/unknown_dimension.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// 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/isq/si/length.h>
|
||||||
|
#include <units/isq/si/speed.h> // IWYU pragma: keep
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<units::isq::Length D, units::isq::Time T>
|
||||||
|
constexpr units::isq::Speed auto avg_speed(D d, T t)
|
||||||
|
{
|
||||||
|
return d / t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace units::isq;
|
||||||
|
using namespace units::isq::si::literals;
|
||||||
|
|
||||||
|
Length auto d1 = 123_q_m;
|
||||||
|
Time auto t1 = 10_q_s;
|
||||||
|
Speed auto v1 = avg_speed(d1, t1);
|
||||||
|
|
||||||
|
auto temp1 = v1 * 50_q_m; // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
|
||||||
|
Speed auto v2 = temp1 / 100_q_m; // back to known dimensions again
|
||||||
|
Length auto d2 = v2 * 60_q_s;
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // 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";
|
||||||
|
}
|
||||||
|
}
|
60
example/references/CMakeLists.txt
Normal file
60
example/references/CMakeLists.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
|
#
|
||||||
|
# add_example(target <depependencies>...)
|
||||||
|
#
|
||||||
|
function(add_example target)
|
||||||
|
add_executable(${target}-references ${target}.cpp)
|
||||||
|
target_link_libraries(${target}-references PRIVATE ${ARGN})
|
||||||
|
target_compile_definitions(${target}-references PRIVATE UNITS_REFERENCES)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
||||||
|
add_example(box_example mp-units::core-fmt mp-units::si)
|
||||||
|
add_example(capacitor_time_curve mp-units::core-io mp-units::si)
|
||||||
|
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-us)
|
||||||
|
add_example(conversion_factor mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
add_example(custom_systems mp-units::core-io mp-units::si)
|
||||||
|
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
|
||||||
|
add_example(kalman_filter-alpha_beta_filter_example2 mp-units::core-fmt mp-units::si)
|
||||||
|
add_example(measurement mp-units::core-io mp-units::si)
|
||||||
|
add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural)
|
||||||
|
add_example(unknown_dimension mp-units::core-io mp-units::si)
|
||||||
|
|
||||||
|
if(NOT UNITS_LIBCXX)
|
||||||
|
add_executable(glide_computer-references
|
||||||
|
geographic.cpp geographic.h
|
||||||
|
glide_computer.cpp glide_computer.h
|
||||||
|
glide_computer_example.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(glide_computer-references PRIVATE mp-units::core-fmt mp-units::si mp-units::si-international)
|
||||||
|
target_include_directories(glide_computer-references PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
target_compile_definitions(glide_computer-references PRIVATE UNITS_REFERENCES)
|
||||||
|
|
||||||
|
find_package(linear_algebra CONFIG REQUIRED)
|
||||||
|
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
target_link_libraries(linear_algebra-references PRIVATE linear_algebra::linear_algebra)
|
||||||
|
endif()
|
113
example/references/custom_systems.cpp
Normal file
113
example/references/custom_systems.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// 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/base_dimension.h>
|
||||||
|
#include <units/isq/si/prefixes.h>
|
||||||
|
#include <units/quantity.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <units/unit.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
using namespace units;
|
||||||
|
|
||||||
|
namespace fps {
|
||||||
|
|
||||||
|
struct foot : named_unit<foot, "ft", no_prefix> {};
|
||||||
|
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {};
|
||||||
|
|
||||||
|
struct dim_length : base_dimension<"L", foot> {};
|
||||||
|
|
||||||
|
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||||
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
|
} // namespace fps
|
||||||
|
|
||||||
|
namespace si {
|
||||||
|
|
||||||
|
struct metre : named_unit<metre, "m", units::isq::si::prefix> {};
|
||||||
|
struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {};
|
||||||
|
|
||||||
|
struct dim_length : base_dimension<"L", metre> {};
|
||||||
|
|
||||||
|
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||||
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
|
namespace fps {
|
||||||
|
|
||||||
|
struct foot : named_scaled_unit<foot, "ft", no_prefix, ratio(3'048, 1'000, -1), metre> {};
|
||||||
|
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {};
|
||||||
|
|
||||||
|
struct dim_length : base_dimension<"L", foot> {};
|
||||||
|
|
||||||
|
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||||
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
|
} // namespace fps
|
||||||
|
} // namespace si
|
||||||
|
|
||||||
|
void conversions()
|
||||||
|
{
|
||||||
|
// constexpr auto fps_yard = fps::length<fps::yard>(1.);
|
||||||
|
// std::cout << quantity_cast<si::kilometre>(fps_yard) << "\n";
|
||||||
|
|
||||||
|
constexpr auto si_fps_yard = si::fps::length<si::fps::yard>(1.);
|
||||||
|
std::cout << quantity_cast<si::kilometre>(si_fps_yard) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void unknown_dimensions()
|
||||||
|
{
|
||||||
|
constexpr auto fps_yard = fps::length<fps::yard>(1.);
|
||||||
|
constexpr auto fps_area = quantity_cast<unknown_coherent_unit>(fps_yard * fps_yard);
|
||||||
|
std::cout << fps_yard << "\n";
|
||||||
|
std::cout << fps_area << "\n";
|
||||||
|
|
||||||
|
constexpr auto si_fps_yard = si::fps::length<si::fps::yard>(1.);
|
||||||
|
constexpr auto si_fps_area = quantity_cast<unknown_coherent_unit>(si_fps_yard * si_fps_yard);
|
||||||
|
std::cout << si_fps_yard << "\n";
|
||||||
|
std::cout << si_fps_area << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const ratio& r)
|
||||||
|
{
|
||||||
|
return os << "ratio{" << r.num << ", " << r.den << ", " << r.exp << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const U& u)
|
||||||
|
{
|
||||||
|
using unit_type = std::remove_cvref_t<decltype(u)>;
|
||||||
|
return os << unit_type::ratio << " x " << unit_type::reference::symbol.standard();
|
||||||
|
}
|
||||||
|
|
||||||
|
void what_is_your_ratio()
|
||||||
|
{
|
||||||
|
std::cout << "fps: " << fps::yard() << "\n";
|
||||||
|
std::cout << "si::fps: " << si::fps::yard() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
conversions();
|
||||||
|
unknown_dimensions();
|
||||||
|
what_is_your_ratio();
|
||||||
|
}
|
166
example/references/glide_computer.cpp
Normal file
166
example/references/glide_computer.cpp
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.
|
||||||
|
|
||||||
|
#include "glide_computer.h"
|
||||||
|
#include <numeric>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace glide_computer {
|
||||||
|
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
task::legs task::make_legs(const waypoints& wpts)
|
||||||
|
{
|
||||||
|
task::legs res;
|
||||||
|
res.reserve(wpts.size() - 1);
|
||||||
|
auto to_leg = [](const waypoint& w1, const waypoint& w2) { return task::leg(w1, w2); };
|
||||||
|
std::ranges::transform(wpts.cbegin(), prev(wpts.cend()), next(wpts.cbegin()), wpts.cend(), std::back_inserter(res), to_leg);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<distance> task::make_leg_total_distances(const legs& legs)
|
||||||
|
{
|
||||||
|
std::vector<distance> res;
|
||||||
|
res.reserve(legs.size());
|
||||||
|
auto to_length = [](const leg& l) { return l.get_length(); };
|
||||||
|
std::transform_inclusive_scan(legs.cbegin(), legs.cend(), std::back_inserter(res), std::plus(), to_length);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
altitude terrain_level_alt(const task& t, const flight_point& pos)
|
||||||
|
{
|
||||||
|
const task::leg& l = t.get_legs()[pos.leg_idx];
|
||||||
|
const height alt_diff = l.end().alt - l.begin().alt;
|
||||||
|
return l.begin().alt + alt_diff * ((pos.dist - t.get_leg_dist_offset(pos.leg_idx)) / l.get_length()).common();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns `x` of the intersection of a glide line and a terrain line.
|
||||||
|
// y = -x / glide_ratio + pos.alt;
|
||||||
|
// y = (finish_alt - ground_alt) / dist_to_finish * x + ground_alt + min_agl_height;
|
||||||
|
distance glide_distance(const flight_point& pos, const glider& g, const task& t, const safety& s, altitude ground_alt)
|
||||||
|
{
|
||||||
|
const auto dist_to_finish = t.get_length() - pos.dist;
|
||||||
|
return distance((ground_alt + s.min_agl_height - pos.alt).common() /
|
||||||
|
((ground_alt - t.get_finish().alt) / dist_to_finish - 1 / glide_ratio(g.polar[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace glide_computer;
|
||||||
|
|
||||||
|
void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point, const glide_computer::flight_point& new_point)
|
||||||
|
{
|
||||||
|
fmt::print(
|
||||||
|
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) |\n",
|
||||||
|
phase_name, quantity_cast<si::minute>(new_point.ts - point.ts), quantity_cast<si::minute>(new_point.ts - start_ts),
|
||||||
|
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
flight_point takeoff(timestamp start_ts, const task& t)
|
||||||
|
{
|
||||||
|
return {start_ts, t.get_start().alt};
|
||||||
|
}
|
||||||
|
|
||||||
|
flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow& at)
|
||||||
|
{
|
||||||
|
const duration d = (at.height_agl / at.performance).common();
|
||||||
|
const flight_point new_pos{pos.ts + d, pos.alt + at.height_agl, pos.leg_idx, pos.dist};
|
||||||
|
|
||||||
|
print("Tow", start_ts, pos, new_pos);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
flight_point circle(timestamp start_ts, const flight_point& pos, const glider& g, const weather& w, const task& t, height& height_to_gain)
|
||||||
|
{
|
||||||
|
const height h_agl = agl(pos.alt, terrain_level_alt(t, pos));
|
||||||
|
const height circling_height = std::min(w.cloud_base - h_agl, height_to_gain);
|
||||||
|
const rate_of_climb circling_rate = w.thermal_strength + g.polar[0].climb;
|
||||||
|
const duration d = (circling_height / circling_rate).common();
|
||||||
|
const flight_point new_pos{pos.ts + d, pos.alt + circling_height, pos.leg_idx, pos.dist};
|
||||||
|
|
||||||
|
height_to_gain -= circling_height;
|
||||||
|
|
||||||
|
print("Circle", start_ts, pos, new_pos);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
flight_point glide(timestamp start_ts, const flight_point& pos, const glider& g, const task& t, const safety& s)
|
||||||
|
{
|
||||||
|
const auto ground_alt = terrain_level_alt(t, pos);
|
||||||
|
const auto dist = glide_distance(pos, g, t, s, ground_alt);
|
||||||
|
const auto new_distance = pos.dist + dist;
|
||||||
|
const auto alt = ground_alt + s.min_agl_height;
|
||||||
|
const auto l3d = length_3d(dist, pos.alt - alt);
|
||||||
|
const duration d = l3d / g.polar[0].v.common();
|
||||||
|
const flight_point new_pos{pos.ts + d, terrain_level_alt(t, pos) + s.min_agl_height, t.get_leg_index(new_distance), new_distance};
|
||||||
|
|
||||||
|
print("Glide", start_ts, pos, new_pos);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
flight_point final_glide(timestamp start_ts, const flight_point& pos, const glider& g, const task& t)
|
||||||
|
{
|
||||||
|
const auto dist = t.get_length() - pos.dist;
|
||||||
|
const auto l3d = length_3d(dist, pos.alt - t.get_finish().alt);
|
||||||
|
const duration d = l3d / g.polar[0].v.common();
|
||||||
|
const flight_point new_pos{pos.ts + d, t.get_finish().alt, t.get_legs().size() - 1, pos.dist + dist};
|
||||||
|
|
||||||
|
print("Final Glide", start_ts, pos, new_pos);
|
||||||
|
return new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace glide_computer {
|
||||||
|
|
||||||
|
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s, const aircraft_tow& at)
|
||||||
|
{
|
||||||
|
fmt::print("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance", "Height");
|
||||||
|
fmt::print("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
|
||||||
|
|
||||||
|
// ready to takeoff
|
||||||
|
flight_point pos = takeoff(start_ts, t);
|
||||||
|
|
||||||
|
// estimate aircraft towing
|
||||||
|
pos = tow(start_ts, pos, at);
|
||||||
|
|
||||||
|
// estimate the altitude needed to reach the finish line from this place
|
||||||
|
const altitude final_glide_alt = t.get_finish().alt + height(t.get_length().common() / glide_ratio(g.polar[0]));
|
||||||
|
|
||||||
|
// how much height we still need to gain in the thermalls to reach the destination?
|
||||||
|
height height_to_gain = final_glide_alt - pos.alt;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// glide to the next thermall
|
||||||
|
pos = glide(start_ts, pos, g, t, s);
|
||||||
|
|
||||||
|
// circle in a thermall to gain height
|
||||||
|
pos = circle(start_ts, pos, g, w, t, height_to_gain);
|
||||||
|
} while (height_to_gain > height{});
|
||||||
|
|
||||||
|
// final glide
|
||||||
|
pos = final_glide(start_ts, pos, g, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace glide_computer
|
218
example/references/glide_computer.h
Normal file
218
example/references/glide_computer.h
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
// IWYU pragma: begin_exports
|
||||||
|
#include "geographic.h"
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/speed.h>
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/quantity_point_kind.h>
|
||||||
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
#include <units/format.h>
|
||||||
|
#include <units/math.h> // IWYU pragma: keep
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <iterator>
|
||||||
|
#include <ostream>
|
||||||
|
#include <ranges>
|
||||||
|
#include <string> // IWYU pragma: keep
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// An example of a really simplified tactical glide computer
|
||||||
|
// Simplifications:
|
||||||
|
// - glider 100% clean and with full factory performance (brand new painting)
|
||||||
|
// - no influence of the ballast (pilot weight, water, etc) to glider performance
|
||||||
|
// - only one point on a glider polar curve
|
||||||
|
// - no influence of bank angle (during circling) on a glider performance
|
||||||
|
// - no wind
|
||||||
|
// - constant thermals strength
|
||||||
|
// - thermals exactly where and when we need them ;-)
|
||||||
|
// - no airspaces
|
||||||
|
// - ground level changes linearly between waypoints
|
||||||
|
// - no ground obstacles (i.e. mountains) to pass
|
||||||
|
// - flight path exactly on a shortest possible line to destination
|
||||||
|
|
||||||
|
template<units::QuantityKind QK>
|
||||||
|
struct fmt::formatter<QK> : formatter<typename QK::quantity_type> {
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(const QK& v, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
return formatter<typename QK::quantity_type>::format(v.common(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace glide_computer {
|
||||||
|
|
||||||
|
template<units::QuantityKind QK1, units::QuantityKind QK2>
|
||||||
|
constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
|
||||||
|
requires(!units::QuantityKindRelatedTo<QK1, QK2>) && requires { lhs.common() / rhs.common();}
|
||||||
|
{
|
||||||
|
return lhs.common() / rhs.common();
|
||||||
|
}
|
||||||
|
|
||||||
|
// kinds
|
||||||
|
using horizontal_kind = geographic::horizontal_kind;
|
||||||
|
struct vertical_kind : units::kind<vertical_kind, units::isq::si::dim_length> {};
|
||||||
|
struct vertical_point_kind : units::point_kind<vertical_point_kind, vertical_kind> {};
|
||||||
|
struct velocity_kind : units::derived_kind<velocity_kind, horizontal_kind, units::isq::si::dim_speed> {};
|
||||||
|
struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, vertical_kind, units::isq::si::dim_speed> {};
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement
|
||||||
|
// length
|
||||||
|
using distance = units::quantity_kind<horizontal_kind, units::isq::si::kilometre>;
|
||||||
|
using height = units::quantity_kind<vertical_kind, units::isq::si::metre>;
|
||||||
|
using altitude = units::quantity_point_kind<vertical_point_kind, units::isq::si::metre>;
|
||||||
|
|
||||||
|
// time
|
||||||
|
using duration = units::isq::si::time<units::isq::si::second>;
|
||||||
|
using timestamp = units::quantity_point<units::isq::si::dim_time, units::isq::si::second>;
|
||||||
|
|
||||||
|
// speed
|
||||||
|
using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>;
|
||||||
|
using rate_of_climb = units::quantity_kind<rate_of_climb_kind, units::isq::si::metre_per_second>;
|
||||||
|
|
||||||
|
// text output
|
||||||
|
template<class CharT, class Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const altitude& a)
|
||||||
|
{
|
||||||
|
return os << a.relative().common() << " AMSL";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace glide_computer
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<glide_computer::altitude> : formatter<units::isq::si::length<units::isq::si::metre>> {
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(glide_computer::altitude a, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
formatter<units::isq::si::length<units::isq::si::metre>>::format(a.relative().common(), ctx);
|
||||||
|
return format_to(ctx.out(), " AMSL");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// definition of glide computer databases and utilities
|
||||||
|
namespace glide_computer {
|
||||||
|
|
||||||
|
struct glider {
|
||||||
|
struct polar_point {
|
||||||
|
velocity v;
|
||||||
|
rate_of_climb climb;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::array<polar_point, 1> polar;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr units::Dimensionless auto glide_ratio(const glider::polar_point& polar) { return polar.v / -polar.climb; }
|
||||||
|
|
||||||
|
struct weather {
|
||||||
|
height cloud_base;
|
||||||
|
rate_of_climb thermal_strength;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct waypoint {
|
||||||
|
std::string name;
|
||||||
|
geographic::position pos;
|
||||||
|
altitude alt;
|
||||||
|
};
|
||||||
|
|
||||||
|
class task {
|
||||||
|
public:
|
||||||
|
using waypoints = std::vector<waypoint>;
|
||||||
|
|
||||||
|
class leg {
|
||||||
|
const waypoint* begin_;
|
||||||
|
const waypoint* end_;
|
||||||
|
distance length_ = geographic::spherical_distance(begin().pos, end().pos);
|
||||||
|
public:
|
||||||
|
leg(const waypoint& b, const waypoint& e) noexcept: begin_(&b), end_(&e) {}
|
||||||
|
constexpr const waypoint& begin() const { return *begin_; };
|
||||||
|
constexpr const waypoint& end() const { return *end_; }
|
||||||
|
constexpr const distance get_length() const { return length_; }
|
||||||
|
};
|
||||||
|
using legs = std::vector<leg>;
|
||||||
|
|
||||||
|
template<std::ranges::input_range R>
|
||||||
|
requires std::same_as<std::ranges::range_value_t<R>, waypoint>
|
||||||
|
explicit task(const R& r) : waypoints_(std::ranges::begin(r), std::ranges::end(r)) {}
|
||||||
|
|
||||||
|
task(std::initializer_list<waypoint> wpts) : waypoints_(wpts) {}
|
||||||
|
|
||||||
|
const waypoints& get_waypoints() const { return waypoints_; }
|
||||||
|
const legs& get_legs() const { return legs_; }
|
||||||
|
|
||||||
|
const waypoint& get_start() const { return waypoints_.front(); }
|
||||||
|
const waypoint& get_finish() const { return waypoints_.back(); }
|
||||||
|
|
||||||
|
distance get_length() const { return length_; }
|
||||||
|
|
||||||
|
distance get_leg_dist_offset(std::size_t leg_index) const { return leg_index == 0 ? distance{} : leg_total_distances_[leg_index - 1]; }
|
||||||
|
std::size_t get_leg_index(distance dist) const
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t>(std::ranges::distance(leg_total_distances_.cbegin(), std::ranges::lower_bound(leg_total_distances_, dist)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
waypoints waypoints_;
|
||||||
|
legs legs_ = make_legs(waypoints_);
|
||||||
|
std::vector<distance> leg_total_distances_ = make_leg_total_distances(legs_);
|
||||||
|
distance length_ = leg_total_distances_.back();
|
||||||
|
|
||||||
|
static legs make_legs(const task::waypoints& wpts);
|
||||||
|
static std::vector<distance> make_leg_total_distances(const legs& legs);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct safety {
|
||||||
|
height min_agl_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct aircraft_tow {
|
||||||
|
height height_agl;
|
||||||
|
rate_of_climb performance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flight_point {
|
||||||
|
timestamp ts;
|
||||||
|
altitude alt;
|
||||||
|
std::size_t leg_idx = 0;
|
||||||
|
distance dist{};
|
||||||
|
};
|
||||||
|
|
||||||
|
altitude terrain_level_alt(const task& t, const flight_point& pos);
|
||||||
|
|
||||||
|
constexpr height agl(altitude glider_alt, altitude terrain_level) { return glider_alt - terrain_level; }
|
||||||
|
|
||||||
|
inline units::isq::si::length<units::isq::si::kilometre> length_3d(distance dist, height h)
|
||||||
|
{
|
||||||
|
// TODO support for hypot(q, q)
|
||||||
|
return sqrt(pow<2>(dist.common()) + pow<2>(h.common()));
|
||||||
|
}
|
||||||
|
|
||||||
|
distance glide_distance(const flight_point& pos, const glider& g, const task& t, const safety& s, altitude ground_alt);
|
||||||
|
|
||||||
|
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s, const aircraft_tow& at);
|
||||||
|
|
||||||
|
} // namespace glide_computer
|
157
example/references/measurement.cpp
Normal file
157
example/references/measurement.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// 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/isq/si/acceleration.h>
|
||||||
|
#include <units/isq/si/length.h>
|
||||||
|
#include <units/isq/si/speed.h>
|
||||||
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/quantity_io.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class measurement {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
measurement() = default;
|
||||||
|
|
||||||
|
constexpr explicit measurement(const value_type& val, const value_type& err = {}) :
|
||||||
|
value_(val),
|
||||||
|
uncertainty_(std::abs(err))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const value_type& value() const { return value_; }
|
||||||
|
constexpr const value_type& uncertainty() const { return uncertainty_; }
|
||||||
|
|
||||||
|
constexpr value_type relative_uncertainty() const { return uncertainty() / value(); }
|
||||||
|
constexpr value_type lower_bound() const { return value() - uncertainty(); }
|
||||||
|
constexpr value_type upper_bound() const { return value() + uncertainty(); }
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr measurement operator-() const { return measurement(-value(), uncertainty()); }
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator+(const measurement& lhs, const measurement& rhs)
|
||||||
|
{
|
||||||
|
return measurement(lhs.value() + rhs.value(), rss(lhs.uncertainty(), rhs.uncertainty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator-(const measurement& lhs, const measurement& rhs)
|
||||||
|
{
|
||||||
|
return measurement(lhs.value() - rhs.value(), rss(lhs.uncertainty(), rhs.uncertainty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator*(const measurement& lhs, const measurement& rhs)
|
||||||
|
{
|
||||||
|
const auto val = lhs.value() * rhs.value();
|
||||||
|
return measurement(val, val * rss(lhs.relative_uncertainty(), rhs.relative_uncertainty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator*(const measurement& lhs, const value_type& value)
|
||||||
|
{
|
||||||
|
const auto val = lhs.value() * value;
|
||||||
|
return measurement(val, val * lhs.relative_uncertainty());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator*(const value_type& value, const measurement& rhs)
|
||||||
|
{
|
||||||
|
const auto val = rhs.value() * value;
|
||||||
|
return measurement(val, val * rhs.relative_uncertainty());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator/(const measurement& lhs, const measurement& rhs)
|
||||||
|
{
|
||||||
|
const auto val = lhs.value() / rhs.value();
|
||||||
|
return measurement(val, val * rss(lhs.relative_uncertainty(), rhs.relative_uncertainty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator/(const measurement& lhs, const value_type& value)
|
||||||
|
{
|
||||||
|
const auto val = lhs.value() / value;
|
||||||
|
return measurement(val, val * lhs.relative_uncertainty());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] friend constexpr measurement operator/(const value_type& value, const measurement& rhs)
|
||||||
|
{
|
||||||
|
const auto val = value / rhs.value();
|
||||||
|
return measurement(val, val * rhs.relative_uncertainty());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto operator<=>(const measurement&) const = default;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const measurement& v)
|
||||||
|
{
|
||||||
|
return os << v.value() << " ± " << v.uncertainty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type value_{};
|
||||||
|
value_type uncertainty_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static_assert(units::Representation<measurement<double>>);
|
||||||
|
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace units::isq;
|
||||||
|
|
||||||
|
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 Speed auto v1 = a * t;
|
||||||
|
#if UNITS_DOWNCAST_MODE == 0
|
||||||
|
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::dim_speed, si::kilometre_per_hour>(v1) << '\n';
|
||||||
|
#else
|
||||||
|
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
||||||
|
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // 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";
|
||||||
|
}
|
||||||
|
}
|
@ -27,9 +27,11 @@ project(mp-units
|
|||||||
)
|
)
|
||||||
|
|
||||||
option(UNITS_AS_SYSTEM_HEADERS "Exports library as system headers" OFF)
|
option(UNITS_AS_SYSTEM_HEADERS "Exports library as system headers" OFF)
|
||||||
|
option(UNITS_REFERENCES "Enables definitions of Quantity References provided for quantities of various units" ON)
|
||||||
option(UNITS_LITERALS "Enables definitions of User Defined Literals (UDLs) provided for quantities of various units" OFF)
|
option(UNITS_LITERALS "Enables definitions of User Defined Literals (UDLs) provided for quantities of various units" OFF)
|
||||||
|
|
||||||
message(STATUS "UNITS_AS_SYSTEM_HEADERS: ${UNITS_AS_SYSTEM_HEADERS}")
|
message(STATUS "UNITS_AS_SYSTEM_HEADERS: ${UNITS_AS_SYSTEM_HEADERS}")
|
||||||
|
message(STATUS "UNITS_REFERENCES: ${UNITS_REFERENCES}")
|
||||||
message(STATUS "UNITS_LITERALS: ${UNITS_LITERALS}")
|
message(STATUS "UNITS_LITERALS: ${UNITS_LITERALS}")
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
@ -45,5 +45,8 @@ endfunction()
|
|||||||
#
|
#
|
||||||
function(add_units_system name)
|
function(add_units_system name)
|
||||||
add_units_module(${name} ${ARGN})
|
add_units_module(${name} ${ARGN})
|
||||||
target_compile_definitions(mp-units-${name} INTERFACE $<$<BOOL:${UNITS_LITERALS}>:UNITS_LITERALS>)
|
target_compile_definitions(mp-units-${name} INTERFACE
|
||||||
|
$<$<BOOL:${UNITS_REFERENCES}>:UNITS_REFERENCES>
|
||||||
|
$<$<BOOL:${UNITS_LITERALS}>:UNITS_LITERALS>
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -55,7 +55,10 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(mp-units-core INTERFACE $<$<BOOL:${UNITS_LITERALS}>:UNITS_LITERALS>)
|
target_compile_definitions(mp-units-core INTERFACE
|
||||||
|
$<$<BOOL:${UNITS_REFERENCES}>:UNITS_REFERENCES>
|
||||||
|
$<$<BOOL:${UNITS_LITERALS}>:UNITS_LITERALS>
|
||||||
|
)
|
||||||
|
|
||||||
if(DEFINED UNITS_DOWNCAST_MODE)
|
if(DEFINED UNITS_DOWNCAST_MODE)
|
||||||
set(downcast_mode_options OFF ON AUTO)
|
set(downcast_mode_options OFF ON AUTO)
|
||||||
|
@ -55,10 +55,14 @@ constexpr auto operator"" _q_rad(long double l) { return angle<radian, long doub
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto rad = reference<dim_angle<>, radian>{};
|
inline constexpr auto rad = reference<dim_angle<>, radian>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@ -68,6 +68,8 @@ constexpr auto operator"" _q_YBd(unsigned long long l) { gsl_ExpectsAudit(std::i
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto Bd = reference<dim_modulation_rate, baud>{};
|
inline constexpr auto Bd = reference<dim_modulation_rate, baud>{};
|
||||||
@ -82,4 +84,6 @@ inline constexpr auto YBd = reference<dim_modulation_rate, yottabaud>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
@ -125,6 +125,8 @@ constexpr auto operator"" _q_PiB(unsigned long long l) { gsl_ExpectsAudit(std::i
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
// bits
|
// bits
|
||||||
@ -167,4 +169,6 @@ inline constexpr auto PiB = reference<dim_storage_capacity, pebibyte>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
@ -53,10 +53,14 @@ constexpr auto operator"" _q_E(unsigned long long l) { gsl_ExpectsAudit(std::in_
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto E = reference<dim_traffic_intensity, erlang>{};
|
inline constexpr auto E = reference<dim_traffic_intensity, erlang>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
@ -52,10 +52,14 @@ constexpr auto operator"" _q_Gal(long double l) { return acceleration<gal, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto Gal = reference<dim_acceleration, gal>{};
|
inline constexpr auto Gal = reference<dim_acceleration, gal>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -54,10 +54,14 @@ constexpr auto operator"" _q_cm2(long double l) { return area<square_centimetre,
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto cm2 = reference<dim_area, square_centimetre>{};
|
inline constexpr auto cm2 = reference<dim_area, square_centimetre>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -54,10 +54,14 @@ constexpr auto operator"" _q_erg(long double l) { return energy<erg, long double
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto erg = reference<dim_energy, cgs::erg>{};
|
inline constexpr auto erg = reference<dim_energy, cgs::erg>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -55,10 +55,14 @@ constexpr auto operator"" _q_dyn(long double l) { return force<dyne, long double
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto dyn = reference<dim_force, dyne>{};
|
inline constexpr auto dyn = reference<dim_force, dyne>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -53,10 +53,14 @@ constexpr auto operator"" _q_cm(long double l) { return length<centimetre, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto cm = reference<dim_length, centimetre>{};
|
inline constexpr auto cm = reference<dim_length, centimetre>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -53,10 +53,14 @@ constexpr auto operator"" _q_g(long double l) { return mass<gram, long double>(l
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto g = reference<dim_mass, gram>{};
|
inline constexpr auto g = reference<dim_mass, gram>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -55,10 +55,14 @@ constexpr auto operator"" _q_Ba(long double l) { return pressure<barye, long dou
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto Ba = reference<dim_pressure, barye>{};
|
inline constexpr auto Ba = reference<dim_pressure, barye>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -47,10 +47,14 @@ using si::literals::operator"" _q_s;
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
using si::references::s;
|
using si::references::s;
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::cgs
|
} // namespace units::isq::si::cgs
|
||||||
|
@ -53,10 +53,14 @@ constexpr auto operator"" _q_ft2(long double l) { return area<square_foot, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ft2 = reference<dim_area, square_foot>{};
|
inline constexpr auto ft2 = reference<dim_area, square_foot>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -72,6 +72,8 @@ constexpr auto operator"" _q_klbf(long double l) { return force<kilopound_force,
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto pdl = reference<dim_force, poundal>{};
|
inline constexpr auto pdl = reference<dim_force, poundal>{};
|
||||||
@ -80,4 +82,6 @@ inline constexpr auto klbf = reference<dim_force, kilopound_force>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -102,6 +102,8 @@ constexpr auto operator"" _q_naut_mi(long double l) { return length<nautical_mil
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto thou = reference<dim_length, thousandth>{};
|
inline constexpr auto thou = reference<dim_length, thousandth>{};
|
||||||
@ -117,4 +119,6 @@ inline constexpr auto naut_mi = reference<dim_length, nautical_mile>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -102,6 +102,8 @@ constexpr auto operator"" _q_lton(long double l) { return mass<long_ton, long do
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto gr = reference<dim_mass, grain>{};
|
inline constexpr auto gr = reference<dim_mass, grain>{};
|
||||||
@ -116,4 +118,6 @@ inline constexpr auto lton = reference<dim_mass, long_ton>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -66,10 +66,14 @@ constexpr auto operator"" _q_hp(long double l) { return power<horse_power, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto hp = reference<dim_power, horse_power>{};
|
inline constexpr auto hp = reference<dim_power, horse_power>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -69,6 +69,8 @@ constexpr auto operator"" _q_kpsi(long double l) { return pressure<kilopound_for
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto psi = reference<dim_pressure, pound_force_per_inch_sq>{};
|
inline constexpr auto psi = reference<dim_pressure, pound_force_per_inch_sq>{};
|
||||||
@ -76,4 +78,6 @@ inline constexpr auto kpsi = reference<dim_pressure, kilopound_force_per_inch_sq
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -68,6 +68,8 @@ constexpr auto operator"" _q_knot(long double l) { return speed<knot, long doubl
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto mph = reference<dim_speed, mile_per_hour>{};
|
inline constexpr auto mph = reference<dim_speed, mile_per_hour>{};
|
||||||
@ -75,4 +77,6 @@ inline constexpr auto knot = reference<dim_speed, fps::knot>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -51,10 +51,14 @@ using si::literals::operator"" _q_s;
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
using si::references::s;
|
using si::references::s;
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -58,6 +58,8 @@ constexpr auto operator"" _q_yd3(long double l) { return volume<cubic_yard, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ft3 = reference<dim_volume, cubic_foot>{};
|
inline constexpr auto ft3 = reference<dim_volume, cubic_foot>{};
|
||||||
@ -65,4 +67,6 @@ inline constexpr auto yd3 = reference<dim_volume, cubic_yard>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::fps
|
} // namespace units::isq::si::fps
|
||||||
|
@ -64,6 +64,8 @@ constexpr auto operator"" _q_angstrom(long double l) { return si::length<angstro
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ly = reference<si::dim_length, light_year>{};
|
inline constexpr auto ly = reference<si::dim_length, light_year>{};
|
||||||
@ -72,4 +74,6 @@ inline constexpr auto angstrom = reference<si::dim_length, iau::angstrom>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::iau
|
} // namespace units::isq::si::iau
|
||||||
|
@ -56,6 +56,8 @@ constexpr auto operator"" _q_rd(long double l) { return si::length<rod, long dou
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ch = reference<si::dim_length, chain>{};
|
inline constexpr auto ch = reference<si::dim_length, chain>{};
|
||||||
@ -63,4 +65,6 @@ inline constexpr auto rd = reference<si::dim_length, rod>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::imperial
|
} // namespace units::isq::si::imperial
|
||||||
|
@ -49,10 +49,14 @@ constexpr auto operator"" _q_ft2(long double l) { return si::area<square_foot, l
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ft2 = reference<si::dim_area, square_foot>{};
|
inline constexpr auto ft2 = reference<si::dim_area, square_foot>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::international
|
} // namespace units::isq::si::international
|
||||||
|
@ -106,6 +106,8 @@ constexpr auto operator"" _q_mil(long double l) { return si::length<mil, long do
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto yd = reference<si::dim_length, yard>{};
|
inline constexpr auto yd = reference<si::dim_length, yard>{};
|
||||||
@ -119,4 +121,6 @@ inline constexpr auto mil = reference<si::dim_length, international::mil>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::international
|
} // namespace units::isq::si::international
|
||||||
|
@ -49,10 +49,14 @@ constexpr auto operator"" _q_ft3(long double l) { return si::volume<cubic_foot,
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ft3 = reference<si::dim_volume, cubic_foot>{};
|
inline constexpr auto ft3 = reference<si::dim_volume, cubic_foot>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::international
|
} // namespace units::isq::si::international
|
||||||
|
@ -65,6 +65,8 @@ constexpr auto operator"" _q_point_prn(long double l) { return si::length<point_
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto pica_comp = reference<si::dim_length, typographic::pica_comp>{};
|
inline constexpr auto pica_comp = reference<si::dim_length, typographic::pica_comp>{};
|
||||||
@ -74,4 +76,6 @@ inline constexpr auto point_prn = reference<si::dim_length, typographic::point_p
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::typographic
|
} // namespace units::isq::si::typographic
|
||||||
|
@ -65,6 +65,8 @@ constexpr auto operator"" _q_mi_us(long double l) { return si::length<units::isq
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto ft = reference<si::dim_length, us::foot>{};
|
inline constexpr auto ft = reference<si::dim_length, us::foot>{};
|
||||||
@ -73,4 +75,6 @@ inline constexpr auto mi = reference<si::dim_length, us::mile>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si::us
|
} // namespace units::isq::si::us
|
||||||
|
@ -154,6 +154,8 @@ constexpr auto operator"" _q_YGy(long double l) { return absorbed_dose<yottagray
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto Gy = reference<dim_absorbed_dose, gray>{};
|
inline constexpr auto Gy = reference<dim_absorbed_dose, gray>{};
|
||||||
@ -180,4 +182,6 @@ inline constexpr auto YGy = reference<dim_absorbed_dose, yottagray>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -53,10 +53,14 @@ constexpr auto operator"" _q_mol(long double l) { return amount_of_substance<mol
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto mol = reference<dim_amount_of_substance, mole>{};
|
inline constexpr auto mol = reference<dim_amount_of_substance, mole>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -159,6 +159,8 @@ constexpr auto operator"" _q_ha(long double l) { return area<hectare, long doubl
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto m2 = reference<dim_area, square_metre>{};
|
inline constexpr auto m2 = reference<dim_area, square_metre>{};
|
||||||
@ -186,4 +188,6 @@ inline constexpr auto ha = reference<dim_area, hectare>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -155,6 +155,8 @@ constexpr auto operator"" _q_YF(long double l) { return capacitance<yottafarad,
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto F = reference<dim_capacitance, farad>{};
|
inline constexpr auto F = reference<dim_capacitance, farad>{};
|
||||||
@ -181,4 +183,6 @@ inline constexpr auto YF = reference<dim_capacitance, yottafarad>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -161,6 +161,8 @@ constexpr auto operator"" _q_U(long double l) { return catalytic_activity<enzyme
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto kat = reference<dim_catalytic_activity, katal>{};
|
inline constexpr auto kat = reference<dim_catalytic_activity, katal>{};
|
||||||
@ -188,5 +190,7 @@ inline constexpr auto U = reference<dim_catalytic_activity, enzyme_unit>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
|
||||||
|
@ -134,6 +134,8 @@ constexpr auto operator"" _q_YS(long double l) { return conductance<yottasiemens
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto S = reference<dim_conductance, siemens>{};
|
inline constexpr auto S = reference<dim_conductance, siemens>{};
|
||||||
@ -156,5 +158,7 @@ inline constexpr auto YS = reference<dim_conductance, yottasiemens>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
|
||||||
|
@ -54,10 +54,14 @@ constexpr auto operator"" _q_C(long double l) { return electric_charge<coulomb,
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto C = reference<dim_electric_charge, coulomb>{};
|
inline constexpr auto C = reference<dim_electric_charge, coulomb>{};
|
||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -153,6 +153,8 @@ constexpr auto operator"" _q_YA(long double l) { return electric_current<yottaam
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto A = reference<dim_electric_current, ampere>{};
|
inline constexpr auto A = reference<dim_electric_current, ampere>{};
|
||||||
@ -179,4 +181,6 @@ inline constexpr auto YA = reference<dim_electric_current, yottaampere>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -145,6 +145,8 @@ constexpr auto operator"" _q_GeV(long double l) { return energy<gigaelectronvolt
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto J = reference<dim_energy, joule>{};
|
inline constexpr auto J = reference<dim_energy, joule>{};
|
||||||
@ -169,4 +171,6 @@ inline constexpr auto GeV = reference<dim_energy, gigaelectronvolt>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
@ -155,6 +155,8 @@ constexpr auto operator"" _q_YN(long double l) { return force<yottanewton, long
|
|||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_LITERALS
|
||||||
|
|
||||||
|
#ifdef UNITS_REFERENCES
|
||||||
|
|
||||||
namespace references {
|
namespace references {
|
||||||
|
|
||||||
inline constexpr auto N = reference<dim_force, newton>{};
|
inline constexpr auto N = reference<dim_force, newton>{};
|
||||||
@ -181,4 +183,6 @@ inline constexpr auto YN = reference<dim_force, yottanewton>{};
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
|
#endif // UNITS_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user