mirror of
https://github.com/mpusz/mp-units.git
synced 2025-06-25 01:01:33 +02:00
docs: initial V2 documenatation added
This commit is contained in:
88
.github/workflows/documentation.yml
vendored
88
.github/workflows/documentation.yml
vendored
@ -24,79 +24,29 @@ name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/documentation.yml"
|
||||
- "docs/**"
|
||||
- "src/**"
|
||||
- "example/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/documentation.yml"
|
||||
- "docs/**"
|
||||
- "src/**"
|
||||
- "example/**"
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
docs:
|
||||
name: Generate documentation
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CONAN_CMAKE_GENERATOR: Ninja
|
||||
OS: ubuntu-22.04
|
||||
BUILD_TYPE: Debug
|
||||
COMPILER_TYPE: GCC
|
||||
COMPILER_VERSION: 10
|
||||
STDLIB: libstdc++11
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ["ubuntu-latest"]
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cache Conan data
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-conan-data
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
path: ~/.conan2/p
|
||||
key: build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB-docs
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
path: .cache
|
||||
restore-keys: |
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-$STDLIB
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-$COMPILER_VERSION-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-$COMPILER_TYPE-
|
||||
build-${{ matrix.os }}-$BUILD_TYPE-
|
||||
build-${{ matrix.os }}-
|
||||
- name: Install Ninja
|
||||
mkdocs-material-
|
||||
- name: Installing pip packages
|
||||
run: |
|
||||
sudo apt install -y ninja-build
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install Python dependencies
|
||||
pip install conan mkdocs-material mike
|
||||
- name: Building docs
|
||||
run: |
|
||||
pip install -Ur docs/requirements.txt
|
||||
- name: Install Conan
|
||||
run: |
|
||||
pip install -U conan
|
||||
- name: Configure Conan
|
||||
run: |
|
||||
conan profile detect --force
|
||||
conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
- name: Install Conan dependencies
|
||||
run: |
|
||||
conan install . -s compiler.cppstd=20 -s compiler.libcxx=$STDLIB -c user.build:all=True -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -b missing
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cmake --preset conan-default
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
cmake --build --preset conan-release --target documentation
|
||||
- name: Deploy documentation
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./build/docs/sphinx
|
||||
mike deploy --push --update-aliases `conan inspect . | sed -n -r 's/version: ([0-9]+.[0-9]+).[0-9]+/\1/p'` latest
|
||||
|
@ -25,7 +25,7 @@ project(mp-units-dev LANGUAGES CXX)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
set(projectPrefix UNITS_)
|
||||
set(projectPrefix MP_UNITS_)
|
||||
|
||||
option(${projectPrefix}BUILD_LA "Build code depending on the linear algebra library" ON)
|
||||
message(STATUS "${projectPrefix}BUILD_LA: ${${projectPrefix}BUILD_LA}")
|
||||
@ -70,9 +70,6 @@ add_subdirectory(src)
|
||||
# add usage example
|
||||
add_subdirectory(example)
|
||||
|
||||
# generate project documentation
|
||||
# add_subdirectory(docs)
|
||||
|
||||
# add unit tests
|
||||
enable_testing()
|
||||
|
||||
|
10
README.md
10
README.md
@ -25,8 +25,8 @@ enable the rest of mainstream compilers and update the documentation to reflect
|
||||
|
||||
## Documentation
|
||||
|
||||
An extensive project documentation for the previous release library version can be found on
|
||||
[mp-units GitHub Pages](https://mpusz.github.io/mp-units). It includes installation instructions and user's guide.
|
||||
An extensive project documentation can be found on [mp-units GitHub Pages](https://mpusz.github.io/mp-units).
|
||||
It includes installation instructions and a detailed user's guide.
|
||||
|
||||
|
||||
## Terms and Definitions
|
||||
@ -100,8 +100,8 @@ int main()
|
||||
|
||||
constexpr auto v1 = 110 * (km / h);
|
||||
constexpr auto v2 = 70 * mph;
|
||||
constexpr auto v3 = avg_speed(220. * km, 2 * h);
|
||||
constexpr auto v4 = avg_speed(isq::distance(140. * mi), 2 * isq::duration[h]);
|
||||
constexpr auto v3 = avg_speed(220. * isq::distance[km], 2 * h);
|
||||
constexpr auto v4 = avg_speed(isq::distance(140. * mi), 2 * h);
|
||||
constexpr auto v5 = v3[m / s];
|
||||
constexpr auto v6 = value_cast<m / s>(v4);
|
||||
constexpr auto v7 = value_cast<int>(v6);
|
||||
@ -116,4 +116,4 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/rrTojn47v)._
|
||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/T8bovrqTP)._
|
||||
|
@ -1,7 +0,0 @@
|
||||
# Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
|
@ -1,123 +0,0 @@
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2018 Mateusz Pusz
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# TODO Switch to CONFIG when Conan will start supporting imported executables in CMakeDeps
|
||||
find_package(Doxygen MODULE REQUIRED)
|
||||
find_package(Sphinx REQUIRED)
|
||||
|
||||
#
|
||||
# add_documentation(TargetName [ALL]
|
||||
# BREATHE_PROJECT projectName
|
||||
# [DOXYFILE_TEMPLATE Doxyfile.in]
|
||||
# [CODE_SOURCE_DIR dir]
|
||||
# [DOCS_SOURCE_DIR dir]
|
||||
# [INSTALL_DIR dir]
|
||||
# CODE_DEPENDS codeDeps...
|
||||
# DOC_DEPENDS docDeps...)
|
||||
#
|
||||
function(add_documentation targetName)
|
||||
set(_options ALL)
|
||||
set(_one_value_args BREATHE_PROJECT DOXYFILE_TEMPLATE CODE_SOURCE_DIR DOCS_SOURCE_DIR INSTALL_DIR)
|
||||
set(_multi_value_args CODE_DEPENDS DOCS_DEPENDS)
|
||||
cmake_parse_arguments(_args "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if(NOT _args_BREATHE_PROJECT)
|
||||
message(FATAL_ERROR "BREATHE_PROJECT not provided")
|
||||
endif()
|
||||
|
||||
# Validate arguments
|
||||
if(NOT _args_DOXYFILE_TEMPLATE)
|
||||
set(_args_DOXYFILE_TEMPLATE Doxyfile.in)
|
||||
endif()
|
||||
get_filename_component(_doxyfileIn ${_args_DOXYFILE_TEMPLATE} REALPATH)
|
||||
if(NOT EXISTS ${_doxyfileIn})
|
||||
message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist")
|
||||
endif()
|
||||
|
||||
if(_args_DOCS_SOURCE_DIR)
|
||||
if(NOT EXISTS ${_args_DOCS_SOURCE_DIR})
|
||||
message(FATAL_ERROR "'${_args_DOCS_SOURCE_DIR}' does not exist")
|
||||
endif()
|
||||
else()
|
||||
set(_args_DOCS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# Validate CODE_SOURCE_DIR and set input for the configuration file
|
||||
if(_args_CODE_SOURCE_DIR)
|
||||
if(NOT EXISTS ${_args_CODE_SOURCE_DIR})
|
||||
message(FATAL_ERROR "'${_args_CODE_SOURCE_DIR}' does not exist")
|
||||
endif()
|
||||
set(DOXYGEN_INPUT_DIR "${_args_CODE_SOURCE_DIR}")
|
||||
else()
|
||||
set(DOXYGEN_INPUT_DIR "${PROJECT_SOURCE_DIR}")
|
||||
endif()
|
||||
set(DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doxygen")
|
||||
|
||||
# Replace variables inside @@ with the current values
|
||||
set(_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
configure_file("${_doxyfileIn}" "${_doxyfile}" @ONLY)
|
||||
|
||||
set(_doxygenIndexFile "${DOXYGEN_OUTPUT_DIR}/xml/index.xml")
|
||||
|
||||
# Only regenerate Doxygen when the Doxyfile or given dependencies change
|
||||
add_custom_command(
|
||||
OUTPUT "${_doxygenIndexFile}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR}
|
||||
COMMAND Doxygen::doxygen ARGS "${_doxyfile}"
|
||||
MAIN_DEPENDENCY "${_doxyfileIn}"
|
||||
DEPENDS "${_doxyfile}" "${_args_CODE_DEPENDS}"
|
||||
COMMENT "Generating doxygen XML metadata"
|
||||
USES_TERMINAL VERBATIM
|
||||
)
|
||||
|
||||
set(_sphinx_docs_dir "${CMAKE_CURRENT_BINARY_DIR}/sphinx")
|
||||
set(_sphinx_index_file "${_sphinx_docs_dir}/index.html")
|
||||
|
||||
# Only regenerate Sphinx when:
|
||||
# - Doxygen has rerun
|
||||
# - Our doc files have been updated
|
||||
# - The Sphinx config has been updated
|
||||
add_custom_command(
|
||||
OUTPUT "${_sphinx_index_file}"
|
||||
COMMAND "${SPHINX_EXECUTABLE}" ARGS -b html -j auto
|
||||
"-Dbreathe_projects.${_args_BREATHE_PROJECT}=${DOXYGEN_OUTPUT_DIR}/xml" "${_args_DOCS_SOURCE_DIR}"
|
||||
"${_sphinx_docs_dir}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
MAIN_DEPENDENCY "${_args_DOCS_SOURCE_DIR}/conf.py"
|
||||
DEPENDS "${_doxygenIndexFile}" "${_args_DOCS_DEPENDS}"
|
||||
COMMENT "Generating documentation with Sphinx"
|
||||
USES_TERMINAL VERBATIM
|
||||
)
|
||||
|
||||
# Custom target
|
||||
if(_args_ALL)
|
||||
set(_all ALL)
|
||||
endif()
|
||||
add_custom_target(${targetName} ${_all} DEPENDS "${_sphinx_index_file}")
|
||||
|
||||
if(_args_INSTALL_DIR)
|
||||
# Add an install step to install the docs
|
||||
install(DIRECTORY ${_sphinx_docs_dir} TYPE DOC)
|
||||
endif()
|
||||
endfunction()
|
@ -82,10 +82,6 @@ class MPUnitsConan(ConanFile):
|
||||
def _skip_la(self):
|
||||
return bool(self.conf.get("user.build:skip_la", default=False))
|
||||
|
||||
@property
|
||||
def _skip_docs(self):
|
||||
return bool(self.conf.get("user.build:skip_docs", default=True))
|
||||
|
||||
@property
|
||||
def _use_libfmt(self):
|
||||
compiler = self.settings.compiler
|
||||
@ -118,8 +114,6 @@ class MPUnitsConan(ConanFile):
|
||||
self.test_requires("catch2/3.3.2")
|
||||
if not self._skip_la:
|
||||
self.test_requires("wg21-linear_algebra/0.7.3")
|
||||
if not self._skip_docs:
|
||||
self.tool_requires("doxygen/1.9.4")
|
||||
|
||||
def validate(self):
|
||||
check_min_cppstd(self, self._min_cppstd)
|
||||
|
8
docs/.overrides/main.html
Normal file
8
docs/.overrides/main.html
Normal file
@ -0,0 +1,8 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block outdated %}
|
||||
You're not viewing the latest version.
|
||||
<a href="{{ '../' ~ base_url }}">
|
||||
<strong>Click here to go to latest.</strong>
|
||||
</a>
|
||||
{% endblock %}
|
@ -1,241 +0,0 @@
|
||||
# Release notes
|
||||
|
||||
- **2.0.0 WIP**
|
||||
- `units` namespace renamed to `mp_units` (#317)
|
||||
- header files in the `<mp-units/...>` rather then in `<units/...>` (#317)
|
||||
- the downcasting facility is removed (#383, #211, #32)
|
||||
- unified and simplified quantity creation (#274)
|
||||
- Determining the best way to create a quantity (#413)
|
||||
- V2 quantity_point (#414)
|
||||
- introduction of `quantity_spec` to store not only `dimension` but also additional information about quantities (#405)
|
||||
- `quantity` now takes `reference` object, which aggregates `quantity_spec` and a `unit` and a `representation` type
|
||||
- units, prefixes, dimensions, quantity specifications, and references are passed as NTTPs to templates and provide arithmetic operations and comparison
|
||||
- expression templates consistently used in all derived types to increase the readability (#351, #166)
|
||||
- derived dimensions are now factors of only base dimensions (#281)
|
||||
- Interconvertibility of derived quantities (#427)
|
||||
- dimensions, quantity specifications, units, and references are now composable, significantly reducing the number of definitions and resulting types
|
||||
- heavily simplified unit systems definitions (no need to define unnamed derived units, systems-specific dimensions, aliases for quantities, concepts, UDLs, ... anymore)
|
||||
- improved definition of all systems
|
||||
- support for all (or at least most) ISO 80000 quantities
|
||||
- faster than lightspeed constants (#169)
|
||||
- extensions to quantity formatting with `fmt`
|
||||
- `quantity_kind` removed
|
||||
- much easier and safe casting of unit with `operator[]` and `.number_in(Unit)`
|
||||
- quantity can no longer be constructed with a raw value (#434)
|
||||
- Implicit construction of quantities from a value (#410)
|
||||
- `ceil` and `floor` are dangerous (#432)
|
||||
- quecto, ronto, ronna, quetta new SI prefixes support
|
||||
- many smaller changes not possible to address with the previous design (#205, #210, #134)
|
||||
|
||||
- **0.8.0 June 14, 2023**
|
||||
- (!) refactor: `common_quantity`, `common_quantity_for`, `common_quantity_point`, `common_quantity_kind`, and `common_quantity_point_kind` removed
|
||||
- (!) refactor: `named_derived_unit` removed as it was not used
|
||||
- (!) refactor: `derived_unit` renamed to `derived_scaled_unit`
|
||||
- (!) refactor: `unit` renamed to `derived_unit`
|
||||
- (!) refactor: `U::is_named` removed from the unit types and replaced with `NamedUnit` concept
|
||||
- (!) refactor: `PrefixFamily` support removed
|
||||
- (!) refactor: `mi(naut)` renamed to `nmi`
|
||||
- (!) refactor: `knot` unit helper renamed to `kn` in FPS
|
||||
- (!) refactor: `knot` text symbol changed from `"knot"` to `"kn"`
|
||||
- refactor: `quantity` `op+()` and `op-()` reimplemented in terms of `reference` rather then `quantity` types
|
||||
- refactor(example): `glide_computer` now use dimensionless quantities with `ranged_representation` as `rep`
|
||||
- feat: HEP system support added (thanks [@RalphSteinhagen](https://github.com/RalphSteinhagen))
|
||||
- feat: `floor()`, `ceil()`, and `round()` support added (thanks [@hofbi](https://github.com/hofbi))
|
||||
- feat: `std::format` support for compliant compilers added
|
||||
- feat: conversion helpers from `mp-units` to `std::chrono` types added
|
||||
- feat: math functions can now be safely used with user-defined types
|
||||
- feat: conversion from `quantity_point` to `std::chrono::time_point` added
|
||||
- feat: `nautical_mile_per_hour` and `knot` added to `si::international` system
|
||||
- (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock`
|
||||
- fix: enable any prefixes for most of the named units (beside those that use prefixes already)
|
||||
- fix: `hectare` definition fixed to be a prefixed version of `are` + other units
|
||||
- fix: account for different dimensions in `quantity_point_cast`'s constraint
|
||||
- fix: output stream operator now properly handles state
|
||||
- fix: `fmt` algorithms were overconstrained with `forward_iterator`
|
||||
- fix: CTAD for aliases fixed
|
||||
- fix: `derived_ratio` calculation
|
||||
- fix: `fill_t` assignment operator fixed
|
||||
- fix: improve downcast mode off
|
||||
- fix: `radioactivity` header compilation fixed
|
||||
- fix: `si::hep::dim_momentum` duplicated definition fixed
|
||||
- fix: `fps` can now coexist with `international` system
|
||||
- fix: public headers fixed to be standalone
|
||||
- test: standalone public headers tests added
|
||||
- (!) build: CMake generator in Conan is no longer obtained from an environment variable
|
||||
- (!) build: Required Conan version bumped to 1.48
|
||||
- (!) build: Conan 1.48 does not set `CMAKE_BUILD_TYPE` in the `conan_toolchain.cmake` anymore
|
||||
- build: AppleClang 13 support added (thanks [@fdischner](https://github.com/fdischner))
|
||||
- build: most of the `conanfile.py` refactored to be Conan 2.0 ready
|
||||
- build: `validate()` replaced with `configure()` to raise errors during `conan install` in Conan 1.X
|
||||
- build: minimum Conan version changed to 1.40
|
||||
- build: `linear-algebra` Conan repo is no needed anymore
|
||||
- build: Gitpod support added
|
||||
- build: clang-format-15 support added
|
||||
- build: export config to local build (#322)
|
||||
- build: fix export name of `mp-units-system`
|
||||
- build: fmt updated to 8.0.1
|
||||
- build: gsl-lite updated to 0.40.0
|
||||
- build: catch2 updated to 2.13.9
|
||||
- build: doxygen updated to 1.9.4
|
||||
- build: linear_algebra/0.7.0 switched to wg21-linear_algebra/0.7.2
|
||||
- ci: VS2022, gcc-11, clang-13, clang-14, and AppleClang 13 support added
|
||||
- ci: pre-commit support added (thanks [@hofbi](https://github.com/hofbi))
|
||||
- docs: Project documentation updated
|
||||
- docs: `CITATION.cff` file added
|
||||
- docs: `CONTRIBUTING.md` updated
|
||||
|
||||
- **0.7.0 May 11, 2021**
|
||||
- (!) refactor: `ScalableNumber` renamed to `Representation`
|
||||
- (!) refactor: output stream operators moved to the `units/quantity_io.h` header file
|
||||
- (!) refactor: Refactored the library file tree
|
||||
- (!) refactor: `quantity::count()` renamed to `quantity::number()`
|
||||
- (!) refactor: `data` system renamed to `isq::iec80000` (quantity names renamed too)
|
||||
- (!) refactor: `*deduced_unit` renamed to `*derived_unit`
|
||||
- (!) refactor: got rid of a `noble_derived_unit`
|
||||
- refactor: quantity (kind) point updated to reflect latest changes to `quantity`
|
||||
- refactor: basic concepts, `quantity` and `quantity_cast` refactored
|
||||
- refactor: `abs()` definition refactored to be more explicit about the return type
|
||||
- feat: quantity (point) kind support added (thanks [@johelegp](https://github.com/johelegp))
|
||||
- feat: quantity references support added (thanks [@johelegp](https://github.com/johelegp))
|
||||
- feat: quantity aliases support addded
|
||||
- feat: interoperability with `std::chrono::duration` and other units libraries
|
||||
- feat: CTAD for dimensionless quantity added
|
||||
- feat: `modulation_rate` support added (thanks [@go2sh](https://github.com/go2sh))
|
||||
- feat: SI prefixes for `isq::iec80000` support added (thanks [@go2sh](https://github.com/go2sh))
|
||||
- feat: a possibility to disable quantity UDLs support with `UNITS_NO_LITERALS` preprocessor define
|
||||
- feat: a support to define ISQ derived dimensions in terms of different number or order of components
|
||||
- perf: preconditions check do not influence the runtime performance of a Release build
|
||||
- perf: `quantity_cast()` generates less assembly instructions
|
||||
- perf: temporary string creation removed from `quantity::op<<()`
|
||||
- perf: value initialization for quantity value removed (left with a default initialization)
|
||||
- perf: limited the `equivalent` trait usage
|
||||
- perf: limited the C++ Standard Library headers usage
|
||||
- perf: rvalue references support added for constructors and getters
|
||||
- (!) fix: `exp()` has sense only for dimensionless quantities
|
||||
- (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change
|
||||
- fix: quantity's operators fixed to behave like the underlying types do
|
||||
- fix: `quantity_cast()` fixed to work correctly with representation types not convertible from `std::intmax_t`
|
||||
- fix: ambiguous case for empty type list resolved
|
||||
- fix: downcasting facility for non-default-constructible types
|
||||
- fix: restore user-warnings within the library implementation
|
||||
- fix: the text symbol of `foot_pound_force` and `foot_pound_force_per_second`
|
||||
- fix: quantity modulo arithmetics fixed
|
||||
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
|
||||
- (!) build: Linear Algebra is now hosted on its [Artifactory](https://twonington.jfrog.io/artifactory/api/conan/conan-oss)
|
||||
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
|
||||
- build: doxygen updated to 1.8.20
|
||||
- build: catch2 updated to 2.13.4
|
||||
- build: fmt updated to 7.1.3
|
||||
- build: ms-gsl replaced with gsl-lite/0.38.0
|
||||
- build: Conan generator switched to `cmake_find_package_multi`
|
||||
- build: Conan CMakeToolchain support added
|
||||
- build: CMake scripts cleanup
|
||||
- build: ccache support added
|
||||
- ci: CI switched from Travis CI to GitHub Actions
|
||||
|
||||
- **0.6.0 September 13, 2020**
|
||||
- feat: `quantity_point` support added (thanks [@johelegp](https://github.com/johelegp))
|
||||
- feat: Added angle as SI base dimension (thanks [@kwikius](https://github.com/kwikius))
|
||||
- feat: `si::angular_velocity` support added (thanks [@mikeford3](https://github.com/mikeford3))
|
||||
- feat: FPS system added (thanks [@mikeford3](https://github.com/mikeford3))
|
||||
- feat: Added support for mathematical function `exp(quantity)`
|
||||
- feat: Localization support for text output added (thanks [@rbrugo](https://github.com/rbrugo))
|
||||
- feat: Added STL random number distribution wrappers (thanks [@yasamoka](https://github.com/yasamoka))
|
||||
- (!) refactor: Refactored and cleaned up the library file tree
|
||||
- (!) refactor: `q_*` UDL renamed to `_q_*`
|
||||
- (!) refactor: UDLs with "per" in name renamed from `*p*` to `*_per_*`
|
||||
- (!) refactor: `ratio` changed to the NTTP kind
|
||||
- (!) refactor: `exp` and `Exp` renamed to `exponent` and `Exponent`
|
||||
- (!) refactor: `Scalar` concept renamed to `ScalableNumber`
|
||||
- (!) refactor: Dimensionless quantities redesigned to be of a `quantity` type
|
||||
- refactor: `math.h` function signatures refactored to use a `Quantity` concept (thanks [@kwikius](https://github.com/kwikius))
|
||||
- refactor: `[[nodiscard]]` added to many functions
|
||||
- fix: `si::day` unit symbol fixed to `d` (thanks [@komputerwiz](https://github.com/komputerwiz))
|
||||
- fix: `si::mole` unit symbol fixed to `mol` (thanks [@mikeford3](https://github.com/mikeford3))
|
||||
- (!) build: gcc-9 is no longer supported (at least gcc-10 is required)
|
||||
- build: Visual Studio 16.7 support added
|
||||
- build: linear_algebra updated to 0.7.0/stable
|
||||
- build: fmt updated to 7.0.3
|
||||
- build: range-v3 updated to 0.11.0
|
||||
- build: catch2 updated to 2.13.0
|
||||
- build: doxygen updated to 1.8.18
|
||||
- build: ms-gsl 3.1.0 dependency added
|
||||
- build: Removed the dependency on a git submodule with common CMake scripts
|
||||
|
||||
- **0.5.0 May 17, 2020**
|
||||
- Major refactoring and rewrite of the library
|
||||
- Units are now independent from dimensions
|
||||
- Dimensions now depend on units (base or coherent units are provided in a class template)
|
||||
- Quantity gets a Dimension template parameter again (as unit does not provide information about
|
||||
its dimension anymore)
|
||||
- Spaceship operator support added
|
||||
- Added official CGS system support
|
||||
- Added official data information system support
|
||||
- Repository file tree cleanup
|
||||
- `ratio` refactored to contain `Exp` template parameter (thanks a lot [@oschonrock](https://github.com/oschonrock)!)
|
||||
- SI fundamental constants added
|
||||
- `q_` prefix applied to all the UDLs (thanks [@kwikius](https://github.com/kwikius))
|
||||
- `unknown_unit` renamed to `unknown_coherent_unit`
|
||||
- Project documentation greatly extended and switched to Sphinx
|
||||
- A few more usage examples added
|
||||
- ASCII-only output support added (thanks [@yasamoka](https://github.com/yasamoka))
|
||||
- Representation values formatting extended (thanks [@rbrugo](https://github.com/rbrugo))
|
||||
- Output streams formatting support added
|
||||
- Linear algebra from `std::experimental::math` support added
|
||||
- Named SI units and their dimensions added (thanks [@rbrugo](https://github.com/rbrugo)
|
||||
- libfmt updated to 6.2.0
|
||||
- Added absolute functions and epsilon to math.h (thanks [@mikeford3](https://github.com/mikeford3))
|
||||
- Added a lot of prefixes to named units and introduced `alias_unit` (thanks [@yasamoka](https://github.com/yasamoka))
|
||||
- Linking with Conan targets only when they exists ([#98](https://github.com/mpusz/units/issues/98))
|
||||
- All physical dimensions and units put into `physical` namespace
|
||||
- CMake improvements
|
||||
- Velocity renamed to speed
|
||||
|
||||
Many thanks to GitHub users [@oschonrock](https://github.com/oschonrock),
|
||||
[@kwikius](https://github.com/kwikius), and [@i-ky](https://github.com/i-ky) for their support
|
||||
in drafting a new library design.
|
||||
|
||||
- **0.4.0 Nov 17, 2019**
|
||||
- Support for derived dimensions in `exp` added
|
||||
- Added `pow()` and `sqrt()` operations on quantities
|
||||
- `units` removed from a `std::experimental` namespace
|
||||
- Downcasting facility refactored so the user does not have to write the boilerplate code anymore
|
||||
- From now on base dimensions should inherit from `base_dimension` class template
|
||||
- Added unit symbols definitions to `base_dimension` and derived units
|
||||
- Added support for `operator<<` on `quantity`
|
||||
- `fmt` support added
|
||||
- Derived unit factory helpers refactored
|
||||
- Refactored the way prefixed units are defined
|
||||
|
||||
- **0.3.1 Sep 18, 2019**
|
||||
- cmcstl2 dependency changed to range-v3 0.9.1
|
||||
|
||||
- **0.3.0 Sep 16, 2019 (CppCon 2019 design)**
|
||||
- The design as described on CppCon 2019 talk (<https://youtu.be/0YW6yxkdhlU>)
|
||||
- Applied the feedback from the Cologne evening session
|
||||
- `upcasting_traits` renamed to `downcasting_traits`
|
||||
- `Dimension` template parameter removed from quantity
|
||||
- `units` moved to a `std::experimental` namespace
|
||||
- Leading underscore prefix removed from UDLs
|
||||
- Added a few more derived dimensions
|
||||
- `meter` renamed to `metre`
|
||||
- Missing `operator*` added
|
||||
- Predefined dimensions moved to a dedicated directory
|
||||
- `dimension_` prefix removed from names of derived dimensions
|
||||
- cmcstl2 library updated to 2019.09.19
|
||||
- `base_dimension` is a value provided as `const&` to the `exp` type
|
||||
- integrated with Compiler Explorer
|
||||
- gsl-lite dependency removed
|
||||
- Fractional dimension exponents support added
|
||||
- `QuantityOf` concept introduced
|
||||
- `quantity_cast<U, Rep>()` support added
|
||||
|
||||
- **0.2.0 July 18, 2019 (C++Now 2019 design)**
|
||||
- The design as described on C++Now 2019 talk (<https://youtu.be/wKchCktZPHU>)
|
||||
- Added C++20 features supported by gcc-9.1 (`std::remove_cvref_t`, down with typename, `std::type_identity`)
|
||||
- Compile-time performance optimizations (`type_list`, `common_ratio`, `ratio`, `conditional_t`)
|
||||
|
||||
- **0.1.0 May 18, 2019**
|
||||
- Initial library release
|
||||
- Begin semantic versioning
|
||||
- The last version to work with gcc-8
|
@ -1,261 +0,0 @@
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2018 Mateusz Pusz
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
option(${projectPrefix}BUILD_DOCS "Generate project documentation" ON)
|
||||
message(STATUS "${projectPrefix}BUILD_DOCS: ${${projectPrefix}BUILD_DOCS}")
|
||||
|
||||
if(NOT ${projectPrefix}BUILD_DOCS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# set paths to Conan packages (needed for doxygen)
|
||||
# TODO: remove when Conan will learn how to properly create imported build tools targets
|
||||
include(${CMAKE_BINARY_DIR}/conan_paths.cmake OPTIONAL)
|
||||
|
||||
# Find all the public headers
|
||||
file(GLOB_RECURSE unitsPublicHeaders "${PROJECT_SOURCE_DIR}/src/*.h")
|
||||
|
||||
# Sphinx documentation dependencies
|
||||
set(unitsSphinxDocs
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/css/custom.css"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/concepts.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/dimensions.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_1.png"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_2.png"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/quantity_like.svg"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/angular_units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/isq.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/defining_systems/si.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity_kind.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/avg_speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/box_example.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/capacitor_time_curve.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/clcpp_response.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/experimental_angle.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/foot_pound_second.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/glide_computer.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/hello_units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/total_energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/unknown_dimension.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/linear_algebra.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/measurement.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems/custom_systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities/conversion_factor.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_1.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_2.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_3.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_4.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_5.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_6.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_7.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_8.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/kalman.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/faq.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/arithmetics.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/constants.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/conversions_and_casting.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/dimensions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/magnitudes.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/quantities.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_kinds.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_like.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_points.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/text_output.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/framework/units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/genindex.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/glossary.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/index.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/introduction.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/quick_start.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/concepts.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/customization_points.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/downcasting.rst"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/functions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/metafunctions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/dimensions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/kinds.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/prefixes.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/reference.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/quantity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/quantity_kind.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/quantity_point_kind.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/quantity_point.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_fixed_string.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_symbol_text.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/ratio.rst"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/reference/math.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/random.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/angle.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/dimensionless.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/unknown.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/binary_prefixes.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/modulation_rate.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/storage_capacity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/traffic_intensity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/transfer_rate.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/acceleration.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/constants.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/force.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/mass.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/momentum.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/time.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_cgs.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/acceleration.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/area.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/force.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/mass.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/power.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/pressure.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/time.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/dimensions_and_concepts.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_fps.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/acceleration.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/area.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/density.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/force.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/mass.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/power.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/pressure.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/time.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/volume.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_iau.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/iau/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_imperial.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/imperial/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_international.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/area.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/volume.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/absorbed_dose.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/acceleration.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/amount_of_substance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/area.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/capacitance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/catalytic_activity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/charge_density.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/concentration.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/conductance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/constants.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/current_density.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/density.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/dynamic_viscosity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/electric_charge.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/electric_current.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/electric_field_strength.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/force.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/frequency.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/heat_capacity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/inductance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/luminance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/luminous_intensity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/magnetic_flux.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/magnetic_induction.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/mass.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/molar_energy.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/momentum.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/permeability.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/permittivity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/power.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/prefixes.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/pressure.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/resistance.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/speed.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/surface_tension.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/thermal_conductivity.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/thermodynamic_temperature.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/time.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/voltage.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/volume.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_typographic.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/typographic/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_uscs.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/uscs/length.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/references.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/custom_representation_types.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/extensions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/interoperability.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/legacy_interfaces.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/linear_algebra.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/natural_units.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/unknown_dimensions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/usage.rst"
|
||||
)
|
||||
|
||||
include(documentation)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_documentation(
|
||||
documentation ALL
|
||||
BREATHE_PROJECT mp-units
|
||||
CODE_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src"
|
||||
INSTALL_DIR ${CMAKE_INSTALL_DOCDIR}
|
||||
CODE_DEPENDS ${unitsPublicHeaders}
|
||||
DOCS_DEPENDS ${unitsSphinxDocs}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET documentation POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_static/img/*.svg
|
||||
${CMAKE_CURRENT_BINARY_DIR}/sphinx/_images
|
||||
)
|
@ -1,93 +0,0 @@
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
# entered, it will be relative to the location where doxygen was started. If
|
||||
# left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIR@"
|
||||
|
||||
# The INPUT tag is used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like myfile.cpp or
|
||||
# directories like /usr/src/myproject. Separate the files or directories with
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = "@DOXYGEN_INPUT_DIR@"
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
# The default value is: NO.
|
||||
|
||||
RECURSIVE = YES
|
||||
|
||||
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
|
||||
# to include (a tag file for) the STL sources as input, then you should set this
|
||||
# tag to YES in order to let doxygen match functions declarations and
|
||||
# definitions whose arguments contain STL classes (e.g. func(std::string);
|
||||
# versus func(std::string) {}). This also make the inheritance and collaboration
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
# The default value is: NO.
|
||||
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_HTML = NO
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
|
||||
# captures the structure of the code including all documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_XML = YES
|
||||
|
||||
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
|
||||
# documentation are documented, even if no documentation was available. Private
|
||||
# class members and static file members will be hidden unless the
|
||||
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
|
||||
# Note: This will also disable the warnings about undocumented members that are
|
||||
# normally produced when WARNINGS is set to YES.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
|
||||
# included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_STATIC = YES
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS = units::detail
|
||||
|
||||
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
|
||||
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
|
||||
# will automatically be disabled.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated to
|
||||
# standard output by doxygen. If QUIET is set to YES this implies that the
|
||||
# messages are off.
|
||||
# The default value is: NO.
|
||||
|
||||
QUIET = YES
|
20
docs/_static/css/custom.css
vendored
20
docs/_static/css/custom.css
vendored
@ -1,20 +0,0 @@
|
||||
@import 'theme.css';
|
||||
|
||||
a.reference.internal + code.sig-name.descname {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.breatheparameterlist li tt + p {
|
||||
display: inline;
|
||||
}
|
||||
.breatheenumvalues li tt + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.rst-content .admonition-try-it-on-compiler-explorer {
|
||||
background-color: #e2f6d5;
|
||||
}
|
||||
|
||||
.rst-content .admonition-try-it-on-compiler-explorer > .admonition-title {
|
||||
background-color: #66c52a;
|
||||
}
|
116
docs/_static/img/concepts.svg
vendored
116
docs/_static/img/concepts.svg
vendored
@ -1,116 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="818px" preserveAspectRatio="none" style="width:925px;height:818px;background:#FCFCFC;" version="1.1" viewBox="0 0 925 818" width="925px" zoomAndPan="magnify"><defs/><g><!--MD5=[df5443ea73757c949ae3b56ebe1f85be]
|
||||
cluster Kind--><a href="../../framework/quantity_kinds.html#kind-creation" target="_top" title="../../framework/quantity_kinds.html#kind-creation" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#kind-creation" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#kind-creation" xlink:type="simple"><rect fill="#FCFCFC" height="91" style="stroke:#000000;stroke-width:1.5;" width="167" x="193" y="244"/><path d="M238,244 L238,253.2969 L228,263.2969 L193,263.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="35" x="196" y="257.9951">Kind</text></a><!--MD5=[7347e2c91daf6e188383fd600ba11b33]
|
||||
cluster PointKind--><a href="../../framework/quantity_kinds.html#quantity-point-kinds" target="_top" title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:type="simple"><rect fill="#FCFCFC" height="91" style="stroke:#000000;stroke-width:1.5;" width="241" x="60" y="537.5"/><path d="M148,537.5 L148,546.7969 L138,556.7969 L60,556.7969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="78" x="63" y="551.4951">PointKind</text></a><!--MD5=[902b17ab3dc1ff87bf436c5d5e991ce7]
|
||||
cluster PointOrigin--><a href="../../framework/quantity_points.html#point-origins" target="_top" title="../../framework/quantity_points.html#point-origins" xlink:actuate="onRequest" xlink:href="../../framework/quantity_points.html#point-origins" xlink:show="new" xlink:title="../../framework/quantity_points.html#point-origins" xlink:type="simple"><rect fill="#FCFCFC" height="91" style="stroke:#000000;stroke-width:1.5;" width="211" x="400" y="244"/><path d="M502,244 L502,253.2969 L492,263.2969 L400,263.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="92" x="403" y="257.9951">PointOrigin</text></a><!--MD5=[ce5ab648b60979218cea37a66686aafa]
|
||||
cluster Quantity--><a href="../../framework/quantities.html" target="_top" title="../../framework/quantities.html" xlink:actuate="onRequest" xlink:href="../../framework/quantities.html" xlink:show="new" xlink:title="../../framework/quantities.html" xlink:type="simple"><rect fill="#FCFCFC" height="112" style="stroke:#000000;stroke-width:1.5;" width="251" x="531" y="375"/><path d="M613,375 L613,384.2969 L603,394.2969 L531,394.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="72" x="534" y="388.9951">Quantity</text></a><!--MD5=[322ec44ab3fdb4211708329edccee368]
|
||||
cluster QuantityPoint--><a href="../../framework/quantity_points.html" target="_top" title="../../framework/quantity_points.html" xlink:actuate="onRequest" xlink:href="../../framework/quantity_points.html" xlink:show="new" xlink:title="../../framework/quantity_points.html" xlink:type="simple"><rect fill="#FCFCFC" height="112" style="stroke:#000000;stroke-width:1.5;" width="291" x="628" y="527"/><path d="M753,527 L753,536.2969 L743,546.2969 L628,546.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="115" x="631" y="540.9951">QuantityPoint</text></a><!--MD5=[64a7dbcb99a03de11a63a2b4b9c040ec]
|
||||
cluster QuantityKind--><a href="../../framework/quantity_kinds.html" target="_top" title="../../framework/quantity_kinds.html" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html" xlink:show="new" xlink:title="../../framework/quantity_kinds.html" xlink:type="simple"><rect fill="#FCFCFC" height="112" style="stroke:#000000;stroke-width:1.5;" width="247" x="341" y="527"/><path d="M458,527 L458,536.2969 L448,546.2969 L341,546.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="107" x="344" y="540.9951">QuantityKind</text></a><!--MD5=[8bab1fe1e45831c182205808cde691dc]
|
||||
cluster QuantityPointKind--><a href="../../framework/quantity_kinds.html#quantity-point-kinds" target="_top" title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:type="simple"><rect fill="#FCFCFC" height="112" style="stroke:#000000;stroke-width:1.5;" width="313" x="69" y="700"/><path d="M229,700 L229,709.2969 L219,719.2969 L69,719.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="150" x="72" y="713.9951">QuantityPointKind</text></a><!--MD5=[393655ea98b8cc7762ecac08ac25a8bc]
|
||||
entity Unit--><a href="../../framework/units.html" target="_top" title="../../framework/units.html" xlink:actuate="onRequest" xlink:href="../../framework/units.html" xlink:show="new" xlink:title="../../framework/units.html" xlink:type="simple"><rect fill="#FCFCFC" height="46.2969" style="stroke:#000000;stroke-width:1.5;" width="69" x="373.5" y="7"/><path d="M396.5,7 L396.5,12 L389.5,19 L373.5,19 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="29" x="388.5" y="39.9951">Unit</text></a><!--MD5=[203769626a5b736eb6e04c0d5326ab96]
|
||||
entity Dimension--><a href="../../framework/dimensions.html" target="_top" title="../../framework/dimensions.html" xlink:actuate="onRequest" xlink:href="../../framework/dimensions.html" xlink:show="new" xlink:title="../../framework/dimensions.html" xlink:type="simple"><rect fill="#FCFCFC" height="46.2969" style="stroke:#000000;stroke-width:1.5;" width="116" x="350" y="113"/><path d="M388.6667,113 L388.6667,118 L381.6667,125 L350,125 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="365" y="145.9951">Dimension</text></a><!--MD5=[ea03bdbd065578ac5244a06dd30cb289]
|
||||
class kind--><a href="../../framework/quantity_kinds.html#kind-creation" target="_top" title="../../framework/quantity_kinds.html#kind-creation" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#kind-creation" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#kind-creation" xlink:type="simple"><rect codeLine="16" fill="#F8F8F8" height="23.9688" id="kind" style="stroke:#383838;stroke-width:1.5;" width="99" x="236.5" y="287"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="26" x="239.5" y="303.1387">kind</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="65" x="273.5" y="284"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="63" x="274.5" y="296.1387">Dimension</text></a><!--MD5=[687e1f7389fc36adbc8b00efbcc9e77a]
|
||||
class point_kind--><a href="../../framework/quantity_kinds.html#quantity-point-kinds" target="_top" title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:type="simple"><rect codeLine="20" fill="#F8F8F8" height="23.9688" id="point_kind" style="stroke:#383838;stroke-width:1.5;" width="174" x="103" y="580.5"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="63" x="106" y="596.6387">point_kind</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="103" x="177" y="577.5"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="101" x="178" y="589.6387">Kind, PointOrigin</text></a><!--MD5=[9db4689932f79289c10697e18a3c06c1]
|
||||
class point_origin--><a href="../../framework/quantity_points.html#point-origins" target="_top" title="../../framework/quantity_points.html#point-origins" xlink:actuate="onRequest" xlink:href="../../framework/quantity_points.html#point-origins" xlink:show="new" xlink:title="../../framework/quantity_points.html#point-origins" xlink:type="simple"><rect codeLine="24" fill="#F8F8F8" height="23.9688" id="point_origin" style="stroke:#383838;stroke-width:1.5;" width="144" x="443" y="287"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="71" x="446" y="303.1387">point_origin</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="65" x="525" y="284"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="63" x="526" y="296.1387">Dimension</text></a><!--MD5=[da1b011f603b1fa92adce02fc4bac354]
|
||||
class quantity--><a href="../../framework/quantities.html#construction" target="_top" title="../../framework/quantities.html#construction" xlink:actuate="onRequest" xlink:href="../../framework/quantities.html#construction" xlink:show="new" xlink:title="../../framework/quantities.html#construction" xlink:type="simple"><rect codeLine="28" fill="#F8F8F8" height="44.7734" id="quantity" style="stroke:#383838;stroke-width:1.5;" width="184" x="574" y="418"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="47" x="577" y="434.1387">quantity</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="129" x="632" y="415"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="127" x="633" y="427.1387">Dimension, Unit, Rep</text><line style="stroke:#383838;stroke-width:1.5;" x1="575" x2="757" y1="441.9688" y2="441.9688"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="75" x="580" y="456.1792">rep number()</text></a><!--MD5=[18fbdc711d33f9ff282e1f4c30c050e6]
|
||||
class quantity_point--><a href="../../framework/quantity_points.html#construction" target="_top" title="../../framework/quantity_points.html#construction" xlink:actuate="onRequest" xlink:href="../../framework/quantity_points.html#construction" xlink:show="new" xlink:title="../../framework/quantity_points.html#construction" xlink:type="simple"><rect codeLine="34" fill="#F8F8F8" height="44.7734" id="quantity_point" style="stroke:#383838;stroke-width:1.5;" width="223" x="671.5" y="570"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="83" x="674.5" y="586.1387">quantity_point</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="132" x="765.5" y="567"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="130" x="766.5" y="579.1387">PointOrigin, Unit, Rep</text><line style="stroke:#383838;stroke-width:1.5;" x1="672.5" x2="893.5" y1="593.9688" y2="593.9688"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="102" x="677.5" y="608.1792">quantity relative()</text></a><!--MD5=[5b6ab379e9f247363b208f7c72246136]
|
||||
class quantity_kind--><a href="../../framework/quantity_kinds.html#construction" target="_top" title="../../framework/quantity_kinds.html#construction" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#construction" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#construction" xlink:type="simple"><rect codeLine="40" fill="#F8F8F8" height="44.7734" id="quantity_kind" style="stroke:#383838;stroke-width:1.5;" width="179" x="384.5" y="570"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="78" x="387.5" y="586.1387">quantity_kind</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="93" x="473.5" y="567"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="91" x="474.5" y="579.1387">Kind, Unit, Rep</text><line style="stroke:#383838;stroke-width:1.5;" x1="385.5" x2="562.5" y1="593.9688" y2="593.9688"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="107" x="390.5" y="608.1792">quantity common()</text></a><!--MD5=[6d322596e71f19471be4dbdd0c5e34a1]
|
||||
class quantity_point_kind--><a href="../../framework/quantity_kinds.html#quantity-point-kinds" target="_top" title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:actuate="onRequest" xlink:href="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:show="new" xlink:title="../../framework/quantity_kinds.html#quantity-point-kinds" xlink:type="simple"><rect codeLine="46" fill="#F8F8F8" height="44.7734" id="quantity_point_kind" style="stroke:#383838;stroke-width:1.5;" width="245" x="112.5" y="743"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="114" x="115.5" y="759.1387">quantity_point_kind</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="123" x="237.5" y="740"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="121" x="238.5" y="752.1387">PointKind, Unit, Rep</text><line style="stroke:#383838;stroke-width:1.5;" x1="113.5" x2="356.5" y1="766.9688" y2="766.9688"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="131" x="118.5" y="781.1792">quantity_kind relative()</text></a><!--MD5=[cc29d0a880a167f6baed24f1904eef31]
|
||||
reverse link Unit to Dimension--><path d="M408,58.192 C408,75.262 408,96.989 408,112.976 " fill="none" id="Unit-backto-Dimension" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="408,53.056,404,62.056,408,58.056,412,62.056,408,53.056" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[0b98293d9a517e9db9c4d9c6d74de02a]
|
||||
reverse link Dimension to Quantity--><path d="M470.945,148.015 C516.207,159.579 574.149,182.699 603,228 C632.366,274.11 638.11,309.098 603,351 C589.954,366.57 572.759,345.043 558,359 C554.7656,362.0586 552.036,365.5569 549.7362,369.3436 C549.1613,370.2902 548.6132,371.2549 548.0909,372.2352 C547.8297,372.7254 547.5749,373.2195 547.3264,373.7172 C547.2022,373.966 547.0795,374.2158 546.9584,374.4664 C546.8978,374.5917 546.8377,374.7173 546.7779,374.843 " fill="none" id="Dimension-backto-Quantity" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="466.05,146.796,473.8179,152.8508,470.9021,148.0033,475.7495,145.0875,466.05,146.796" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[fc31f3d5d7e3482da677a28e231832f1]
|
||||
reverse link Unit to Quantity--><path d="M447.467,50.131 C502.971,79.525 601.795,141.597 642,228 C665.063,277.564 678.777,310.554 642,351 C629.385,364.873 572.134,346.678 558,359 C554.6445,361.9251 551.823,365.3223 549.4555,369.0342 C548.2717,370.8901 547.2014,372.8248 546.2346,374.8185 " fill="none" id="Unit-backto-Quantity" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="442.891,47.729,449.0002,55.4541,447.318,50.0532,452.7189,48.371,442.891,47.729" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[af7c6403d4c00eaf6863e827abf137ba]
|
||||
reverse link Dimension to Kind--><path d="M344.831,152.802 C303.642,166.251 251.814,189.65 220,228 C217.5076,231.0044 215.3403,234.3076 213.4558,237.7932 C212.5135,239.536 211.642,241.3245 210.8359,243.1439 C210.7351,243.3714 210.6353,243.5993 210.5366,243.8277 " fill="none" id="Dimension-backto-Kind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="349.8,151.211,340.0087,150.1481,345.0385,152.7367,342.4499,157.7666,349.8,151.211" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[e0820a2743574ce16047da1026a45d42]
|
||||
reverse link Dimension to PointOrigin--><path d="M408,164.077 C408,175.3583 408,189.1913 408,203.6384 C408,210.862 408,218.2391 408,225.5276 C408,229.1718 408,232.7939 408,236.3636 C408,238.1484 408,239.9201 408,241.6749 C408,242.1136 408,242.5512 408,242.9878 C408,243.206 408,243.424 408,243.6417 " fill="none" id="Dimension-backto-PointOrigin" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="408,159.049,404,168.049,408,164.049,412,168.049,408,159.049" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[0171a2a578dda2fb989d4518d60e2add]
|
||||
reverse link PointOrigin to PointKind--><path d="M399.9204,307.7672 C399.6824,307.9939 399.4399,308.2246 399.1932,308.4592 C398.2064,309.3976 397.1513,310.3983 396.0354,311.4529 C393.8037,313.562 391.3291,315.887 388.673,318.3616 C378.0485,328.26 364.5185,340.552 352,351 C266.556,422.313 256.085,461.053 153,503 C139.316,508.568 98.011,501.15 87,511 C80.3646,516.936 75.8288,524.7184 72.7648,533.1048 C72.3818,534.1531 72.0218,535.2108 71.6836,536.2755 C71.599,536.5417 71.5158,536.8083 71.4339,537.0754 C71.393,537.2089 71.3524,537.3425 71.3122,537.4762 " fill="none" id="PointOrigin-backto-PointKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="399.9204,307.7672,390.6445,311.0773,396.2996,311.2154,396.1615,316.8706,399.9204,307.7672" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[d2ac93a9f2f8e7f09e3b64c12255ee7d]
|
||||
reverse link Kind to PointKind--><path d="M192.7677,312.4035 C191.175,314.8435 189.3808,317.6118 187.4119,320.6797 C179.5361,332.9512 168.8633,350.0162 157.0968,370.0396 C133.5638,410.0865 105.656,461.967 87,511 C83.834,519.321 81.0871,528.3333 78.7419,537.2139 " fill="none" id="Kind-backto-PointKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="192.7677,312.4035,184.4987,317.7536,190.0346,316.5905,191.1978,322.1265,192.7677,312.4035" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[fd164a02e043296bed0ac24e8dea3999]
|
||||
reverse link Unit to QuantityPoint--><path d="M447.88,30.995 C551.995,33.277 824,54.938 824,219 C824,219 824,219 824,300 C824,392.919 845.175,443.267 774,503 C753.698,520.038 675.219,493.863 655,511 C651.6041,513.8781 648.7521,517.2396 646.3619,520.9252 C645.1669,522.768 644.0873,524.6919 643.1129,526.6768 " fill="none" id="Unit-backto-QuantityPoint" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="442.752,30.895,451.6726,35.0691,447.7511,30.9922,451.828,27.0706,442.752,30.895" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[70cd19cb2aca3701b75cff1362c25352]
|
||||
reverse link PointOrigin to QuantityPoint--><path d="M417.0792,335.5885 C417.1578,335.8517 417.2369,336.1159 417.3166,336.3812 C417.4759,336.9117 417.6375,337.4465 417.8014,337.9854 C419.1121,342.297 420.5668,346.8737 422.1727,351.6604 C425.3844,361.2337 429.2009,371.6468 433.6805,382.4578 C451.599,425.7015 480.1275,475.3105 523,503 C544.489,516.879 558.207,497.602 580,511 C597.984,522.056 611.6847,541.2883 621.0323,558.1821 C623.3691,562.4056 625.4339,566.4829 627.2255,570.2498 C627.4495,570.7207 627.6692,571.1867 627.8846,571.6475 " fill="none" id="PointOrigin-backto-QuantityPoint" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="417.0792,335.5885,415.8213,345.3567,418.5097,340.3795,423.4869,343.068,417.0792,335.5885" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[4824db4e5b398e43184a581563085055]
|
||||
link quantity to quantity_point--><path codeLine="64" d="M683.013,463.311 C702.682,488.529 735.244,530.274 757.841,559.246 " fill="none" id="quantity-to-quantity_point" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="#383838" points="765.967,569.662,765.4305,562.4709,758.5862,560.2003,759.1227,567.3914,765.967,569.662" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[d771781a58c6bc6a1155ff477a9676a1]
|
||||
reverse link Unit to QuantityKind--><path d="M368.366,40.059 C295.58,59.302 148,111.565 148,219 C148,219 148,219 148,300 C148,395.581 144.142,443.569 219,503 C244.908,523.569 264.548,494.124 293,511 C311.157,521.7695 324.863,540.993 334.17,557.9539 C336.4968,562.1941 338.5486,566.2929 340.3263,570.0828 C340.5485,570.5566 340.7664,571.0255 340.98,571.4893 " fill="none" id="Unit-backto-QuantityKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="373.474,38.73,363.7564,37.1271,368.6354,39.99,365.7725,44.8689,373.474,38.73" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[df745d6e016be8f34c5f8c120fb76388]
|
||||
reverse link Kind to QuantityKind--><path d="M213.3487,335.0716 C213.3831,335.1598 213.4176,335.2481 213.4521,335.3364 C213.5902,335.6896 213.729,336.0431 213.8683,336.3967 C214.147,337.1039 214.4282,337.8118 214.7115,338.5193 C215.2781,339.9344 215.8535,341.3479 216.436,342.7521 C217.6008,345.5603 218.7936,348.3309 220,351 C244.587,405.4015 276.2213,464.5123 302.0095,510.5179 C314.9036,533.5207 326.3363,553.2472 334.6957,567.4707 C336.7856,571.0265 338.6834,574.2385 340.3639,577.0716 C340.574,577.4258 340.7807,577.774 340.9839,578.1163 " fill="none" id="Kind-backto-QuantityKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="213.3487,335.0716,212.8947,344.91,215.1666,339.7294,220.3472,342.0013,213.3487,335.0716" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[c1804ecabd485ae0f6f9feb5d83c0cf7]
|
||||
link quantity to quantity_kind--><path codeLine="68" d="M638.082,463.311 C604.855,489.269 549.212,532.74 512.062,561.764 " fill="none" id="quantity-to-quantity_kind" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="#383838" points="501.641,569.906,508.8317,569.3644,511.0975,562.5186,503.9068,563.0601,501.641,569.906" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[41588c27c6e4d927cf9148a254d0b3d7]
|
||||
reverse link Unit to QuantityPointKind--><path d="M368.078,31.546 C266.463,35.252 6,60.236 6,219 C6,219 6,219 6,593.5 C6,634.0025 23.1997,676.0599 40.668,708.3298 C49.4022,724.4648 58.2036,738.153 64.9558,747.9765 C65.7998,749.2044 66.6118,750.372 67.3877,751.4764 C67.7756,752.0286 68.1545,752.565 68.5238,753.0853 C68.6162,753.2153 68.7079,753.3444 68.799,753.4724 " fill="none" id="Unit-backto-QuantityPointKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="373.378,31.367,364.2472,27.6753,368.3809,31.537,364.5192,35.6707,373.378,31.367" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[7bf21d8cbe84c4088afc37d2e279dcea]
|
||||
reverse link PointKind to QuantityPointKind--><path d="M69.8533,628.7128 C69.8674,628.9804 69.8815,629.249 69.8957,629.5186 C69.9241,630.0579 69.9527,630.6011 69.9815,631.1482 C70.0391,632.2423 70.0975,633.3519 70.1566,634.4757 C70.3932,638.971 70.6418,643.694 70.8983,648.5688 C71.4115,658.3184 71.9566,668.6752 72.5016,679.0313 C72.7742,684.2093 73.0467,689.3872 73.3152,694.489 C73.3823,695.7645 73.4492,697.0352 73.5158,698.2999 C73.5324,698.6161 73.549,698.9319 73.5656,699.2473 C73.5739,699.4051 73.5822,699.5627 73.5905,699.7202 " fill="none" id="PointKind-backto-QuantityPointKind" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="69.8533,628.7128,66.3319,637.9106,70.1161,633.7059,74.3208,637.4901,69.8533,628.7128" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[cdb229abe92fd1672bac6bf302be0a95]
|
||||
link quantity_kind to quantity_point_kind--><path codeLine="72" d="M443.73,615.157 C401.286,645.525 323.949,700.859 276.264,734.976 " fill="none" id="quantity_kind-to-quantity_point_kind" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="#383838" points="265.4,742.7492,272.6072,742.5112,275.1595,735.7669,267.9523,736.0049,265.4,742.7492" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[b70cc1f6fe797c95e8c32899ac5bc65f]
|
||||
@startuml
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide circle
|
||||
hide members
|
||||
show class methods
|
||||
|
||||
package Unit <<Frame>> [[../../framework/units.html]] {
|
||||
}
|
||||
|
||||
package Dimension <<Frame>> [[../../framework/dimensions.html]] {
|
||||
}
|
||||
|
||||
package Kind <<Frame>> [[../../framework/quantity_kinds.html#kind-creation]] {
|
||||
abstract kind<Dimension> [[../../framework/quantity_kinds.html#kind-creation]]
|
||||
}
|
||||
|
||||
package PointKind <<Frame>> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
abstract point_kind<Kind, PointOrigin> [[../../framework/quantity_kinds.html#quantity-point-kinds]]
|
||||
}
|
||||
|
||||
package PointOrigin <<Frame>> [[../../framework/quantity_points.html#point-origins]] {
|
||||
abstract point_origin<Dimension> [[../../framework/quantity_points.html#point-origins]]
|
||||
}
|
||||
|
||||
package Quantity <<Frame>> [[../../framework/quantities.html]] {
|
||||
class quantity<Dimension, Unit, Rep> [[../../framework/quantities.html#construction]] {
|
||||
rep number()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityPoint <<Frame>> [[../../framework/quantity_points.html]] {
|
||||
class quantity_point<PointOrigin, Unit, Rep> [[../../framework/quantity_points.html#construction]] {
|
||||
quantity relative()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityKind <<Frame>> [[../../framework/quantity_kinds.html]] {
|
||||
class quantity_kind<Kind, Unit, Rep> [[../../framework/quantity_kinds.html#construction]] {
|
||||
quantity common()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityPointKind <<Frame>> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
class quantity_point_kind<PointKind, Unit, Rep> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
quantity_kind relative()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Unit <.. Dimension
|
||||
|
||||
Dimension <... Quantity
|
||||
Unit <... Quantity
|
||||
|
||||
Dimension <... Kind
|
||||
Dimension <... PointOrigin
|
||||
PointOrigin <... PointKind
|
||||
Kind <... PointKind
|
||||
|
||||
Unit <... QuantityPoint
|
||||
PointOrigin <... QuantityPoint
|
||||
quantity - -* quantity_point
|
||||
|
||||
Unit <... QuantityKind
|
||||
Kind <... QuantityKind
|
||||
quantity - -* quantity_kind
|
||||
|
||||
Unit <... QuantityPointKind
|
||||
PointKind <... QuantityPointKind
|
||||
quantity_kind - -* quantity_point_kind
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2021.12(Tue Oct 05 16:01:58 UTC 2021)
|
||||
(GPL source distribution)
|
||||
Java Runtime: Java(TM) SE Runtime Environment
|
||||
JVM: Java HotSpot(TM) 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
Before Width: | Height: | Size: 27 KiB |
35
docs/_static/img/dimensions.svg
vendored
35
docs/_static/img/dimensions.svg
vendored
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="256px" preserveAspectRatio="none" style="width:271px;height:256px;background:#FCFCFC;" version="1.1" viewBox="0 0 271 256" width="271px" zoomAndPan="magnify"><defs/><g><!--MD5=[3235af1cc77a6acc457ea7021772201c]
|
||||
cluster Dimension--><rect fill="#FCFCFC" height="243" style="stroke:#000000;stroke-width:1.5;" width="258" x="7" y="7"/><path d="M101,7 L101,16.2969 L91,26.2969 L7,26.2969 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="84" x="10" y="20.9951">Dimension</text><!--MD5=[418e3bda8d8c8b7ad8dc503f3566e869]
|
||||
class base_dimension--><a href="../../framework/units.html" target="_top" title="../../framework/units.html" xlink:actuate="onRequest" xlink:href="../../framework/units.html" xlink:show="new" xlink:title="../../framework/units.html" xlink:type="simple"><rect codeLine="9" fill="#F8F8F8" height="23.9688" id="base_dimension" style="stroke:#383838;stroke-width:1.5;" width="184" x="44" y="42"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="96" x="47" y="58.1387">base_dimension</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="80" x="151" y="39"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="78" x="152" y="51.1387">Symbol, Unit</text></a><!--MD5=[68f31181282be310d7d3efc1882b33d4]
|
||||
class exponent--><a href="../../framework/dimensions.html#derived-dimensions" target="_top" title="../../framework/dimensions.html#derived-dimensions" xlink:actuate="onRequest" xlink:href="../../framework/dimensions.html#derived-dimensions" xlink:show="new" xlink:title="../../framework/dimensions.html#derived-dimensions" xlink:type="simple"><rect codeLine="10" fill="#F8F8F8" height="23.9688" id="exponent" style="stroke:#383838;stroke-width:1.5;" width="199" x="36.5" y="126"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="57" x="39.5" y="142.1387">exponent</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="134" x="104.5" y="123"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="132" x="105.5" y="135.1387">Dimension, Num, Den</text></a><!--MD5=[21e724ef10c67d921f6b3fcb22c06f35]
|
||||
class derived_dimension--><a href="../../framework/dimensions.html#derived-dimensions" target="_top" title="../../framework/dimensions.html#derived-dimensions" xlink:actuate="onRequest" xlink:href="../../framework/dimensions.html#derived-dimensions" xlink:show="new" xlink:title="../../framework/dimensions.html#derived-dimensions" xlink:type="simple"><rect codeLine="11" fill="#F8F8F8" height="23.9688" id="derived_dimension" style="stroke:#383838;stroke-width:1.5;" width="226" x="23" y="210"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="113" x="26" y="226.1387">derived_dimension</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="105" x="147" y="207"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="103" x="148" y="219.1387">Unit, Exponent...</text></a><!--MD5=[a178719c9c6142e046a1431351c96a28]
|
||||
reverse link base_dimension to exponent--><path codeLine="13" d="M136,71.197 C136,87.356 136,111.751 136,125.854 " fill="none" id="base_dimension-backto-exponent" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="136,66.059,132,75.059,136,71.059,140,75.059,136,66.059" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[cd03d9c68e1638ad57e35f0e1135acfc]
|
||||
reverse link exponent to derived_dimension--><path codeLine="14" d="M125.605,155.197 C122.073,171.3561 122.514,195.7514 126.928,209.8544 " fill="none" id="exponent-backto-derived_dimension" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="126.955,150.059,120.8001,157.7477,125.6849,154.895,128.5377,159.7799,126.955,150.059" style="stroke:#383838;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="24" x="94.2358" y="198.8513">0..n</text><!--MD5=[1f4f10499975d495bfeb71f1fbda2882]
|
||||
link exponent to derived_dimension--><path codeLine="15" d="M145.577,150.059 C150.268,164.12 150.752,188.5106 147.03,204.7039 " fill="none" id="exponent-to-derived_dimension" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="145.606,209.8544,151.859,202.2452,146.938,205.0351,144.1481,200.1141,145.606,209.8544" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[da6c529a5f75ef54a9908f22b56975b6]
|
||||
@startuml
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide members
|
||||
hide circle
|
||||
|
||||
package Dimension <<Frame>> {
|
||||
abstract base_dimension<Symbol, Unit> [[../../framework/units.html]]
|
||||
abstract exponent<Dimension, Num, Den> [[../../framework/dimensions.html#derived-dimensions]]
|
||||
abstract derived_dimension<Unit, Exponent...> [[../../framework/dimensions.html#derived-dimensions]]
|
||||
|
||||
base_dimension <.. exponent
|
||||
exponent <.. "0..n" derived_dimension
|
||||
exponent ..> derived_dimension
|
||||
}
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2021.12(Tue Oct 05 16:01:58 UTC 2021)
|
||||
(GPL source distribution)
|
||||
Java Runtime: Java(TM) SE Runtime Environment
|
||||
JVM: Java HotSpot(TM) 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
Before Width: | Height: | Size: 5.8 KiB |
BIN
docs/_static/img/downcast_1.png
vendored
BIN
docs/_static/img/downcast_1.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
BIN
docs/_static/img/downcast_2.png
vendored
BIN
docs/_static/img/downcast_2.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
37
docs/_static/img/quantity_like.svg
vendored
37
docs/_static/img/quantity_like.svg
vendored
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="348px" preserveAspectRatio="none" style="width:288px;height:348px;background:#FCFCFC;" version="1.1" viewBox="0 0 288 348" width="288px" zoomAndPan="magnify"><defs/><g><!--MD5=[da1b011f603b1fa92adce02fc4bac354]
|
||||
class quantity--><a href="../framework/quantities.html" target="_top" title="../framework/quantities.html" xlink:actuate="onRequest" xlink:href="../framework/quantities.html" xlink:show="new" xlink:title="../framework/quantities.html" xlink:type="simple"><g id="elem_quantity"><rect codeLine="8" fill="#F1F1F1" height="26.2969" id="quantity" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="66" x="80" y="110"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="60" x="83" y="127.9951">quantity</text></g></a><!--MD5=[18fbdc711d33f9ff282e1f4c30c050e6]
|
||||
class quantity_point--><a href="../framework/quantity_points.html" target="_top" title="../framework/quantity_points.html" xlink:actuate="onRequest" xlink:href="../framework/quantity_points.html" xlink:show="new" xlink:title="../framework/quantity_points.html" xlink:type="simple"><g id="elem_quantity_point"><rect codeLine="9" fill="#F1F1F1" height="26.2969" id="quantity_point" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="112" x="7" y="213"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="106" x="10" y="230.9951">quantity_point</text></g></a><!--MD5=[5b6ab379e9f247363b208f7c72246136]
|
||||
class quantity_kind--><a href="../framework/quantity_kinds.html" target="_top" title="../framework/quantity_kinds.html" xlink:actuate="onRequest" xlink:href="../framework/quantity_kinds.html" xlink:show="new" xlink:title="../framework/quantity_kinds.html" xlink:type="simple"><g id="elem_quantity_kind"><rect codeLine="10" fill="#F1F1F1" height="26.2969" id="quantity_kind" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="104" x="154" y="213"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="98" x="157" y="230.9951">quantity_kind</text></g></a><!--MD5=[6d322596e71f19471be4dbdd0c5e34a1]
|
||||
class quantity_point_kind--><a href="../framework/quantity_kinds.html#quantity-point-kinds" target="_top" title="../framework/quantity_kinds.html#quantity-point-kinds" xlink:actuate="onRequest" xlink:href="../framework/quantity_kinds.html#quantity-point-kinds" xlink:show="new" xlink:title="../framework/quantity_kinds.html#quantity-point-kinds" xlink:type="simple"><g id="elem_quantity_point_kind"><rect codeLine="11" fill="#F1F1F1" height="26.2969" id="quantity_point_kind" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="150" x="131" y="316"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="144" x="134" y="333.9951">quantity_point_kind</text></g></a><!--MD5=[b2a694e6474a2a9b22a2e31fbfd4909a]
|
||||
class Rep--><g id="elem_Rep"><rect fill="#F1F1F1" height="26.2969" id="Rep" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="35" x="95.5" y="7"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="29" x="98.5" y="24.9951">Rep</text></g><!--MD5=[e24fe1f9fefda9999290bb447fae99e3]
|
||||
reverse link Rep to quantity--><g id="link_Rep_quantity"><path codeLine="13" d="M113,38.526 C113,58.92 113,92.061 113,109.83 " fill="none" id="Rep-backto-quantity" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="113,33.385,109,42.385,113,38.385,117,42.385,113,33.385" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="60" x="114" y="76.0669">number()</text></g><!--MD5=[90d8d95e9adcc8fc2f6906e762b4a14d]
|
||||
reverse link quantity to quantity_point--><g id="link_quantity_quantity_point"><path codeLine="14" d="M98.633,140.033 C92.5205,147.508 85.7271,156.776 81,166 C73.1851,181.249 68.1076,200.483 65.3984,212.765 " fill="none" id="quantity-backto-quantity_point" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="101.9413,136.076,93.0996,140.4147,98.7341,139.9118,99.2369,145.5463,101.9413,136.076" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="58" x="82" y="179.0669">relative()</text></g><!--MD5=[dd075b90f0ec4f5db24762fad9b93a06]
|
||||
reverse link quantity to quantity_kind--><g id="link_quantity_quantity_kind"><path codeLine="15" d="M127.956,140.242 C146.612,160.503 178.084,194.683 194.794,212.83 " fill="none" id="quantity-backto-quantity_kind" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="124.404,136.385,127.5577,145.7153,127.7908,140.0632,133.4429,140.2964,124.404,136.385" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="67" x="167" y="179.0669">common()</text></g><!--MD5=[1acbd4671b34e1d8b20d7848e474454e]
|
||||
reverse link quantity_kind to quantity_point_kind--><g id="link_quantity_kind_quantity_point_kind"><path codeLine="16" d="M206,244.5264 C206,264.9203 206,298.0611 206,315.8296 " fill="none" id="quantity_kind-backto-quantity_point_kind" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="206,239.385,202,248.385,206,244.385,210,248.385,206,239.385" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="58" x="207" y="282.0669">relative()</text></g><!--MD5=[abc9f5195c71d2db961c2d927d457aba]
|
||||
@startuml
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide members
|
||||
hide circle
|
||||
|
||||
class quantity [[../framework/quantities.html]]
|
||||
class quantity_point [[../framework/quantity_points.html]]
|
||||
class quantity_kind [[../framework/quantity_kinds.html]]
|
||||
class quantity_point_kind [[../framework/quantity_kinds.html#quantity-point-kinds]]
|
||||
|
||||
Rep <- - quantity : number()
|
||||
quantity <- - quantity_point : relative()
|
||||
quantity <- - quantity_kind : common()
|
||||
quantity_kind <- - quantity_point_kind : relative()
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2022.6beta5(Unknown compile time)
|
||||
(GPL source distribution)
|
||||
Java Runtime: Java(TM) SE Runtime Environment
|
||||
JVM: Java HotSpot(TM) 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
Before Width: | Height: | Size: 6.4 KiB |
158
docs/_static/img/units.svg
vendored
158
docs/_static/img/units.svg
vendored
@ -1,158 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="456px" preserveAspectRatio="none" style="width:591px;height:456px;background:#FCFCFC;" version="1.1" viewBox="0 0 591 456" width="591px" zoomAndPan="magnify">
|
||||
<defs />
|
||||
<g>
|
||||
<!--MD5=[197a77df23d290968e58c76a2239d979]
|
||||
cluster Unit-->
|
||||
<g id="cluster_Unit">
|
||||
<a href="../../framework/units.html" target="_top" title="../../framework/units.html" xlink:actuate="onRequest" xlink:href="../../framework/units.html" xlink:show="new" xlink:title="../../framework/units.html" xlink:type="simple">
|
||||
<rect height="443" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;fill:none;" width="578" x="7" y="7" />
|
||||
<path d="M51,7 L51,16.2969 L41,26.2969 L7,26.2969 " fill="none" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="34" x="10" y="20.9951">Unit</text>
|
||||
</a>
|
||||
</g> <!--MD5=[124cbcdfdb408a63d08476bd52d3bb38]
|
||||
class scaled_unit-->
|
||||
<g id="elem_scaled_unit">
|
||||
<rect codeLine="12" fill="#F1F1F1" height="26.2969" id="scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="178" x="23" y="225" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="80" x="26" y="242.9951">scaled_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="90" x="114" y="222" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="88" x="115" y="234.1387">UnitRatio, Unit</text>
|
||||
</g> <!--MD5=[c262fc293e71d96455ecd38c5cba51e9]
|
||||
class prefixed_alias_unit-->
|
||||
<a href="../../framework/units.html#aliased-units" target="_top" title="../../framework/units.html#aliased-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#aliased-units" xlink:show="new" xlink:title="../../framework/units.html#aliased-units" xlink:type="simple">
|
||||
<g id="elem_prefixed_alias_unit">
|
||||
<rect codeLine="14" fill="#F1F1F1" height="26.2969" id="prefixed_alias_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="269" x="280.5" y="408" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="133" x="283.5" y="425.9951">prefixed_alias_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="128" x="424.5" y="405" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="126" x="425.5" y="417.1387">Unit, Prefix, AliasUnit</text>
|
||||
</g>
|
||||
</a> <!--MD5=[80b1f1fe027b66c9bd530ac9502a064a]
|
||||
class alias_unit-->
|
||||
<a href="../../framework/units.html#aliased-units" target="_top" title="../../framework/units.html#aliased-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#aliased-units" xlink:show="new" xlink:title="../../framework/units.html#aliased-units" xlink:type="simple">
|
||||
<g id="elem_alias_unit">
|
||||
<rect codeLine="15" fill="#F1F1F1" height="26.2969" id="alias_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="155" x="337.5" y="347" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="67" x="340.5" y="364.9951">alias_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="80" x="415.5" y="344" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="78" x="416.5" y="356.1387">Unit, Symbol</text>
|
||||
</g>
|
||||
</a> <!--MD5=[26e0af737c6dfe4c6ad8ee7c79493d2e]
|
||||
class derived_scaled_unit-->
|
||||
<a href="../../framework/units.html#derived-scaled-units" target="_top" title="../../framework/units.html#derived-scaled-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#derived-scaled-units" xlink:show="new" xlink:title="../../framework/units.html#derived-scaled-units" xlink:type="simple">
|
||||
<g id="elem_derived_deduced_unit">
|
||||
<rect codeLine="16" fill="#F1F1F1" height="26.2969" id="derived_scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="308" x="261" y="286" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="157" x="264" y="303.9951">derived_scaled_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="143" x="429" y="283" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="141" x="430" y="295.1387">Dimension, Unit, Unit...</text>
|
||||
</g>
|
||||
</a> <!--MD5=[21a38f8b465de3a6a580896bb83abf03]
|
||||
class derived_unit-->
|
||||
<a href="../../framework/units.html#derived-unnamed-units" target="_top" title="../../framework/units.html#derived-unnamed-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#derived-unnamed-units" xlink:show="new" xlink:title="../../framework/units.html#derived-unnamed-units" xlink:type="simple">
|
||||
<g id="elem_derived_unit">
|
||||
<rect codeLine="17" fill="#F1F1F1" height="26.2969" id="derived_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="94" x="368" y="225" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="88" x="371" y="242.9951">derived_unit</text>
|
||||
</g>
|
||||
</a> <!--MD5=[002996a525ad7ee43e1a2ae0bbb7adb6]
|
||||
class prefixed_unit-->
|
||||
<a href="../../framework/units.html#prefixed-unit" target="_top" title="../../framework/units.html#prefixed-unit" xlink:actuate="onRequest" xlink:href="../../framework/units.html#prefixed-unit" xlink:show="new" xlink:title="../../framework/units.html#prefixed-unit" xlink:type="simple">
|
||||
<g id="elem_prefixed_unit">
|
||||
<rect codeLine="18" fill="#F1F1F1" height="26.2969" id="prefixed_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="169" x="330.5" y="164" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="93" x="333.5" y="181.9951">prefixed_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="68" x="434.5" y="161" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="66" x="435.5" y="173.1387">Prefix, Unit</text>
|
||||
</g>
|
||||
</a> <!--MD5=[3a0c8cf47fc662100af5bce8b7f7e204]
|
||||
class named_scaled_unit-->
|
||||
<a href="../../framework/units.html#named-scaled-units" target="_top" title="../../framework/units.html#named-scaled-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#named-scaled-units" xlink:show="new" xlink:title="../../framework/units.html#named-scaled-units" xlink:type="simple">
|
||||
<g id="elem_named_scaled_unit">
|
||||
<rect codeLine="19" fill="#F1F1F1" height="26.2969" id="named_scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="263" x="283.5" y="103" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="137" x="286.5" y="120.9951">named_scaled_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="118" x="431.5" y="100" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="116" x="432.5" y="112.1387">Symbol, Ratio, Unit</text>
|
||||
</g>
|
||||
</a> <!--MD5=[5e57872b30d77ee0da3206dd3d117986]
|
||||
class named_unit-->
|
||||
<a href="../../framework/units.html#base-units" target="_top" title="../../framework/units.html#base-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#base-units" xlink:show="new" xlink:title="../../framework/units.html#base-units" xlink:type="simple">
|
||||
<g id="elem_named_unit">
|
||||
<rect codeLine="20" fill="#F1F1F1" height="26.2969" id="named_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="139" x="345.5" y="42" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="84" x="348.5" y="59.9951">named_unit</text>
|
||||
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="47" x="440.5" y="39" />
|
||||
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="45" x="441.5" y="51.1387">Symbol</text>
|
||||
</g>
|
||||
</a> <!--MD5=[d10f3427b03caf67d8b4e569e5f4936e]
|
||||
reverse link scaled_unit to named_unit-->
|
||||
<g id="link_scaled_unit_named_unit">
|
||||
<path codeLine="22" d="M133.027,208.194 C158.437,172.883 205.676,115.067 261,85 C286.686,71.041 317.93,63.52 345.471,59.49 " fill="none" id="scaled_unit-backto-named_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="138.679,212.326,121.521,224.76,127.181,204.34,138.679,212.326" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[c4573f7b87c3262f7d3adc92106a39ed]
|
||||
reverse link scaled_unit to named_scaled_unit-->
|
||||
<g id="link_scaled_unit_named_scaled_unit">
|
||||
<path codeLine="23" d="M145.911,212.637 C174.734,191.666 218.536,162.71 261,146 C279.262,138.814 299.451,133.292 319.011,129.068 " fill="none" id="scaled_unit-backto-named_scaled_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="149.884,218.407,129.672,224.769,141.505,207.191,149.884,218.407" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[65b74da07c0359a7bcc888d9c9b6e7d5]
|
||||
reverse link scaled_unit to prefixed_unit-->
|
||||
<g id="link_scaled_unit_prefixed_unit">
|
||||
<path codeLine="24" d="M194.254,220.784 C215.93,216.246 239.344,211.391 261,207 C288.988,201.325 319.892,195.233 346.556,190.03 " fill="none" id="scaled_unit-backto-prefixed_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="195.542,227.667,174.53,224.927,192.664,213.966,195.542,227.667" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[29a2e6b65a8256359df6b41e4d3b7c7c]
|
||||
reverse link scaled_unit to derived_unit-->
|
||||
<g id="link_scaled_unit_derived_unit">
|
||||
<path codeLine="25" d="M221.579,238 C271.79,238 328.764,238 367.604,238 " fill="none" id="scaled_unit-backto-derived_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="221.276,245,201.276,238,221.276,231,221.276,245" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[1916bf928027667941dfca121ed1aff3]
|
||||
reverse link scaled_unit to derived_scaled_unit-->
|
||||
<g id="link_scaled_unit_derived_deduced_unit">
|
||||
<path codeLine="26" d="M197.3,255.089 C218.121,259.31 240.369,263.819 261,268 C290.086,273.894 322.282,280.418 349.606,285.954 " fill="none" id="scaled_unit-backto-derived_scaled_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="195.683,261.904,177.472,251.07,198.464,248.183,195.683,261.904" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[19d99332ae619b76851ceaa34f4e9014]
|
||||
reverse link scaled_unit to alias_unit-->
|
||||
<g id="link_scaled_unit_alias_unit">
|
||||
<path codeLine="27" d="M145.982,263.005 C174.849,283.698 218.676,312.311 261,329 C285.078,338.494 312.484,345.219 337.384,349.919 " fill="none" id="scaled_unit-backto-alias_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="141.677,268.529,129.714,251.039,149.972,257.251,141.677,268.529" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[a61d68e6008f4d1392d92030b50774f1]
|
||||
reverse link scaled_unit to prefixed_alias_unit-->
|
||||
<g id="link_scaled_unit_prefixed_alias_unit">
|
||||
<path codeLine="28" d="M133.104,267.552 C158.592,302.572 205.908,359.952 261,390 C275.157,397.7215 290.998,403.5283 306.976,407.8934 " fill="none" id="scaled_unit-backto-prefixed_alias_unit" style="stroke:#181818;stroke-width:1.0;" />
|
||||
<polygon fill="none" points="127.332,271.513,121.559,251.125,138.786,263.462,127.332,271.513" style="stroke:#181818;stroke-width:1.0;" />
|
||||
</g> <!--MD5=[f18d7856f7539404df991684234dc7ed]
|
||||
@startuml
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide members
|
||||
hide circle
|
||||
|
||||
left to right direction
|
||||
|
||||
package Unit <<Frame>> [[../../framework/units.html]] {
|
||||
|
||||
abstract scaled_unit<UnitRatio, Unit>
|
||||
|
||||
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
|
||||
abstract alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
|
||||
abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
|
||||
abstract derived_unit [[../../framework/units.html#derived-unnamed-units]]
|
||||
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
|
||||
abstract named_scaled_unit<Symbol, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
|
||||
abstract named_unit<Symbol> [[../../framework/units.html#base-units]]
|
||||
|
||||
scaled_unit <|- - named_unit
|
||||
scaled_unit <|- - named_scaled_unit
|
||||
scaled_unit <|- - prefixed_unit
|
||||
scaled_unit <|- - derived_unit
|
||||
scaled_unit <|- - derived_scaled_unit
|
||||
scaled_unit <|- - alias_unit
|
||||
scaled_unit <|- - prefixed_alias_unit
|
||||
}
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2022.5(Sat Apr 30 10:55:52 UTC 2022)
|
||||
(GPL source distribution)
|
||||
Java Runtime: Java(TM) SE Runtime Environment
|
||||
JVM: Java HotSpot(TM) 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
-->
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 14 KiB |
0
docs/appendix/glossary.md
Normal file
0
docs/appendix/glossary.md
Normal file
1
docs/appendix/release_notes.md
Symbolic link
1
docs/appendix/release_notes.md
Symbolic link
@ -0,0 +1 @@
|
||||
../../CHANGELOG.md
|
139
docs/conf.py
139
docs/conf.py
@ -1,139 +0,0 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options.
|
||||
# For a full list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def get_version():
|
||||
try:
|
||||
with open("../src/CMakeLists.txt", "r") as file:
|
||||
content = file.read()
|
||||
version = re.search(
|
||||
r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content
|
||||
).group(1)
|
||||
return version.strip()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "mp-units"
|
||||
copyright = "2018-present, Mateusz Pusz"
|
||||
author = "Mateusz Pusz"
|
||||
|
||||
# The major project version, used as the replacement for |version|.
|
||||
version = get_version()
|
||||
|
||||
# The full project version, used as the replacement for |release| and
|
||||
# e.g. in the HTML templates.
|
||||
release = get_version()
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autosectionlabel",
|
||||
"sphinx.ext.githubpages",
|
||||
"sphinx.ext.graphviz",
|
||||
"sphinx_rtd_theme",
|
||||
"recommonmark",
|
||||
"breathe",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
# If true, Sphinx will warn about all references where the target cannot
|
||||
# be found. Default is False.
|
||||
nitpicky = True
|
||||
|
||||
# A list of (type, target) tuples (by default empty) that should be ignored
|
||||
# when generating warnings in “nitpicky mode”. Note that type should include
|
||||
# the domain name if present. Example entries would be ('py:func', 'int')
|
||||
# or ('envvar', 'LD_LIBRARY_PATH').
|
||||
nitpick_ignore = []
|
||||
|
||||
# True to prefix each section label with the name of the document it is in,
|
||||
# followed by a colon. Useful for avoiding ambiguity when the same section
|
||||
# heading appears in different documents.
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
# -- C++ configuration ---------------------------------------------------
|
||||
|
||||
# The name of the default domain. Can also be None to disable a default
|
||||
# domain. The default is 'py'.
|
||||
primary_domain = "cpp"
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
default_role = "cpp:any"
|
||||
|
||||
# The default language to highlight source code in. The default is 'python3'.
|
||||
# The value should be a valid Pygments lexer name (https://pygments.org/docs/lexers).
|
||||
highlight_language = "cpp"
|
||||
|
||||
# The style name to use for Pygments highlighting of source code. If not set,
|
||||
# either the theme’s default style or 'sphinx' is selected for HTML output.
|
||||
pygments_style = "default"
|
||||
|
||||
# A list of prefixes that will be ignored when sorting C++ objects in the global
|
||||
# index. For example ['awesome_lib::'].
|
||||
cpp_index_common_prefix = ["units::"]
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# A dictionary of options that influence the look and feel of the selected theme.
|
||||
# These are theme-specific.
|
||||
html_theme_options = {
|
||||
# WARNING: unsupported theme option 'github_url' given
|
||||
# 'github_url': 'https://github.com/mpusz/units'
|
||||
}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# If given, this must be the name of an image file (path relative to the
|
||||
# configuration directory) that is the logo of the docs. It is placed at the
|
||||
# top of the sidebar; its width should therefore not exceed 200 pixels.
|
||||
# Default: None.
|
||||
# html_logo =
|
||||
|
||||
# These paths are either relative to html_static_path or fully qualified
|
||||
# paths (eg. https://...)
|
||||
html_css_files = ["css/custom.css"]
|
||||
|
||||
|
||||
# -- Breathe configuration ---------------------------------------------------
|
||||
|
||||
|
||||
# This should be a dictionary in which the keys are project names and the values
|
||||
# are paths to the folder containing the doxygen output for that project.
|
||||
breathe_projects = {"mp-units": "build/xml"}
|
||||
|
||||
# This should match one of the keys in the breathe_projects dictionary and
|
||||
# indicates which project should be used when the project is not specified on
|
||||
# the directive.
|
||||
breathe_default_project = "mp-units"
|
||||
|
||||
# Allows you to specify domains for particular files according to their extension.
|
||||
breathe_domain_by_extension = {"h": "cpp"}
|
||||
|
||||
# Provides the directive flags that should be applied to all directives which
|
||||
# take :members:, :private-members: and :undoc-members: options. By default,
|
||||
# this is set to an empty list, which means no members are displayed.
|
||||
breathe_default_members = ("members",)
|
@ -1,9 +0,0 @@
|
||||
Defining Systems
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
defining_systems/isq
|
||||
defining_systems/si
|
||||
defining_systems/angular_units
|
@ -1,175 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Angular Units
|
||||
=============
|
||||
|
||||
Some background information
|
||||
---------------------------
|
||||
|
||||
As per today's SI, both radian and steradian are dimensionless. This forces the convention to set the angle ``1 radian``
|
||||
equal to the number ``1`` within equations (similar to what natural units system does for ``c`` constant).
|
||||
|
||||
Following `Wikipedia <https://en.wikipedia.org/wiki/Radian#Dimensional_analysis>`_:
|
||||
|
||||
Giacomo Prando says "the current state of affairs leads inevitably to ghostly appearances and disappearances of the radian
|
||||
in the dimensional analysis of physical equations." For example, a mass hanging by a string from a pulley will rise or drop
|
||||
by :math:`y=rθ`` centimeters, where :math:`r` is the radius of the pulley in centimeters and :math:`θ` is the angle
|
||||
the pulley turns in radians. When multiplying :math:`r` by :math:`θ` the unit of radians disappears from the result.
|
||||
Similarly in the formula for the angular velocity of a rolling wheel, :math:`ω=v/r`, radians appear in the units of
|
||||
:math:`ω` but not on the right hand side.
|
||||
Anthony French calls this phenomenon "a perennial problem in the teaching of mechanics". Oberhofer says that the typical
|
||||
advice of ignoring radians during dimensional analysis and adding or removing radians in units according to convention
|
||||
and contextual knowledge is "pedagogically unsatisfying".
|
||||
|
||||
At least a dozen scientists have made proposals to treat the radian as a base unit of measure defining its own dimension of "angle",
|
||||
as early as 1936 and as recently as 2022. This would bring the advantages of a physics-based, consistent, and logically-robust
|
||||
unit system, with unambiguous units for all physical quantities. At the same time the only notable changes for typical
|
||||
end-users would be: improved units for the quantities **torque**, **angular momentum** and **moment of inertia**.
|
||||
|
||||
Paul Quincey in his proposal *"Angles in the SI: a detailed proposal for solving the problem"* [Quincey]_ states:
|
||||
|
||||
The familiar units assigned to some angular quantities are based on equations that have adopted the radian convention,
|
||||
and so are missing `rad`s that would be present if the complete equation is used. The physically-correct units are
|
||||
those with the `rad`s reinstated. Numerical values would not change, and the physical meanings of all quantities would
|
||||
also be unaffected.
|
||||
|
||||
He proposes the following changes:
|
||||
|
||||
- The **radian** would become either a new base unit or a 'complementary' unit
|
||||
- The **steradian** would become a derived unit equal to :math:`1\:rad^2`
|
||||
- The SI units for
|
||||
|
||||
- **Torque** would change from :math:`N\:m` (= J) to :math:`J\:rad^{-1}`
|
||||
- **Angular momentum** would change from :math:`J\:s` to :math:`J\:s\:rad^{-1}` (i.e. :math:`J/(rad/s)`)
|
||||
- **Moment of inertia** would change from :math:`kg\:m^2` to :math:`kg\:m^2\:rad^{-2}` (i.e. :math:`J/(rad/s)^2`)
|
||||
|
||||
- The option to omit the radian from the SI units for **angle**, **angular velocity**, **angular frequency**,
|
||||
**angular acceleration**, and **angular wavenumber** would be removed, the only correct SI units being
|
||||
:math:`rad`, :math:`rad/s`, :math:`rad/s`, :math:`rad/s^2` and :math:`rad/m` respectively.
|
||||
|
||||
Paul Quincey summarizes that with the above in action:
|
||||
|
||||
However, the physical clarity this would build into the SI should be recognised very quickly. The units would tell us that
|
||||
:math:`torque \times angle = energy`, and :math:`angular\:momentum \times angle = action`, for example, in the same way that they do for
|
||||
:math:`force \times distance = energy`, :math:`linear\:momentum \times distance = action`, and
|
||||
:math:`radiant\:intensity \times solid\:angle = radiant\:flux`.
|
||||
Dimensional analysis could be used to its full extent. Software involving angular quantities would be rationalised.
|
||||
Arguments about the correct units for frequency and angular frequency, and the meaning of the unit Hz, could be left behind.
|
||||
The explanation of these changes would be considerably easier and more rewarding than explaining how a kilogram-sized mass
|
||||
can be measured in terms of the Planck constant.
|
||||
|
||||
|
||||
Angular quantities in the :term:`SI`
|
||||
------------------------------------
|
||||
|
||||
Even though the :term:`SI` somehow ignores the dimensionality of angle:
|
||||
|
||||
Plane and solid angles, when expressed in radians and steradians respectively, are in effect
|
||||
also treated within the SI as quantities with the unit one. The symbols :math:`rad`
|
||||
and :math:`sr` are written explicitly where appropriate, in order to emphasize that, for radians or
|
||||
steradians, the quantity being considered is, or involves the plane angle or solid angle
|
||||
respectively. For steradians it emphasizes the distinction between units of flux and intensity
|
||||
in radiometry and photometry for example. However, it is a long-established practice in
|
||||
mathematics and across all areas of science to make use of :math:`rad = 1` and :math:`sr = 1`.
|
||||
For historical reasons the radian and steradian are treated as derived units.
|
||||
|
||||
It also explicitly states:
|
||||
|
||||
The SI unit of frequency is hertz, the SI unit of angular velocity and angular frequency is
|
||||
radian per second, and the SI unit of activity is becquerel, implying counts per second.
|
||||
Although it is formally correct to write all three of these units as the reciprocal second, the
|
||||
use of the different names emphasizes the different nature of the quantities concerned. It is
|
||||
especially important to carefully distinguish frequencies from angular frequencies, because
|
||||
by definition their numerical values differ by a factor of :math:`2\pi`. Ignoring this fact may cause
|
||||
an error of :math:`2\pi`. Note that in some countries, frequency values are conventionally expressed
|
||||
using “cycle/s” or “cps” instead of the SI unit :math:`Hz`, although “cycle” and “cps” are not units
|
||||
in the SI. Note also that it is common, although not recommended, to use the term
|
||||
frequency for quantities expressed in :math:`rad/s`. Because of this, it is recommended that
|
||||
quantities called “frequency”, “angular frequency”, and “angular velocity” always be given
|
||||
explicit units of :math:`Hz` or :math:`rad/s`` and not :math:`s^{-1}`.
|
||||
|
||||
|
||||
Angular quantities in the library
|
||||
---------------------------------
|
||||
|
||||
The mp-units library strives to define physically-correct quantities and their units to provide maximum help
|
||||
to its users. As treating angle as a dimensional quantity can lead to many "trivial" mistakes in dimensional
|
||||
analysis and calculation, it was decided to follow the above approach and treat angle as a base quantity
|
||||
with a base unit of radian and solid angle as its derived quantity.
|
||||
|
||||
As those the above (at least for now) not a part of :term:`SI`, the plain angle and solid
|
||||
angle definitions can be found in the *units/generic* subdirectory. However, in the sake of correctness,
|
||||
they are consistently used in the dimensional recipes of all angle-based :term:`SI` quantities like
|
||||
torque or angular velocity::
|
||||
|
||||
#include <units/generic/angle.h>
|
||||
#include <units/isq/si/torque.h>
|
||||
#include <units/math.h>
|
||||
#include <units/quantity_io.h>
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace units;
|
||||
using namespace units::isq;
|
||||
using namespace units::aliases;
|
||||
using namespace units::aliases::isq::si;
|
||||
|
||||
const Length auto lever = cm<>(20);
|
||||
const Force auto force = N<>(500);
|
||||
const Angle auto angle = deg<>(90);
|
||||
const Torque auto torque = lever * force * sin(angle) / cotes_angle<>;
|
||||
|
||||
std::cout << "Applying a perpendicular force of " << force << " to a "
|
||||
<< lever << " long lever results in "
|
||||
<< quantity_cast<si::newton_metre_per_radian>(torque) << " of torque.\n";
|
||||
}
|
||||
|
||||
The above program prints:
|
||||
|
||||
.. code-block::
|
||||
|
||||
Applying a perpendicular force of 500 N to a 20 cm long lever results in 100 N⋅m/rad of torque.
|
||||
|
||||
.. note::
|
||||
|
||||
`cotes_angle` is a constant which represents an angle with the value of exactly ``1 radian``.
|
||||
You can find more information about this constant in [Quincey]_.
|
||||
|
||||
|
||||
Radians and degrees support
|
||||
---------------------------
|
||||
|
||||
Thanks to :ref:`framework/magnitudes:Magnitudes` usage the library provides efficient strong types for all
|
||||
angular types. This means that with the built-in support for magnitudes of :math:`\pi` we can provide
|
||||
accurate conversions between radians and degrees. The library also provides common trigonometric functions
|
||||
for angular quantities::
|
||||
|
||||
using namespace units::aliases::isq::si;
|
||||
|
||||
auto velocity = km_per_h<>(110);
|
||||
auto rate_of_climb = m_per_s<>(-0.63657);
|
||||
auto glide_ratio = velocity / -rate_of_climb;
|
||||
auto glide_angle = asin(1 / glide_ratio);
|
||||
|
||||
std::cout << std::format("Glide ratio: {:%.1Q %q}\n", quantity_cast<units::one>(glide_ratio));
|
||||
std::cout << "Glide angle:\n";
|
||||
std::cout << std::format(" - {:%.4Q %q}\n", glide_angle);
|
||||
std::cout << std::format(" - {:%.2Q %q}\n", quantity_cast<units::degree>(glide_angle));
|
||||
std::cout << std::format(" - {:%.2Q %q}\n", quantity_cast<units::gradian>(glide_angle));
|
||||
|
||||
The above program prints:
|
||||
|
||||
.. code-block::
|
||||
|
||||
Glide ratio: 48.0
|
||||
Glide angle:
|
||||
- 0.0208 rad
|
||||
- 1.19 °
|
||||
- 1.33 ᵍ
|
||||
|
||||
.. note::
|
||||
|
||||
The above ``velocity`` and ``rate_of_climb`` in the production code should be modelled as
|
||||
:ref:`framework/quantity_kinds:Quantity Kinds`.
|
||||
A better but longer code can be found in the :ref:`examples/basics/glide_computer:glide_computer` example.
|
@ -1,48 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
International System of Quantities (ISQ)
|
||||
========================================
|
||||
|
||||
According to [ISO80000]_:
|
||||
|
||||
The system of quantities, including the relations among them the quantities used as the basis of the units of
|
||||
the SI, is named the **International System of Quantities**, denoted "ISQ", in all languages.
|
||||
|
||||
|
||||
Base dimensions and their symbols
|
||||
---------------------------------
|
||||
|
||||
According to the [SIBrochure]_:
|
||||
|
||||
Physical quantities can be organized in a system of dimensions, where the system used is
|
||||
decided by convention. Each of the seven base quantities used in the SI is regarded as
|
||||
having its own dimension. The symbols used for the base quantities and the symbols used
|
||||
to denote their dimension are shown in Table 3.
|
||||
|
||||
Following that the library provides the following definitions::
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<Unit U> struct dim_time : base_dimension<"T", U> {};
|
||||
template<Unit U> struct dim_length : base_dimension<"L", U> {};
|
||||
template<Unit U> struct dim_mass : base_dimension<"M", U> {};
|
||||
template<Unit U> struct dim_electric_current : base_dimension<"I", U> {};
|
||||
template<Unit U> struct dim_thermodynamic_temperature : base_dimension<"Θ", U> {};
|
||||
template<Unit U> struct dim_amount_of_substance : base_dimension<"N", U> {};
|
||||
template<Unit U> struct dim_luminous_intensity : base_dimension<"J", U> {};
|
||||
|
||||
}
|
||||
|
||||
Base dimension symbols provided above are consistently defined by both [SIBrochure]_ and [ISO80000]_.
|
||||
|
||||
|
||||
Derived dimensions
|
||||
------------------
|
||||
|
||||
[SIBrochure]_ states:
|
||||
|
||||
Since the number of quantities is without limit, it is not possible to
|
||||
provide a complete list of derived quantities and derived units.
|
||||
|
||||
The authors of this library decided to limit the set of defined quantities to all
|
||||
quantities defined in the [ISO80000]_ series of documents.
|
@ -1,231 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
The International System of Units (SI)
|
||||
======================================
|
||||
|
||||
The :term:`SI` system is defined in the [SIBrochure]_ and standardizes units for quantities provided in
|
||||
the :term:`ISQ` system:
|
||||
|
||||
The SI is a consistent system of units for use in all aspects of life, including international
|
||||
trade, manufacturing, security, health and safety, protection of the environment, and in the
|
||||
basic science that underpins all of these. The system of quantities underlying the SI and the
|
||||
equations relating them are based on the present description of nature and are familiar to all
|
||||
scientists, technologists and engineers.
|
||||
|
||||
As the :term:`SI` is defined on top of the :term:`ISQ` the C++ namespace for all of its definitions
|
||||
is ``units::isq::si``.
|
||||
|
||||
Base units
|
||||
----------
|
||||
|
||||
Even though from 2019 the :term:`SI` system is defined in terms of the `Defining constants`_,
|
||||
base units still are really important. As the [SIBrochure]_ states:
|
||||
|
||||
Prior to the definitions adopted in 2018, the SI was defined through seven base units from
|
||||
which the derived units were constructed as products of powers of the base units. Defining
|
||||
the SI by fixing the numerical values of seven defining constants has the effect that this
|
||||
distinction is, in principle, not needed, since all units, base as well as derived units, may be
|
||||
constructed directly from the defining constants. Nevertheless, the concept of base and
|
||||
derived units is maintained because it is useful and historically well established, noting
|
||||
also that the ISO/IEC 80000 series of Standards specify base and derived quantities which
|
||||
necessarily correspond to the SI base and derived units defined here.
|
||||
|
||||
The base units and quantities of the :term:`SI` system are defined as follows::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct second : named_unit<second, "s"> {};
|
||||
struct dim_time : isq::dim_time<second> {};
|
||||
template<UnitOf<dim_time> U, Representation Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
struct metre : named_unit<metre, "m"> {};
|
||||
struct dim_length : isq::dim_length<metre> {};
|
||||
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
struct gram : named_unit<gram, "g"> {};
|
||||
struct kilogram : prefixed_unit<kilogram, kilo, gram> {};
|
||||
struct dim_mass : isq::dim_mass<kilogram> {};
|
||||
template<UnitOf<dim_mass> U, Representation Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct ampere : named_unit<ampere, "A"> {};
|
||||
struct dim_electric_current : isq::dim_electric_current<ampere> {};
|
||||
template<UnitOf<dim_electric_current> U, Representation Rep = double>
|
||||
using electric_current = quantity<dim_electric_current, U, Rep>;
|
||||
|
||||
struct kelvin : named_unit<kelvin, "K"> {};
|
||||
struct dim_thermodynamic_temperature : isq::dim_thermodynamic_temperature<kelvin> {};
|
||||
template<UnitOf<dim_thermodynamic_temperature> U, Representation Rep = double>
|
||||
using thermodynamic_temperature = quantity<dim_thermodynamic_temperature, U, Rep>;
|
||||
|
||||
struct mole : named_unit<mole, "mol"> {};
|
||||
struct dim_amount_of_substance : isq::dim_amount_of_substance<mole> {};
|
||||
template<UnitOf<dim_amount_of_substance> U, Representation Rep = double>
|
||||
using amount_of_substance = quantity<dim_amount_of_substance, U, Rep>;
|
||||
|
||||
struct candela : named_unit<candela, "cd"> {};
|
||||
struct dim_luminous_intensity : isq::dim_luminous_intensity<candela> {};
|
||||
template<UnitOf<dim_luminous_intensity> U, Representation Rep = double>
|
||||
using luminous_intensity = quantity<dim_luminous_intensity, U, Rep>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Derived units
|
||||
-------------
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
Derived units are defined as products of powers of the base units. When the numerical
|
||||
factor of this product is one, the derived units are called coherent derived units. The base
|
||||
and coherent derived units of the SI form a coherent set, designated the set of coherent SI
|
||||
units. The word “coherent” here means that equations between the numerical values of
|
||||
quantities take exactly the same form as the equations between the quantities themselves.
|
||||
Some of the coherent derived units in the SI are given special names. ... Together with the
|
||||
seven base units they form the core of the set of SI units. All other SI units are combinations
|
||||
of some of these 29 units.
|
||||
|
||||
|
||||
Unit prefixes
|
||||
-------------
|
||||
|
||||
According to [SIBrochure]_:
|
||||
|
||||
Prefixes may be used with any of the 29 SI units with special names with
|
||||
the exception of the base unit kilogram.
|
||||
|
||||
Here is a complete list of all the :term:`SI` prefixes supported by the library::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct yocto : prefix<yocto, "y", mag_power<10, -24>()> {};
|
||||
struct zepto : prefix<zepto, "z", mag_power<10, -21>()> {};
|
||||
struct atto : prefix<atto, "a", mag_power<10, -18>()> {};
|
||||
struct femto : prefix<femto, "f", mag_power<10, -15>()> {};
|
||||
struct pico : prefix<pico, "p", mag_power<10, -12>()> {};
|
||||
struct nano : prefix<nano, "n", mag_power<10, -9>()> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
||||
mag_power<10, -6>()> {};
|
||||
struct milli : prefix<milli, "m", mag_power<10, -3>()> {};
|
||||
struct centi : prefix<centi, "c", mag_power<10, -2>()> {};
|
||||
struct deci : prefix<deci, "d", mag_power<10, -1>()> {};
|
||||
struct deca : prefix<deca, "da", mag_power<10, 1>()> {};
|
||||
struct hecto : prefix<hecto, "h", mag_power<10, 2>()> {};
|
||||
struct kilo : prefix<kilo, "k", mag_power<10, 3>()> {};
|
||||
struct mega : prefix<mega, "M", mag_power<10, 6>()> {};
|
||||
struct giga : prefix<giga, "G", mag_power<10, 9>()> {};
|
||||
struct tera : prefix<tera, "T", mag_power<10, 12>()> {};
|
||||
struct peta : prefix<peta, "P", mag_power<10, 15>()> {};
|
||||
struct exa : prefix<exa, "E", mag_power<10, 18>()> {};
|
||||
struct zetta : prefix<zetta, "Z", mag_power<10, 21>()> {};
|
||||
struct yotta : prefix<yotta, "Y", mag_power<10, 24>()> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Other definitions for names units
|
||||
---------------------------------
|
||||
|
||||
For all of the above units the library also provides:
|
||||
|
||||
- prefixed versions using SI prefixes::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct millisecond : prefixed_unit<millisecond, milli, second> {};
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:Quantity References (Experimental)`::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
namespace time_references {
|
||||
|
||||
inline constexpr auto s = reference<dim_time, second>{};
|
||||
|
||||
}
|
||||
|
||||
namespace references {
|
||||
|
||||
using namespace time_references;
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:Unit-Specific Aliases (Experimental)`::
|
||||
|
||||
namespace units::aliases::isq::si::inline time {
|
||||
|
||||
template<Representation Rep = double>
|
||||
using s = units::isq::si::time<units::isq::si::second, Rep>;
|
||||
|
||||
}
|
||||
|
||||
- :ref:`framework/quantities:User Defined Literals (Experimental)`::
|
||||
|
||||
namespace units::isq::si::inline literals {
|
||||
|
||||
constexpr auto operator"" _q_s(unsigned long long l)
|
||||
{
|
||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
|
||||
return time<second, std::int64_t>(static_cast<std::int64_t>(l));
|
||||
}
|
||||
constexpr auto operator"" _q_s(long double l) { return time<second, long double>(l); }
|
||||
|
||||
}
|
||||
|
||||
For some of the units, when accepted by the :term:`SI`, other non-standard scaled versions are also provided::
|
||||
|
||||
namespace units::isq::si {
|
||||
|
||||
struct minute : named_scaled_unit<minute, "min", mag<60>(), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", mag<60>(), minute> {};
|
||||
struct day : named_scaled_unit<day, "d", mag<24>(), hour> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Defining constants
|
||||
------------------
|
||||
|
||||
[SIBrochure]_ states that:
|
||||
|
||||
The definition of the SI units is established in terms of a set of seven defining constants.
|
||||
The complete system of units can be derived from the fixed values of these defining
|
||||
constants, expressed in the units of the SI.
|
||||
|
||||
Those constants are provided in the *units/isq/si/constants.h* header file as::
|
||||
|
||||
namespace units::isq::si::si2019 {
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto hyperfine_structure_transition_frequency = frequency<hertz, Rep>(Rep{9'192'631'770});
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<metre_per_second, Rep>(299'792'458);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto planck_constant = energy<joule, Rep>(6.62607015e-34) * time<second, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto elementary_charge = electric_charge<coulomb, Rep>(1.602176634e-19);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto boltzmann_constant = energy<joule, Rep>(1.380649e-23) / thermodynamic_temperature<kelvin, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto avogadro_constant = Rep(6.02214076e23) / amount_of_substance<mole, Rep>(1);
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto luminous_efficacy = luminous_flux<lumen, Rep>(683) / power<watt, Rep>(1);
|
||||
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
Please note the nested `si2019` namespace. It is introduced in case those constants were changed/updated
|
||||
by the :term:`SI` in the future.
|
@ -1,17 +0,0 @@
|
||||
Design Deep Dive
|
||||
================
|
||||
|
||||
.. note::
|
||||
|
||||
For brevity all the code examples in this chapter assume::
|
||||
|
||||
using namespace units;
|
||||
using namespace units::isq;
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
design/directories
|
||||
design/quantity
|
||||
design/quantity_kind
|
||||
design/downcasting
|
@ -1,64 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Library Directories Structure
|
||||
=============================
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
units
|
||||
├── bits
|
||||
│ └── external
|
||||
├── generic
|
||||
└── isq
|
||||
├── dimensions
|
||||
├── iec80000
|
||||
├── natural
|
||||
└── si
|
||||
├── cgs
|
||||
├── fps
|
||||
├── iau
|
||||
├── imperial
|
||||
├── international
|
||||
├── typographic
|
||||
└── us
|
||||
|
||||
- *./units*
|
||||
|
||||
- The main directory of the library.
|
||||
- Contains headers files that define a public interface of the library framework.
|
||||
|
||||
- *./units/bits*
|
||||
|
||||
- Contains header files with implementation details for the library. Interface of
|
||||
the tools provided here should not be standardized.
|
||||
|
||||
- *./units/bits/external*
|
||||
|
||||
- Contains header files of general purpose utilities that are not necessary
|
||||
**mp-units** library specific. They are either implementation details of the
|
||||
library or should be (or already are) the subject of separate standardization
|
||||
proposals not related to a Physical Units library proposal.
|
||||
|
||||
- *./units/generic*
|
||||
|
||||
- Provides quantity types not related to any :term:`system of quantities`
|
||||
(e.g. `dimensionless`, `angle`).
|
||||
|
||||
- *./units/isq*
|
||||
|
||||
- Contains the definition of quantity dimensions of International System of Quantities
|
||||
(:term:`ISQ`).
|
||||
- Its subfolders provide the definitions of various
|
||||
:term:`systems of units <system of units>` with International System of Units (:term:`SI`)
|
||||
being the most popular one.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information on provided :term:`systems of units <system of units>` can be
|
||||
found in :ref:`reference/systems:Systems` chapter.
|
||||
|
||||
.. important::
|
||||
|
||||
While working with predefined systems please always include a header file with all
|
||||
the definitions for the current system to limit the possibility of an ODR violation
|
||||
(e.g. *units/isq/si/si.h*).
|
@ -1,161 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
The Downcasting Facility
|
||||
========================
|
||||
|
||||
Problem statement
|
||||
-----------------
|
||||
|
||||
Most of the C++ libraries in the world use template aliases to provide a friendly name for a
|
||||
developer. Unfortunately, such aliases are quickly lost in a compilation process and as a
|
||||
result the potential error log contains a huge source type rather than a short alias for it.
|
||||
The same can be observed during debugging of a source code that use template aliases.
|
||||
|
||||
Let's assume that we want to provide a user friendly name for a derived dimension of capacitance
|
||||
quantity. Other libraries will do it in the following way::
|
||||
|
||||
using dim_capacitance = detail::derived_dimension_base<exponent<si::dim_electric_current, 2>,
|
||||
exponent<si::dim_length, -2>,
|
||||
exponent<si::dim_mass, -1>,
|
||||
exponent<si::dim_time, 4>>;
|
||||
|
||||
The above solution does provide a good developer's experience but a really poor one for the end
|
||||
user. If we will get a compilation error message containing ``dim_capacitance`` in most cases
|
||||
the compiler will print the following type instead of the alias::
|
||||
|
||||
units::detail::derived_dimension_base<units::exponent<units::isq::si::dim_electric_current, 2, 1>,
|
||||
units::exponent<units::isq::si::dim_length, -2, 1>, units::exponent<units::isq::si::dim_mass,
|
||||
-1, 1>, units::exponent<units::isq::si::dim_time, 4, 1> >
|
||||
|
||||
You can notice that in case of **mp-units** even this long syntax was carefully selected to
|
||||
provide quite good user experience (some other units libraries produce a type that cannot easily
|
||||
fit on one slide) but it is not questionable less readable than just ``dim_capacitance``.
|
||||
|
||||
.. note::
|
||||
|
||||
To better understand how the framework works and not clutter the text and graphs with
|
||||
long types in the following examples we will switch from ``dim_capacitance`` to ``dim_area``.
|
||||
The latter one has much shorter definition but the end result for both will be exactly the same -
|
||||
user-friendly, short name printed by the compiler and the debugger.
|
||||
|
||||
|
||||
As we lack opaque/strong typedefs in the C++ language the only way to improve our case is
|
||||
to use inheritance:
|
||||
|
||||
.. image:: /_static/img/downcast_1.png
|
||||
:align: center
|
||||
|
||||
..
|
||||
http://www.nomnoml.com
|
||||
|
||||
[derived_dimension_base<exponent<si::dim_length, 2>>]<:-[dim_area]
|
||||
|
||||
This gives us a nice looking strong type when directly used by the user. However, we just got
|
||||
ourselves into problems. The library's framework does not know how to switch from a long
|
||||
instantiation of a ``derived_dimension_base`` class template that was generated as a result
|
||||
of dimensional calculation to a nicely named child class assigned by the user for this
|
||||
instantiation.
|
||||
|
||||
|
||||
How it works?
|
||||
-------------
|
||||
|
||||
To support this **mp-units** library introduces a new downcasting facility implemented fully
|
||||
as a library feature. It creates 1-to-1 link between a long class template instantiation and a
|
||||
strong type provided by the user. This provides automatic type substitution mechanism in the
|
||||
framework.
|
||||
|
||||
.. important::
|
||||
|
||||
The above 1-1 correspondence means that only one child class can be provided for a specific
|
||||
base class template instantiation. If a user will try to assign another child class to
|
||||
already used base class template instantiation the program will not compile.
|
||||
|
||||
The downcasting facility is provided by injecting two classes into our hierarchy:
|
||||
|
||||
.. image:: /_static/img/downcast_2.png
|
||||
:align: center
|
||||
|
||||
..
|
||||
http://www.nomnoml.com
|
||||
|
||||
[downcast_base<detail::derived_dimension_base<exponent<si::dim_length, 2>>>]<:-[detail::derived_dimension_base<exponent<si::dim_length, 2>>]
|
||||
[detail::derived_dimension_base<exponent<si::dim_length, 2>>]<:-[downcast_child<dim_area, detail::derived_dimension_base<exponent<si::dim_length, 2>>>]
|
||||
[downcast_child<dim_area, detail::derived_dimension_base<exponent<si::dim_length, 2>>>]<:-[dim_area]
|
||||
|
||||
In the above example:
|
||||
|
||||
- ``dim_area`` is a downcasting target (child class)
|
||||
|
||||
- ``detail::derived_dimension_base`` class template instantiation is a downcasting source (base class)
|
||||
|
||||
- `downcast_base` is a class that implements :abbr:`CRTP (Curiously Recurring Template Pattern)`
|
||||
idiom, stores the base of a downcasting operation in a ``downcast_base_type`` member type,
|
||||
and provides only a Hidden Friend non-member function declaration of ``downcast_guide`` which is an
|
||||
:abbr:`ADL (Argument Dependent Lookup)` entry point for the downcasting operation::
|
||||
|
||||
template<typename BaseType>
|
||||
struct downcast_base {
|
||||
using downcast_base_type = BaseType;
|
||||
friend auto downcast_guide(downcast_base); // declaration only (no implementation)
|
||||
};
|
||||
|
||||
.. important::
|
||||
|
||||
An important design point here is that this friend function does not return any specific type
|
||||
in its declaration and no definition is provided at this point.
|
||||
|
||||
- `downcast_child` is another :abbr:`CRTP (Curiously Recurring Template Pattern)` class template
|
||||
that defines the implementation of a non-member friend function of the `downcast_base` class
|
||||
template::
|
||||
|
||||
template<typename Target, Downcastable T>
|
||||
struct downcast_child : T {
|
||||
friend auto downcast_guide(typename T::downcast_base) { return Target(); }
|
||||
};
|
||||
|
||||
This is the place where the actual return type of the ``downcast_guide`` function is provided
|
||||
which serves as a target type of the downcasting operation.
|
||||
|
||||
In the above class template definition `Downcastable` is a concepts that verifies if a type
|
||||
implements and can be used in a downcasting facility::
|
||||
|
||||
template<typename T>
|
||||
concept Downcastable =
|
||||
requires {
|
||||
typename T::downcast_base_type;
|
||||
} &&
|
||||
std::derived_from<T, downcast_base<typename T::downcast_base_type>>;
|
||||
|
||||
|
||||
With such :abbr:`CRTP (Curiously Recurring Template Pattern)` types the only thing the user
|
||||
has to do in order to register a new type in the downcasting facility is to publicly derive
|
||||
from `downcast_child` and pass this type as the first template argument of the `downcast_child`
|
||||
class template.
|
||||
|
||||
Until now we scoped on how we define the base and target of a downcasting operation. To
|
||||
perform the actual downcasting operation a dedicated alias template is provided::
|
||||
|
||||
template<Downcastable T>
|
||||
using downcast = decltype(detail::downcast_impl<T>());
|
||||
|
||||
`downcast` is used to obtain the target type of the downcasting operation registered for a
|
||||
given instantiation in a base type. ``detail::downcast_impl`` checks if a downcasting
|
||||
target is registered for the specific base class. If yes, it returns the registered type,
|
||||
otherwise it works like a regular identity type trait returning a provided base class::
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
concept has_downcast_guide = requires(T t) { downcast_guide(t); };
|
||||
|
||||
template<typename T>
|
||||
constexpr auto downcast_impl()
|
||||
{
|
||||
if constexpr(has_downcast_guide<T>)
|
||||
return decltype(downcast_guide(std::declval<downcast_base<T>>()))();
|
||||
else
|
||||
return T();
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
quantity
|
||||
========
|
||||
|
||||
Interface
|
||||
---------
|
||||
|
||||
The value of a quantity is generally expressed as the product of a number and a unit. The
|
||||
unit is simply a particular example of the quantity concerned which is used as a reference,
|
||||
and the number is the ratio of the value of the quantity to the unit.
|
||||
|
||||
|
||||
`quantity` class template provides a similar interface to
|
||||
`std::chrono::duration <https://en.cppreference.com/w/cpp/chrono/duration>`_.
|
||||
The difference is that it uses ``double`` as a default representation and has
|
||||
a few additional member types and functions::
|
||||
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep = double>
|
||||
class quantity {
|
||||
public:
|
||||
using dimension = D;
|
||||
using unit = U;
|
||||
using rep = Rep;
|
||||
|
||||
[[nodiscard]] static constexpr quantity one() noexcept;
|
||||
// ...
|
||||
};
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent<D1, dim_invert<D2>>)
|
||||
[[nodiscard]] constexpr Quantity auto operator*(const quantity<D1, U1, Rep1>& lhs,
|
||||
const quantity<D2, U2, Rep2>& rhs);
|
||||
|
||||
template<Representation Value, typename D, typename U, typename Rep>
|
||||
requires std::magma<std::ranges::divided_by, Value, Rep>
|
||||
[[nodiscard]] constexpr Quantity auto operator/(const Value& v,
|
||||
const quantity<D, U, Rep>& q);
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent<D1, D2>)
|
||||
[[nodiscard]] constexpr Quantity auto operator/(const quantity<D1, U1, Rep1>& lhs,
|
||||
const quantity<D2, U2, Rep2>& rhs);
|
||||
|
||||
Additional functions provide the support for operations that result in a
|
||||
different dimension type than those of their arguments. ``equivalent``
|
||||
constraint requires two dimensions to be either the same or have convertible
|
||||
units of base dimension (with the same reference unit).
|
||||
|
||||
Beside adding new elements a few other changes where applied compared to the
|
||||
`std::chrono::duration <https://en.cppreference.com/w/cpp/chrono/duration>`_
|
||||
class template:
|
||||
|
||||
1. The ``std::chrono::duration`` is using ``std::common_type_t<Rep1, Rep2>`` to find a common
|
||||
representation for a calculation result. Such a design was reported as problematic
|
||||
by SG6 (numerics study group) members as sometimes we want to provide a different
|
||||
type in case of multiplication and different in case of division. ``std::common_type``
|
||||
lacks that additional information. That is why `quantity` uses the resulting
|
||||
type of a concrete operator operation.
|
||||
2. ``quantity::operator%()`` is constrained with `treat_as_floating_point` type trait to limit the
|
||||
types to integral representations only. Also ``quantity::operator%(Rep)`` takes ``Rep`` as a
|
||||
template argument to limit implicit conversions.
|
@ -1,52 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
quantity_kind
|
||||
=============
|
||||
|
||||
The ``quantity_kind`` class template provides a similar interface to ``quantity``.
|
||||
|
||||
Kinds
|
||||
-----
|
||||
|
||||
The first template parameter of ``quantity_kind`` is a ``Kind``.
|
||||
|
||||
``Kind`` s, by themselves:
|
||||
|
||||
* Wrap a ``Dimension``, and
|
||||
* opt into the downcasting facility.
|
||||
|
||||
If a dimensional analysis operator on a quantity of kind *A*
|
||||
can result on a quantity of kind *B*,
|
||||
*A* and *B* are *related*.
|
||||
|
||||
The library provides two ``Kind`` bases, ``kind`` and ``derived_kind``.
|
||||
|
||||
``kind`` is an entry point, and there's only one per set of related kinds.
|
||||
|
||||
``derived_kind`` is used to explicitly name other related kinds.
|
||||
Unnamed, they look like ``detail::_kind_base<the-entry-kind, some_dimension>``.
|
||||
|
||||
Unnamed kinds, like unnamed units and dimensions,
|
||||
allows (intermediate) results in formulas without having to name them.
|
||||
|
||||
Quantity kinds
|
||||
--------------
|
||||
|
||||
``quantity_kind`` wraps a ``quantity`` and layers over its dimensional analysis.
|
||||
While all properties of the ``quantity`` apply transparently,
|
||||
results are always ``quantity_kind`` s related to the kind(s) of the argument(s).
|
||||
|
||||
One of the arguments to the dimensional analysis operators can also be ``Quantity``.
|
||||
|
||||
The way back to ``quantity`` is through the ``.common()`` observer.
|
||||
|
||||
Intra-kind operations
|
||||
---------------------
|
||||
|
||||
``quantity_kind`` takes care of operators between related quantity kinds.
|
||||
Intra-kind operations can be opted into as follows::
|
||||
|
||||
struct width : kind<width, dim_length> {};
|
||||
struct height : kind<height, dim_length> {};
|
||||
|
||||
size2d operator+(QuantityKindOf<width> auto, QuantityKindOf<height> auto);
|
@ -1,11 +0,0 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
examples/basics
|
||||
examples/kalman_filter
|
||||
examples/custom_representation
|
||||
examples/custom_systems
|
||||
examples/custom_utilities
|
@ -1,18 +0,0 @@
|
||||
Basics
|
||||
======
|
||||
|
||||
The following examples highlight the basics of the library design.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
basics/hello_units
|
||||
basics/clcpp_response
|
||||
basics/avg_speed
|
||||
basics/box_example
|
||||
basics/capacitor_time_curve
|
||||
basics/unknown_dimension
|
||||
basics/foot_pound_second
|
||||
basics/experimental_angle
|
||||
basics/total_energy
|
||||
basics/glide_computer
|
@ -1,7 +0,0 @@
|
||||
avg_speed
|
||||
=========
|
||||
|
||||
.. literalinclude:: ../../../example/references/avg_speed.cpp
|
||||
:caption: avg_speed.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
box_example
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../../example/references/box_example.cpp
|
||||
:caption: box_example.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
capacitor_time_curve
|
||||
====================
|
||||
|
||||
.. literalinclude:: ../../../example/references/capacitor_time_curve.cpp
|
||||
:caption: capacitor_time_curve.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
clcpp_response
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../../example/references/clcpp_response.cpp
|
||||
:caption: clcpp_response.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
experimental_angle
|
||||
==================
|
||||
|
||||
.. literalinclude:: ../../../example/references/experimental_angle.cpp
|
||||
:caption: experimental_angle.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
foot_pound_second
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../../example/references/foot_pound_second.cpp
|
||||
:caption: foot_pound_second.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,81 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
glide_computer
|
||||
==============
|
||||
|
||||
This example presents the usage of:
|
||||
|
||||
- `quantity_point` to mark "absolute" quantities like ``timestamp``
|
||||
- `quantity_point_kind` to mark "absolute" kinds of quantities like ``altitude`` (as opposed to ``height``),
|
||||
- different kinds for length, time, and speed,
|
||||
- the use of quantity kinds to show how to handle 3D space for aviation needs,
|
||||
- unit constants to initialize the database
|
||||
- quantities text output formatting,
|
||||
- cooperation with `std::chrono`.
|
||||
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-at: #include
|
||||
:end-at: // - flight path exactly on a shortest possible line to destination
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
The use of `quantity_kind` and `quantity_point_kind` provides strong typing
|
||||
that divide quantities and quantity points to the ones on a horizontal (X, Y) plane and vertical (Z) axis.
|
||||
Their purpose is to make different kinds of quantity
|
||||
(i.e. length) separate strong types (i.e. distance, height).
|
||||
Additionally, separating a quantity from its quantity point
|
||||
means that we can define a ``height`` and ``altitude`` as different strong types.
|
||||
A quantity point provides a more restricted interface meant for absolute calculations.
|
||||
|
||||
The glide calculator engine also take benefits from different :term:`kinds of quantities <kind>`.
|
||||
For example we have 3 for a quantity of length:
|
||||
|
||||
- ``distance`` - a relative horizontal distance between 2 points on Earth
|
||||
- ``height`` - a relative altitude difference between 2 points in the air
|
||||
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
|
||||
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-after: // - flight path exactly on a shortest possible line to destination
|
||||
:end-before: // text output
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
Next a custom text output is provided both for C++ output streams and the text formatting facility.
|
||||
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-at: // text output
|
||||
:end-before: // definition of glide computer databases and utilities
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
The engine of this simple glide computer works on quantities of the SI units with a floating-point
|
||||
representation. The user can pass any unit valid for a given quantity and the library will automatically
|
||||
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,
|
||||
safety constraints, and a towing height.
|
||||
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-at: // definition of glide computer databases and utilities
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
.. literalinclude:: ../../../example/references/glide_computer_example.cpp
|
||||
:caption: glide_computer_example.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
Having all of that it estimates the number of flight phases (towing, circling, gliding, final glide)
|
||||
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.
|
||||
|
||||
.. literalinclude:: ../../../example/glide_computer/glide_computer.cpp
|
||||
:caption: glide_computer.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
:lineno-match:
|
@ -1,7 +0,0 @@
|
||||
hello_units
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../../example/hello_units.cpp
|
||||
:caption: hello_units.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
total_energy
|
||||
============
|
||||
|
||||
.. literalinclude:: ../../../example/references/total_energy.cpp
|
||||
:caption: total_energy.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
unknown_dimension
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../../example/references/unknown_dimension.cpp
|
||||
:caption: unknown_dimension.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,10 +0,0 @@
|
||||
Custom Representation Types
|
||||
===========================
|
||||
|
||||
The following examples show how to work with custom represenation types.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
custom_representation/measurement
|
||||
custom_representation/linear_algebra
|
@ -1,7 +0,0 @@
|
||||
linear_algebra
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../../example/references/linear_algebra.cpp
|
||||
:caption: linear_algebra.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
measurement
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../../example/measurement.cpp
|
||||
:caption: measurement.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Custom Systems
|
||||
==============
|
||||
|
||||
The following examples show how to define custom systems of units and quantities.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
custom_systems/custom_systems
|
@ -1,7 +0,0 @@
|
||||
custom_systems
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../../example/custom_systems.cpp
|
||||
:caption: custom_systems.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Custom Utilites
|
||||
===============
|
||||
|
||||
The following examples present how to reuse library facilities to create custom utilities.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
custom_utilities/conversion_factor
|
@ -1,7 +0,0 @@
|
||||
conversion_factor
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../../example/conversion_factor.cpp
|
||||
:caption: conversion_factor.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,17 +0,0 @@
|
||||
Kalman Filter Tutorial
|
||||
======================
|
||||
|
||||
The following examples are based on the `Kalman Filter <https://www.kalmanfilter.net>`_ tutorial.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
kalman_filter/kalman
|
||||
kalman_filter/example_1
|
||||
kalman_filter/example_2
|
||||
kalman_filter/example_3
|
||||
kalman_filter/example_4
|
||||
kalman_filter/example_5
|
||||
kalman_filter/example_6
|
||||
kalman_filter/example_7
|
||||
kalman_filter/example_8
|
@ -1,9 +0,0 @@
|
||||
Example 1 - Weighting the gold
|
||||
==============================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/alphabeta.html#ex1
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_1.cpp
|
||||
:caption: kalman_filter-example_1.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 2 - Tracking the constant velocity aircraft in one dimension
|
||||
====================================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/alphabeta.html#ex2
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_2.cpp
|
||||
:caption: kalman_filter-example_2.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 3 - Tracking accelerating aircraft in one dimension
|
||||
===========================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/alphabeta.html#ex3
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_3.cpp
|
||||
:caption: kalman_filter-example_3.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 4 - Tracking accelerating aircraft with the α−β−γ filter
|
||||
================================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/alphabeta.html#ex4
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_4.cpp
|
||||
:caption: kalman_filter-example_4.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 5 - Estimating the building height
|
||||
==========================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/kalman1d.html#ex5
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_5.cpp
|
||||
:caption: kalman_filter-example_5.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 6 - Estimating the temperature of the liquid in a tank
|
||||
==============================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/kalman1d.html#ex6
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_6.cpp
|
||||
:caption: kalman_filter-example_6.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 7 - Estimating the temperature of the heating liquid I
|
||||
==============================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/kalman1d.html#ex7
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_7.cpp
|
||||
:caption: kalman_filter-example_7.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,9 +0,0 @@
|
||||
Example 8 - Estimating the temperature of the heating liquid II
|
||||
===============================================================
|
||||
|
||||
Implementation of: https://www.kalmanfilter.net/kalman1d.html#ex8
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman_filter-example_8.cpp
|
||||
:caption: kalman_filter-example_8.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
@ -1,7 +0,0 @@
|
||||
Common utility header file (``kalman.h``)
|
||||
=========================================
|
||||
|
||||
.. literalinclude:: ../../../example/kalman_filter/kalman.h
|
||||
:caption: kalman.h
|
||||
:start-at: #include
|
||||
:linenos:
|
131
docs/faq.rst
131
docs/faq.rst
@ -1,131 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
.. contents:: Questions:
|
||||
:local:
|
||||
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
Why dimensions depend on units and not vice versa?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Most of the libraries define units in terms of dimensions and this was also an
|
||||
initial approach for this library. However, it turns out that for such a design
|
||||
it is hard to provide support for all the required scenarios.
|
||||
|
||||
The first of them is to support multiple unit systems (like SI, CGS, ...) where
|
||||
each of can have a different base unit for the same dimension. Base quantity of
|
||||
dimension length in SI should use ``m`` to print the unit symbol to the text
|
||||
output, while the same dimension for CGS should use ``cm``. Also, it helps in
|
||||
conversions among those systems.
|
||||
|
||||
The second one is to support natural units where more than one dimension can be
|
||||
measured with the same unit (i.e. ``GeV``). Also if someone will decide to
|
||||
implement a systems where SI quantities of the same kind are expressed as
|
||||
different dimensions (i.e. height, width, and depth) all of them will just be
|
||||
measured in meters.
|
||||
|
||||
|
||||
Why other systems are defined in the `isq::si` namespace?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All systems defined in the `isq::si` namespace are defined in terms of
|
||||
base units that are convertible to the :term:`SI` units. This enables conversions
|
||||
of units of the same physical dimension between different systems.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More details on this subject can be found in the
|
||||
:ref:`use_cases/extensions:Custom Systems` chapter.
|
||||
|
||||
|
||||
Why a dimensionless quantity is not just an fundamental arithmetic type?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the initial design of this library the resulting type of the division of
|
||||
two quantities was their common representation type::
|
||||
|
||||
static_assert(std::is_same_v<decltype(10 * km / (5 * km)), std::int64_t>);
|
||||
|
||||
The reasoning behind it was to not provide a false impression of a strong `quantity` type
|
||||
for something that looks and feels like a regular number. Also all of the mathematic
|
||||
and trigonometric functions were working fine out of the box with such representation
|
||||
types, so we did not have to rewrite ``sin()``, ``cos()``, ``exp()``, and others.
|
||||
|
||||
However, the feedback we got from the production usage was that such an approach
|
||||
is really bad for generic programming. It is really hard to handle the result of
|
||||
division (or multiplication) of two quantities as it might be either a `quantity`
|
||||
or a fundamental type. If we want to raise such a result to some power we have to
|
||||
either use ``units::pow`` or ``std::pow`` depending on the resulting type. Those
|
||||
are only a few from many similar issues related to such an approach.
|
||||
|
||||
This is why it was decided to go with the current approach.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information on the current design can be found in
|
||||
the :ref:`framework/quantities:Dimensionless Quantities` chapter.
|
||||
|
||||
|
||||
Why do we spell ``metre`` instead of ``meter``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Well, this is how [ISO80000]_ defines it (British English spelling by default).
|
||||
|
||||
|
||||
User Defined Literals (UDLs)
|
||||
----------------------------
|
||||
|
||||
Why all UDLs are prefixed with ``_q_`` instead of just using unit symbol?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Every ``_q_*`` UDL will be replaced by the ``q_*`` literal when/if **mp-units**
|
||||
will become a part of the C++ Standard Library.
|
||||
|
||||
Usage of only unit symbols in UDLs would be a preferred approach (less to type,
|
||||
easier to understand and maintain). However, while increasing the coverage for
|
||||
the library we learned that there are a lot unit symbols that conflict with
|
||||
built-in types or numeric extensions. A few of those are: ``F`` (farad),
|
||||
``J`` (joule), ``W`` (watt), ``K`` (kelvin), ``d`` (day),
|
||||
``l`` or ``L`` (litre), ``erg``, ``ergps``. For a while for those we used ``_``
|
||||
prefix to make the library work at all, but at some point we had to unify the
|
||||
naming and we came up with ``_q_`` prefix which results in a creation of
|
||||
quantity of a provided unit.
|
||||
|
||||
|
||||
Text formatting
|
||||
---------------
|
||||
|
||||
Why Unicode quantity symbols are used by default instead of ASCII-only characters?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Both C++ and :term:`SI` ([ISO80000]_) are standardized by the
|
||||
:abbr:`ISO (International Organization for Standardization)`. :term:`SI` standard
|
||||
specifies Unicode symbols as the official unit names for some quantities (i.e. ``Ω``
|
||||
symbol for the resistance quantity). As **mp-units** library
|
||||
is being proposed for standardization as a part of the C++ Standard Library we have
|
||||
to obey the rules and be consistent with ISO specifications.
|
||||
|
||||
.. seealso::
|
||||
|
||||
We do understand engineering reality and constraints and that is why the library
|
||||
has the option of :ref:`framework/text_output:ASCII-only quantity symbols`.
|
||||
|
||||
|
||||
Compilation Errors
|
||||
------------------
|
||||
|
||||
error: reference to ‘time’ is ambiguous
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Unfortunately, if `using-directives <https://en.cppreference.com/w/cpp/language/namespace#Using-directives>`_
|
||||
(i.e. ``using namespace units::isq::si``) are being used, `units::isq::si::time`
|
||||
will collide with C `time <https://en.cppreference.com/w/c/chrono/time>`_ function. In
|
||||
such a case the library's ``time`` function needs to be prefixed with at least one (or all)
|
||||
namespace names.
|
@ -1,25 +0,0 @@
|
||||
Framework Basics
|
||||
================
|
||||
|
||||
.. note::
|
||||
|
||||
For brevity all the code examples in this chapter assume::
|
||||
|
||||
using namespace units;
|
||||
using namespace units::isq;
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
framework/basic_concepts
|
||||
framework/quantity_like
|
||||
framework/quantities
|
||||
framework/quantity_points
|
||||
framework/quantity_kinds
|
||||
framework/dimensions
|
||||
framework/magnitudes
|
||||
framework/units
|
||||
framework/arithmetics
|
||||
framework/constants
|
||||
framework/conversions_and_casting
|
||||
framework/text_output
|
@ -1,148 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Arithmetics
|
||||
===========
|
||||
|
||||
Quantities
|
||||
----------
|
||||
|
||||
Quantities of the same dimension can be easily added or subtracted with
|
||||
each other and the result will always be a quantity of the same dimension:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3-4
|
||||
|
||||
Length auto dist1 = 2 * m;
|
||||
Length auto dist2 = 1 * m;
|
||||
Length auto res1 = dist1 + dist2;
|
||||
Length auto res2 = dist1 - dist2;
|
||||
|
||||
Additionally, we can always multiply or divide a quantity by a
|
||||
:term:`scalable number` and in such a case the quantity's dimension will also
|
||||
not change:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 2-4
|
||||
|
||||
Length auto dist = 2 * m;
|
||||
Length auto res1 = dist * 2; // 4 m
|
||||
Length auto res2 = 3 * res1; // 12 m
|
||||
Length auto res3 = res2 / 2; // 6 m
|
||||
|
||||
However, if we try to multiply or divide quantities of the same or
|
||||
different dimensions, or we will divide a scalable number by a quantity, we most
|
||||
probably will always end up in a quantity of a yet another dimension:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 4-6
|
||||
|
||||
Length auto dist1 = 2 * m;
|
||||
Length auto dist2 = 3 * m;
|
||||
Time auto dur1 = 2 * s;
|
||||
Area auto res1 = dist1 * dist2; // 6 m²
|
||||
Speed auto res2 = dist1 / dur1; // 1 m/s
|
||||
Frequency auto res3 = 10 / dur1; // 5 Hz
|
||||
|
||||
However, please note that there is an exception from the above rule.
|
||||
In case we divide the same dimensions, or multiply by the inverted
|
||||
dimension, than we will end up with just a dimensionless quantity:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 4-5
|
||||
|
||||
Time auto dur1 = 10 * s;
|
||||
Time auto dur2 = 2 * s;
|
||||
Frequency auto fr1 = 5 * Hz;
|
||||
Dimensionless auto v1 = dur1 / dur2; // quantity(5)
|
||||
Dimensionless auto v2 = dur1 * fr1; // quantity(50)
|
||||
|
||||
Quantity Kinds
|
||||
--------------
|
||||
|
||||
Quantity kinds behave the same as quantities for all operations,
|
||||
except that the quantity types in the operators' declarations
|
||||
are quantity kind types instead.
|
||||
Additionally, for the dimensional analysis operators,
|
||||
you can use a quantity argument instead of a quantity kind.
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 8-9
|
||||
|
||||
struct height_kind : kind<height_kind, dim_length> {};
|
||||
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, dim_speed, height_kind> {};
|
||||
|
||||
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||
|
||||
height h{100 * m};
|
||||
rate_of_climb rate = h / (25 * s);
|
||||
// quantity_kind<rate_of_climb_kind, si::metre_per_second, int>(4 * m / s)
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 8-12
|
||||
|
||||
struct width_kind : kind<width_kind, dim_length> {};
|
||||
struct horizontal_area_kind : derived_kind<horizontal_area_kind, dim_area, width_kind> {};
|
||||
|
||||
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
||||
template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
||||
|
||||
width w{5 * m};
|
||||
horizontal_area area1 = w * w;
|
||||
// quantity_kind<horizontal_area_kind, si::metre_per_second, int>(25 * m * m)
|
||||
width w2 = area1 / w; // quantity_kind<width_kind, si::metre, int>(5 * m)
|
||||
auto q1 = w / w; // Dimensionless quantity kinds related to width
|
||||
auto q2 = w / (5 * m); // with .common() equal to quantity{1}
|
||||
|
||||
Quantity Points
|
||||
---------------
|
||||
|
||||
Quantity points have a more restricted set of operations.
|
||||
Quantity can be added to or subtracted
|
||||
from a quantity point of the same origin.
|
||||
The result will always be a quantity point of the same origin:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3-5
|
||||
|
||||
Length auto dist1 = 2 * m;
|
||||
Length auto dist2 = 1 * m;
|
||||
QuantityPoint auto res1 = quantity_point{dist1} + dist2;
|
||||
QuantityPoint auto res2 = dist1 + quantity_point{dist2};
|
||||
QuantityPoint auto res3 = quantity_point{dist1} - dist2;
|
||||
|
||||
We can also subtract two quantity points.
|
||||
The result is a relative quantity of the same dimension:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3
|
||||
|
||||
Length auto dist1 = 2 * m;
|
||||
Length auto dist2 = 1 * m;
|
||||
Length auto res1 = quantity_point{dist1} - quantity_point{dist2};
|
||||
|
||||
.. note::
|
||||
|
||||
It is not allowed to:
|
||||
|
||||
- add quantity points,
|
||||
- subtract a quantity point from a quantity,
|
||||
- multiply nor divide quantity points with anything else, and
|
||||
- mix quantity points with different origins:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3-5
|
||||
|
||||
Length auto dist1 = 2 * m;
|
||||
Length auto dist2 = 1 * m;
|
||||
auto res1 = quantity_point{dist1} + quantity_point{dist2}; // ERROR
|
||||
auto res2 = dist1 - quantity_point{dist2}; // ERROR
|
||||
auto res3 = quantity_point{dist1} / (2 * s); // ERROR
|
||||
auto res4 = quantity_point{std::chrono::utc_second{1s}} +
|
||||
quantity_point{std::chrono::sys_second{1s}}; // ERROR
|
||||
|
||||
Quantity Point Kinds
|
||||
--------------------
|
||||
|
||||
The same restrictions of a quantity point with respect to its quantity
|
||||
apply to a quantity point kind with respect to its quantity kind.
|
@ -1,117 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Basic Concepts
|
||||
==============
|
||||
|
||||
The most important concepts in the library are `Unit`, `Dimension`,
|
||||
`Quantity`, `QuantityPoint`, `QuantityKind`, and `QuantityPointKind`:
|
||||
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<object data="../_images/concepts.svg" type="image/svg+xml" class="align-center" style="max-width: 100%;"></object>
|
||||
|
||||
..
|
||||
https://www.planttext.com
|
||||
|
||||
@startuml
|
||||
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide circle
|
||||
hide members
|
||||
show class methods
|
||||
|
||||
package Unit <<Frame>> [[../../framework/units.html]] {
|
||||
}
|
||||
|
||||
package Dimension <<Frame>> [[../../framework/dimensions.html]] {
|
||||
}
|
||||
|
||||
package Kind <<Frame>> [[../../framework/quantity_kinds.html#kind-creation]] {
|
||||
abstract kind<Dimension> [[../../framework/quantity_kinds.html#kind-creation]]
|
||||
}
|
||||
|
||||
package PointKind <<Frame>> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
abstract point_kind<Kind, PointOrigin> [[../../framework/quantity_kinds.html#quantity-point-kinds]]
|
||||
}
|
||||
|
||||
package PointOrigin <<Frame>> [[../../framework/quantity_points.html#point-origins]] {
|
||||
abstract point_origin<Dimension> [[../../framework/quantity_points.html#point-origins]]
|
||||
}
|
||||
|
||||
package Quantity <<Frame>> [[../../framework/quantities.html]] {
|
||||
class quantity<Dimension, Unit, Rep> [[../../framework/quantities.html#construction]] {
|
||||
rep number()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityPoint <<Frame>> [[../../framework/quantity_points.html]] {
|
||||
class quantity_point<PointOrigin, Unit, Rep> [[../../framework/quantity_points.html#construction]] {
|
||||
quantity relative()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityKind <<Frame>> [[../../framework/quantity_kinds.html]] {
|
||||
class quantity_kind<Kind, Unit, Rep> [[../../framework/quantity_kinds.html#construction]] {
|
||||
quantity common()
|
||||
}
|
||||
}
|
||||
|
||||
package QuantityPointKind <<Frame>> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
class quantity_point_kind<PointKind, Unit, Rep> [[../../framework/quantity_kinds.html#quantity-point-kinds]] {
|
||||
quantity_kind relative()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Unit <.. Dimension
|
||||
|
||||
Dimension <... Quantity
|
||||
Unit <... Quantity
|
||||
|
||||
Dimension <... Kind
|
||||
Dimension <... PointOrigin
|
||||
PointOrigin <... PointKind
|
||||
Kind <... PointKind
|
||||
|
||||
Unit <... QuantityPoint
|
||||
PointOrigin <... QuantityPoint
|
||||
quantity --* quantity_point
|
||||
|
||||
Unit <... QuantityKind
|
||||
Kind <... QuantityKind
|
||||
quantity --* quantity_kind
|
||||
|
||||
Unit <... QuantityPointKind
|
||||
PointKind <... QuantityPointKind
|
||||
quantity_kind --* quantity_point_kind
|
||||
|
||||
@enduml
|
||||
|
||||
`Unit` is a basic building block of the library. Every dimension works with
|
||||
a concrete hierarchy of units. Such hierarchy defines a reference unit and
|
||||
often a few scaled versions of it. Examples: ``second``, ``metre``, ``kilometre_per_hour``.
|
||||
|
||||
`Dimension` concept matches a dimension of either a base or derived quantity.
|
||||
`base_dimension` is instantiated with a unique symbol identifier and a base
|
||||
unit. `derived_dimension` is a list of exponents of either base or other
|
||||
derived dimensions. Examples: ``si::dim_time``, ``si::dim_length``, ``si::dim_speed``.
|
||||
|
||||
`Quantity` is a concrete amount of a unit for a specified dimension with a
|
||||
specific representation. Examples: ``quantity<si::dim_time, si::second, int>``,
|
||||
``si::length<si::metre, int>``, ``si::speed<si::kilometre_per_hour>``.
|
||||
|
||||
`QuantityPoint` is an absolute `Quantity` with respect to an origin.
|
||||
Examples: timestamp (as opposed to duration), absolute temperature
|
||||
(as opposed to temperature difference).
|
||||
|
||||
`QuantityKind` is a `Quantity` with more specific usage. Examples:
|
||||
distance (``horizonal_kind``) and height (``vertical_kind``) are different kinds
|
||||
of a length quantity.
|
||||
|
||||
`QuantityPointKind` is an absolute `QuantityKind` with respect to an origin.
|
||||
Examples: altitude is a quantity point of ``vertical_kind`` (as opposed to
|
||||
height).
|
@ -1,33 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Quantity Constants
|
||||
==================
|
||||
|
||||
In the **mp-units** library quantity constants are implemented as variable
|
||||
templates of `quantity` types parametrized by the quantity's representation
|
||||
type.
|
||||
|
||||
Additionally, in case of the :term:`SI` its physical constants are put in
|
||||
separate namespaces named after the official release of the :term:`SI`
|
||||
specification. This is needed to be able to provide backward and forward
|
||||
compatibility as exact values of physical constants tend to change with time
|
||||
(in most cases they are getting more and more accurate with every
|
||||
specification release).
|
||||
|
||||
For example the speed of light constant in :term:`SI` is defined as::
|
||||
|
||||
namespace si::si2019 {
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<metre_per_second, Rep>(299792458);
|
||||
|
||||
}
|
||||
|
||||
The same constant defined for natural units may be provided as::
|
||||
|
||||
namespace natural {
|
||||
|
||||
template<Representation Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<one, Rep>(1);
|
||||
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Conversions and Casting
|
||||
=======================
|
||||
|
||||
Programmers who are not full-time programming language geeks **hate lack of
|
||||
implicit conversions** that they consider reasonable. Violate their expectations
|
||||
for reasons they consider hypothetical problems and you get disuse. In type
|
||||
terms, I usually **translate "reasonable" to "not narrowing" aka "not loosing
|
||||
information."** That can reasonably easily be explained to non-language-experts.
|
||||
|
||||
-- *Bjarne Stroustrup*
|
||||
|
||||
The library tries to follow the above principle and at the same time is also consistent
|
||||
with conversions of ``std::chrono::duration``.
|
||||
|
||||
|
||||
No Conversions
|
||||
--------------
|
||||
|
||||
No conversions (either implicit or explicit) are available across quantities of
|
||||
different dimensions::
|
||||
|
||||
si::length<si::metre> d1 = 1 * s; // Compile-time error
|
||||
si::length<si::metre> d2(1 * s); // Compile-time error
|
||||
auto d3 = quantity_cast<si::metre>(1 * s); // Compile-time error
|
||||
|
||||
|
||||
Implicit
|
||||
--------
|
||||
|
||||
Implicit conversions are allowed only across quantities of the same dimension:
|
||||
|
||||
- for integral types with ratios that guarantee no precision loss::
|
||||
|
||||
si::length<si::metre, int> d1 = 1 * km + 1 * m; // OK
|
||||
si::length<si::millimetre, int> d2 = 1 * km + 1 * m; // OK
|
||||
si::length<si::kilometre, int> d3 = 1 * km + 1 * m; // Compile-time error
|
||||
si::length<si::kilometre, int> d4(1 * km + 1 * m); // Compile-time error
|
||||
si::length<si::metre, int> d5 = 1 * m + 1 * ft; // Compile-time error
|
||||
si::length<si::metre, int> d6(1 * m + 1 * ft); // Compile-time error
|
||||
|
||||
- from an integral to a floating-point representation even in case of a truncating
|
||||
ratio::
|
||||
|
||||
si::length<si::kilometre, double> d7 = 1 * km + 1 * m; // OK
|
||||
si::length<si::metre, double> d8 = 1 * m + 1 * ft; // OK
|
||||
|
||||
- when both sides use a floating-point representation::
|
||||
|
||||
si::length<si::metre, int> d9 = 1.23 * m; // Compile-time error
|
||||
si::length<si::metre, double> d10 = 1.23 * m; // OK
|
||||
|
||||
|
||||
Explicit
|
||||
--------
|
||||
|
||||
Explicit conversions are available with the `quantity_cast`, `quantity_point_cast`,
|
||||
`quantity_kind_cast`, and `quantity_point_kind_cast` function templates.
|
||||
They are especially useful to force a truncating conversion across quantities of the same
|
||||
dimension for integral representation types and ratios that may cause precision loss::
|
||||
|
||||
si::length<si::kilometre, int> d1 = quantity_cast<kilometre>(1 * km + 1 * m); // OK
|
||||
si::length<si::kilometre, int> d2 = quantity_cast<kilometre>(1 * s); // Error
|
||||
|
||||
.. seealso::
|
||||
|
||||
Explicit casts are also really useful when working with legacy interfaces.
|
||||
More information on this subject can be found in the
|
||||
:ref:`use_cases/legacy_interfaces:Working with Legacy Interfaces` chapter.
|
||||
|
||||
Quantity Cast Overloads
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`quantity_cast` comes with several overloads:
|
||||
|
||||
.. code-block::
|
||||
:linenos:
|
||||
|
||||
std::cout << "Distance: " << quantity_cast<si::length<si::metre, int>>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::dim_length>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::metre>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<int>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::dim_length, si::metre>(d) << '\n';
|
||||
|
||||
`quantity_cast` in line #1 takes a specific target `quantity` type to which an explicit
|
||||
cast should be performed. This option will change multiple quantity properties at once
|
||||
(unit, representation, etc). However, it is also possible to force only some properties at
|
||||
once and leave the rest intact:
|
||||
|
||||
- line #2 forces only a specific destination dimension type,
|
||||
- line #3 forces only a specific destination unit type,
|
||||
- line #4 sets only a representation type to the type provided by the user,
|
||||
- line #5 forces both a specific dimension and a unit while preserving the original
|
||||
representation type.
|
||||
|
||||
`quantity_point_cast` takes anything that works for `quantity_point`
|
||||
or a specific target `quantity_point`::
|
||||
|
||||
std::cout << "Point: " << quantity_point_cast<decltype(quantity_point{0 * m})>(d) << '\n';
|
||||
|
||||
For a single explicit template argument, `quantity_point_kind_cast` is a superset of
|
||||
`quantity_kind_cast`, which is also a superset of `quantity_cast`.
|
||||
For the (dimension, unit) pair of explicit arguments case of `quantity_cast`,
|
||||
`quantity_point_kind_cast` and `quantity_kind_cast` accept a `PointKind` and `Kind`
|
||||
instead of a `Dimension`, respectively.
|
||||
|
||||
.. seealso::
|
||||
|
||||
For more information on conversion and casting and on how to extend the above
|
||||
"integral" vs "floating-point" logic please refer to the
|
||||
:ref:`use_cases/custom_representation_types:Using Custom Representation Types` chapter.
|
||||
|
||||
|
||||
Implicit conversions of dimensionless quantities
|
||||
------------------------------------------------
|
||||
|
||||
As noted in the :ref:`framework/quantities:Dimensionless Quantities` chapter,
|
||||
:term:`quantity of dimension one` is somehow special but still obey most of the rules defined
|
||||
for quantities. However, as they represent numbers it would be highly uncomfortable to every
|
||||
time type::
|
||||
|
||||
const auto d1 = 10 * km;
|
||||
const auto d2 = 3 * km;
|
||||
if(d1 / d2 > dimensionless<one>(2)) {
|
||||
// ...
|
||||
}
|
||||
|
||||
or::
|
||||
|
||||
const auto fill_time_left = (box.height / box.fill_level(measured_mass) -
|
||||
dimensionless<one>(1)) * fill_time;
|
||||
|
||||
This is why it was decided to allow the ``dimensionless<one>`` quantity of any
|
||||
representation type to be implicitly constructible from this representation type.
|
||||
With that the above examples can be rewritten as follows::
|
||||
|
||||
const auto d1 = 10 * km;
|
||||
const auto d2 = 3 * km;
|
||||
if(d1 / d2 > 2) {
|
||||
// ...
|
||||
}
|
||||
|
||||
and::
|
||||
|
||||
const auto fill_time_left = (box.height / box.fill_level(measured_mass) - 1) * fill_time;
|
||||
|
||||
The above is true only for dimensionless quantities of `one` unit. If our quantity have a unit with
|
||||
ratio different than ``1`` the implicit conversion will not happen. This is to prevent cases were the code
|
||||
could be ambiguous. For example::
|
||||
|
||||
Dimensionless auto foo(Length auto d1, Length auto d2)
|
||||
{
|
||||
return d1 / d2 + 1;
|
||||
}
|
||||
|
||||
As long as we can reason about what such code means for ``foo(10 * km, 2 * km)`` it is not that obvious
|
||||
at all in the case of ``foo(10 * cm, 2 * ft)``. To make such code to compile for every case we have to
|
||||
either change the type of the resulting unit to the one having ``ratio(1)`` (:term:`coherent derived unit`)::
|
||||
|
||||
Dimensionless auto foo(Length auto d1, Length auto d2)
|
||||
{
|
||||
return quantity_cast<one>(d1 / d2) + 1;
|
||||
}
|
||||
|
||||
or to explicitly state what is the unit of our dimensionless value, e.g. `one`, `percent`, etc::
|
||||
|
||||
Dimensionless auto foo(Length auto d1, Length auto d2)
|
||||
{
|
||||
return d1 / d2 + dimensionless<one>(1);
|
||||
}
|
||||
|
||||
There is one more important point to note here. As the the dimensionless quantity is more than just
|
||||
a number, it is never implicitly converted back to the representation type. This means that the following
|
||||
code will not compile::
|
||||
|
||||
auto v = std::exp(10 * m / (5 * m));
|
||||
|
||||
To make it compile fine we have to either explicitly get the value stored in the quantity::
|
||||
|
||||
auto v = std::exp(quantity_cast<one>(10 * m / (5 * m)).number());
|
||||
|
||||
or use a mathematical wrapper function from `units` namespace::
|
||||
|
||||
auto v = units::exp(10 * m / (5 * m));
|
||||
|
||||
.. important::
|
||||
|
||||
Always remember to explicitly cast the quantity to the destination unit with `quantity_cast` before
|
||||
calling `quantity::number()`!
|
@ -1,206 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Dimensions
|
||||
==========
|
||||
|
||||
In the previous chapter we briefly introduced the notion of a physical
|
||||
:term:`dimension`. Now it is time to learn much more about this subject.
|
||||
Length, time, speed, area, energy are only a few examples of physical
|
||||
dimensions.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<object data="../_images/dimensions.svg" type="image/svg+xml" class="align-center" style="max-width: 100%;"></object>
|
||||
|
||||
..
|
||||
https://www.planttext.com
|
||||
|
||||
|
||||
Base Dimensions
|
||||
---------------
|
||||
|
||||
The quantities of base dimensions are called
|
||||
:term:`base quantities <base quantity>` which are the atomic building blocks
|
||||
of a :term:`system of quantities`. For example the The International System
|
||||
of Units (:term:`SI`) defines 7 of them: length, mass, time, electric
|
||||
current, thermodynamic temperature, substance, and luminous intensity.
|
||||
|
||||
To define a new base dimension the `base_dimension` class template is
|
||||
provided. For example the SI base dimension of length can be defined as::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct dim_length : base_dimension<"L", metre> {};
|
||||
|
||||
}
|
||||
|
||||
In the above code sample ``"L"`` is an base dimension's unique identifier
|
||||
and `isq::si::metre` is a :term:`base unit` of this base dimension. We can
|
||||
obtain those back easily with::
|
||||
|
||||
static_assert(si::dim_length::symbol == "L");
|
||||
static_assert(is_same_v<si::dim_length::base_unit, si::metre>);
|
||||
|
||||
|
||||
Derived Dimensions
|
||||
------------------
|
||||
|
||||
The quantities of derived dimensions are called
|
||||
:term:`derived quantities <derived quantity>` and are derived from base
|
||||
quantities. This means that they are created by multiplying or dividing
|
||||
quantities of other dimensions.
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
All other quantities, with the exception of counts, are derived quantities, which may be
|
||||
written in terms of base quantities according to the equations of physics. The dimensions of
|
||||
the derived quantities are written as products of powers of the dimensions of the base
|
||||
quantities using the equations that relate the derived quantities to the base quantities.
|
||||
In general the dimension of any quantity :math:`Q` is written in the form of a dimensional product,
|
||||
|
||||
:math:`dim Q = T^\alpha L^\beta M^\gamma I^\delta \Theta^\varepsilon N^\zeta J^\eta`
|
||||
|
||||
where the exponents :math:`\alpha`, :math:`\beta`, :math:`\gamma`, :math:`\delta`, :math:`\varepsilon`,
|
||||
:math:`\zeta` and :math:`\eta`, which are generally small integers, which can be positive,
|
||||
negative, or zero, are called the dimensional exponents.
|
||||
|
||||
Looking at the previous code snippets the area, speed, or frequency are
|
||||
the examples of such quantities. Each derived quantity can be represented
|
||||
as a unique list of exponents of base quantities. For example:
|
||||
|
||||
- an area is a length base quantity raised to the exponent ``2``
|
||||
- a speed is formed from the length base quantity with exponent ``1``
|
||||
and time base quantity with exponent ``-1``.
|
||||
|
||||
The above dimensions can be defined in the library with the
|
||||
`derived_dimension` class template as follows::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct dim_area : derived_dimension<dim_area, square_metre,
|
||||
exponent<dim_length, 2>> {};
|
||||
struct dim_speed : derived_dimension<dim_speed, metre_per_second,
|
||||
exponent<dim_length, 1>, exponent<dim_time, -1>> {};
|
||||
|
||||
}
|
||||
|
||||
In the above code sample `isq::si::square_metre` and
|
||||
`isq::si::metre_per_second` are the
|
||||
:term:`coherent derived units <coherent derived unit>` of those derived dimensions.
|
||||
|
||||
Coherent unit argument is followed by the list of exponents that form this
|
||||
derived dimension. This list is called a :term:`recipe` of this derived
|
||||
dimension and may contain both base and derived dimensions. In the latter
|
||||
case the dimension is being extracted to base dimensions by the framework
|
||||
itself. The order and types of dimensions used in the recipe determine how
|
||||
an dimension's unnamed unit symbol is being printed in the text output.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information on how the :term:`recipe` affect the printed symbol
|
||||
of unnamed unit can be found in the :ref:`framework/units:Derived Unnamed Units`
|
||||
chapter.
|
||||
|
||||
It is important to mention here that beside text output the order and
|
||||
the number of elements in the `derived_dimension` definition does not
|
||||
matter. Even if we define the above as:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 4, 6
|
||||
|
||||
namespace si {
|
||||
|
||||
struct dim_area : derived_dimension<dim_area, square_metre,
|
||||
exponent<dim_length, 1>, exponent<dim_length, 1>> {};
|
||||
struct dim_speed : derived_dimension<dim_speed, metre_per_second,
|
||||
exponent<dim_time, -1>, exponent<dim_length, 1>> {};
|
||||
|
||||
}
|
||||
|
||||
the library will do its magic and will end up with the same
|
||||
:term:`normalized derived dimension` which will allow the dimensional
|
||||
analysis in the library to work as expected.
|
||||
|
||||
.. note::
|
||||
|
||||
The first template argument of `derived_dimension` is the type of the
|
||||
child class inherited from the instantiation of this `derived_dimension`
|
||||
class template. This is called a
|
||||
:abbr:`CRTP (Curiously Recurring Template Parameter)` Idiom and is used
|
||||
in many places in this library to provide
|
||||
:ref:`design/downcasting:The Downcasting Facility`.
|
||||
|
||||
|
||||
Obtaining a Unit of the Dimension
|
||||
---------------------------------
|
||||
|
||||
In order to obtain the base/coherent unit of any dimension type a
|
||||
`dimension_unit` helper was introduced::
|
||||
|
||||
static_assert(is_same_v<dimension_unit<si::dim_length>, si::metre>);
|
||||
static_assert(is_same_v<dimension_unit<si::dim_speed>, si::metre_per_second>);
|
||||
|
||||
|
||||
|
||||
|
||||
How do you feel about:
|
||||
|
||||
inline constexpr second second;
|
||||
?
|
||||
|
||||
We could do the same to dimensions to not have to type dim_length{} all the time.
|
||||
|
||||
6 replies 2 new
|
||||
@JohelEGP
|
||||
JohelEGP
|
||||
2 days ago
|
||||
mp_units::units::second is a variable. The reference isq::si::second could stay a type and s continue to be a variable.
|
||||
|
||||
@mpusz
|
||||
mpusz
|
||||
2 days ago
|
||||
Maintainer
|
||||
Author
|
||||
The problem is the following:
|
||||
|
||||
Variables are really needed for a new design. We can ask users to put {} after every dimension unit, and reference types but it would be really nasty and a lot of boilerplate.
|
||||
Short names have to be opt-in as they collide with a lot of code (especially on MSVC).
|
||||
@JohelEGP
|
||||
JohelEGP
|
||||
yesterday
|
||||
As pointed out by #389 (reply in thread), I think it'd be OK suffix _t to the types.
|
||||
|
||||
@mpusz
|
||||
mpusz
|
||||
10 hours ago
|
||||
Maintainer
|
||||
Author
|
||||
It will be visible in the compilation errors, which is inconvenient :-(
|
||||
|
||||
Instead of:
|
||||
|
||||
quantity<reference<derived_dimension<length_dim, per<time_dim>>, derived_unit<metre, per<second>>>
|
||||
we will have something like:
|
||||
|
||||
quantity<reference<derived_dimension<length_dim_t, per<time_dim_t>>, derived_unit<metre_t, per<second_t>>>
|
||||
Personally, I like the first output more.
|
||||
|
||||
Note that definition like:
|
||||
|
||||
inline constexpr second second;
|
||||
besides, being really unconventional, is allowed by the language and will not impact our users at all. A user is about to always work with values in the code and observe types in the compilation errors. Using the same nicely blends those two domains together.
|
||||
|
||||
@mpusz
|
||||
mpusz
|
||||
10 hours ago
|
||||
Maintainer
|
||||
Author
|
||||
I could use a list of values instead of types as template parameters in the dervied_dimension and derived_unit but in such case the error would look like:
|
||||
|
||||
quantity<reference<derived_dimension<length_dim{}, per<time_dim{}>{}>{}, derived_unit<metre{}, per<second{}>{}>{}>>
|
||||
which also is not that nice.
|
||||
|
||||
@JohelEGP
|
||||
JohelEGP
|
||||
6 hours ago
|
||||
That's convincing. This justification should definitely be part of the documentation.
|
@ -1,121 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Magnitudes
|
||||
==========
|
||||
|
||||
The ratio of two Units of the same Dimension---say, ``inches`` and ``centimeters``---is some
|
||||
constant number, which is known at compile time. It's a positive real number---a *Magnitude*.
|
||||
|
||||
We also use Magnitudes for *Dimensionless* Units. ``percent`` has a Magnitude of :math:`1/100`, and
|
||||
``dozen`` would have a Magnitude of :math:`12`.
|
||||
|
||||
Interestingly, it turns out that the usual numeric types are not up to this task. We need a
|
||||
Magnitude representation that can do everything Units can do. This means, among other things:
|
||||
|
||||
1. We need *exact* symbolic computation of the core operations of Quantity Calculus (i.e., products
|
||||
and rational powers).
|
||||
|
||||
2. We must support *irrational* Magnitudes, because they frequently occur in practice (e.g.,
|
||||
consider the ratio between ``degrees`` and ``radians``).
|
||||
|
||||
3. We should *avoid overflow* wherever possible (note that ``std::intmax_t`` can't even handle
|
||||
certain simple SI prefixes, such as ``yotta``, representing :math:`10^{24}`).
|
||||
|
||||
Integers' inadequacies are clear enough, but even floating point falls short. Imagine if we
|
||||
implemented all angular units in terms of ``radians``: then both ``degrees`` and ``revolutions``
|
||||
pick up a factor of :math:`\pi`. The arithmetic with *its floating point representation* is
|
||||
unlikely to cancel *exactly*.
|
||||
|
||||
Another common alternative choice is ``std::ratio``, but this fails the first requirement: rational
|
||||
numbers are (`rather infamously <https://hsm.stackexchange.com/a/7>`_!) *not* closed under rational
|
||||
powers.
|
||||
|
||||
The only viable solution we have yet encountered is the *vector space representation*. The
|
||||
implementation is fascinating---but, for purposes of this present page, it's also a distraction.
|
||||
*Here,* we're more focused on how to *use* these Magnitudes.
|
||||
|
||||
One type per Magnitude, one value per type
|
||||
------------------------------------------
|
||||
|
||||
Each typical numeric type (``double``, ``int64_t``, ...) can represent a wide variety of values: the
|
||||
more, the better. However, Magnitudes are **not** like that. Instead, they comprise a *variety* of
|
||||
types, and each type can hold only *one* value.
|
||||
|
||||
.. tip::
|
||||
|
||||
A given Magnitude represents the *same* number, whether you use it as a *type*, or as a *value*
|
||||
(i.e., an *instance* of that type).
|
||||
|
||||
Use whichever is more convenient. (In practice, this is usually the *value*: especially for end
|
||||
users rather than library developers.)
|
||||
|
||||
If these types can only represent one value each, why would we bother to instantiate them? Because
|
||||
*values are easier to use*.
|
||||
|
||||
- ``mag<N>()`` gives the Magnitude value corresponding to any integer ``N``. - You can combine
|
||||
values in the usual way using ``*``, ``/``, ``==``, and ``!=``, as well as ``pow<N>(m)`` and
|
||||
``root<N>(m)`` for any Magnitude value ``m``.
|
||||
|
||||
Traits: integers and rational Magnitudes
|
||||
----------------------------------------
|
||||
|
||||
If you have a Magnitude instance ``m``, we provide traits to help you reason about integers and
|
||||
rational numbers, or manipulate integer or rational parts.
|
||||
|
||||
- ``is_integral(m)``: indicates whether ``m`` represents an *integral* Magnitude.
|
||||
- ``is_rational(m)``: indicates whether ``m`` represents a *rational* Magnitude.
|
||||
|
||||
The above traits indicate what kind of Magnitude we already have. The next traits *manipulate* a
|
||||
Magnitude, letting us break it apart into *constituent* Magnitudes which may be more meaningful.
|
||||
(For example, imagine going from ``inches`` to ``feet``. Naively, we might multiply by the floating
|
||||
point representation of ``1.0 / 12.0``. However, if we broke this apart into separate numerator and
|
||||
denominator, it would let us simply *divide by 12*, yielding **exact** results for inputs that
|
||||
happen to be multiples of 12.)
|
||||
|
||||
- ``numerator(m)`` (value): a Magnitude representing the "numerator", i.e., the largest integer
|
||||
which divides ``m``, without turning any of its base powers' exponents negative (or making any
|
||||
previously-negative exponents *more* negative). - ``denominator(m)`` (value): the "numerator" of
|
||||
the *inverse* of ``m``.
|
||||
|
||||
These traits interact as one would hope. For example, ``is_rational(m)`` is exactly equivalent to
|
||||
``m == numerator(m) / denominator(m)``.
|
||||
|
||||
Why these particular definitions? Because they are equivalent to the numerator and denominator when
|
||||
we have a rational number, and they are compatible with how humans write numbers when we don't.
|
||||
Example:
|
||||
|
||||
- :math:`m1 = \frac{27 \pi^2}{25}`. Then ``numerator(m1) == mag<27>()``, and
|
||||
``denominator(m1) == mag<25>()``.
|
||||
- :math:`m2 = \sqrt{m1}`. Then ``numerator(m2) == mag<3>()``, and ``denominator(m2) == mag<5>()``.
|
||||
Note that this is consistent with how humans would typically write ``m2``, as
|
||||
:math:`\frac{3\sqrt{3} \pi}{5}`.
|
||||
|
||||
Getting values out
|
||||
------------------
|
||||
|
||||
Magnitude types represent numbers in non-numeric types. They've got some amazing strengths (exact
|
||||
rational powers!), and some significant weaknesses (no support for basic addition!). So what if you
|
||||
just want to turn a Magnitude ``m`` into a traditional numeric type ``T``?
|
||||
|
||||
You call ``get_value<T>(m)``.
|
||||
|
||||
This does what it looks like it does, and it does it at compile time. Any intermediate computations
|
||||
take place in the "widest type in category"---``long double`` for floating point, and
|
||||
``std::intmax_t`` or ``std::uintmax_t`` for signed or unsigned integers---before ultimately being
|
||||
cast back to the target type. For ``T = float``, say, this means we get all the precision we'd have
|
||||
with something like ``long double``, but without any speed penalty at runtime!
|
||||
|
||||
``get_value<T>(m)`` also has the protections you would hope: for example, if ``T`` is an integral
|
||||
type, we require ``is_integral(m)``.
|
||||
|
||||
How to use Magnitudes
|
||||
---------------------
|
||||
|
||||
- First, start with your basic inputs: this will typically be ``mag<N>()`` for any integer ``N``, or
|
||||
the built-in Magnitude constant ``mag_pi``. (Again, these are all *values*, not types.)
|
||||
|
||||
- Next, combine and manipulate these using the various "Magnitude math" operations, all of which are
|
||||
**exact**: ``*``, ``/``, ``pow<N>``, ``root<N>``, ``numerator()``, ``denominator()``.
|
||||
|
||||
- If you need to translate a Magnitude ``m`` to a "real" numeric type ``T``, call
|
||||
``get_value<T>(m)``.
|
@ -1,643 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Quantities
|
||||
==========
|
||||
|
||||
A :term:`quantity` is a concrete amount of a unit for a specified dimension
|
||||
with a specific representation and is represented in the library with a
|
||||
`quantity` class template.
|
||||
|
||||
|
||||
Construction
|
||||
------------
|
||||
|
||||
To create the quantity object from a :term:`scalable number` we just have to pass
|
||||
the value to the `quantity` class template explicit constructor::
|
||||
|
||||
quantity<si::dim_length, si::kilometre, double> d(123);
|
||||
quantity<si::dim_speed, si::kilometre_per_hour, int> v(70);
|
||||
|
||||
.. note::
|
||||
|
||||
As the constructor is explicit, the quantity object can be created from
|
||||
an "unsafe" fundamental type only via
|
||||
`direct initialization <https://en.cppreference.com/w/cpp/language/direct_initialization>`_.
|
||||
This is why the code below using
|
||||
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
||||
**does not compile**::
|
||||
|
||||
quantity<si::dim_length, si::kilometre, double> d = 123; // ERROR
|
||||
|
||||
|
||||
Quantity Construction Helpers
|
||||
-----------------------------
|
||||
|
||||
.. important::
|
||||
|
||||
Currently the library provides multiple experimental helpers to instantiate
|
||||
quantities of different dimensions and units. Users are encourages to try them
|
||||
out, vote, and share feedback in this
|
||||
`discussion on GitHub <https://github.com/mpusz/units/discussions/274>`_.
|
||||
|
||||
Most probably only one of the options will be included in the final product so
|
||||
please do not hesitate to vote on the one that suits you the best.
|
||||
|
||||
Dimension-Specific Aliases (Experimental)
|
||||
+++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
To simplify `quantity` objects creation the library provides helper aliases for
|
||||
quantities of each :term:`dimension` which additionally set the representation
|
||||
type to ``double`` by default::
|
||||
|
||||
namespace si {
|
||||
|
||||
template<Unit U, Representation Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
template<Unit U, Representation Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
}
|
||||
|
||||
Thanks to that, the above example can be rewritten as follows::
|
||||
|
||||
si::length<si::kilometre> d(123);
|
||||
si::speed<si::kilometre_per_hour, int> v(70);
|
||||
|
||||
Unit-Specific Aliases (Experimental)
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Additionally to the dimension-specific aliases there are also ones provided for
|
||||
each and every :term:`unit` in the library::
|
||||
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
namespace units::aliases::isq::si::inline length {
|
||||
|
||||
template<Representation Rep = double> using m = units::isq::si::length<units::isq::si::metre, Rep>;
|
||||
template<Representation Rep = double> using km = units::isq::si::length<units::isq::si::kilometre, Rep>;
|
||||
|
||||
}
|
||||
|
||||
namespace units::aliases::isq::si::inline speed {
|
||||
|
||||
template<Representation Rep = double> using m_per_s = units::isq::si::speed<units::isq::si::metre_per_second, Rep>;
|
||||
template<Representation Rep = double> using km_per_h = units::isq::si::speed<units::isq::si::kilometre_per_hour, Rep>;
|
||||
|
||||
}
|
||||
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
||||
Using the above our code can look as follows::
|
||||
|
||||
using namespace units::aliases::isq;
|
||||
si::length::km<> d(123);
|
||||
si::speed::km_per_h<int> v(70);
|
||||
|
||||
Please note that with the C++20 :abbr:`CTAD (Class Template Argument Deduction)` support
|
||||
for alias templates the above can be rewritten as::
|
||||
|
||||
using namespace units::aliases::isq;
|
||||
si::length::km d(123.);
|
||||
si::speed::km_per_h v(70);
|
||||
|
||||
which will deduce the representation type automatically from the initializer provided
|
||||
by the user.
|
||||
|
||||
Also, this feature allows to be more terse if desired::
|
||||
|
||||
using namespace units::aliases::isq::si;
|
||||
auto d = km(123.);
|
||||
auto v = km_per_h(70);
|
||||
|
||||
Quantity References (Experimental)
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
Quantity References provide an alternative and simplified way to create quantities.
|
||||
They are defined using the `reference` class template::
|
||||
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace length_references {
|
||||
|
||||
inline constexpr auto km = reference<dim_length, kilometre>{};
|
||||
|
||||
} // namespace length_references
|
||||
|
||||
namespace time_references {
|
||||
|
||||
inline constexpr auto h = reference<dim_time, hour>{};
|
||||
|
||||
} // namespace time_references
|
||||
|
||||
namespace references {
|
||||
|
||||
using namespace length_references;
|
||||
using namespace time_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
With the above our code can look as follows::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
auto d = 123. * km; // si::length<si::kilometre, double>
|
||||
auto v = 70 * (km / h); // si::speed<si::kilometre_per_hour, int>
|
||||
|
||||
.. important::
|
||||
|
||||
The following syntaxes are not allowed:
|
||||
``2 / s``, ``km * 3``, ``s / 4``, ``70 * km / h``.
|
||||
|
||||
It is also possible to easily define custom quantity references from existing ones::
|
||||
|
||||
inline constexpr auto Nm = N * m;
|
||||
inline constexpr auto km_per_h = km / h;
|
||||
inline constexpr auto mph = mi / h;
|
||||
|
||||
|
||||
User Defined Literals (Experimental)
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Alternatively, to construct quantities with compile-time known values the library provides
|
||||
:abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`::
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
constexpr auto operator"" _q_km(unsigned long long l) { return length<kilometre, std::int64_t>(l); }
|
||||
constexpr auto operator"" _q_km(long double l) { return length<kilometre, long double>(l); }
|
||||
|
||||
constexpr auto operator"" _q_km_per_h(unsigned long long l) { return speed<kilometre_per_hour, std::int64_t>(l); }
|
||||
constexpr auto operator"" _q_km_per_h(long double l) { return speed<kilometre_per_hour, long double>(l); }
|
||||
|
||||
}
|
||||
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
Thanks to them the same code can be as simple as::
|
||||
|
||||
using namespace units::isq::si::literals;
|
||||
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>
|
||||
|
||||
.. note::
|
||||
|
||||
``123._q_km`` should be read as a quantity of length in kilometers. Initially the
|
||||
library did not use the ``_q_`` prefix for UDLs but it turned out that there are
|
||||
a few unit symbols that collide with literals already existing in C and C++
|
||||
language (i.e. ``F`` (farad), ``J`` (joule), ``W`` (watt), ``K`` (kelvin),
|
||||
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
|
||||
``_q_`` prefix was consistently applied to all the UDLs.
|
||||
|
||||
UDLs vs Quantity References
|
||||
+++++++++++++++++++++++++++
|
||||
|
||||
UDLs are helpful but they also have some disadvantages compared to Quantity References:
|
||||
|
||||
1. UDLs are only for compile-time known values and do not work for runtime variables
|
||||
|
||||
- UDLs::
|
||||
|
||||
using namespace units::isq::si::literals;
|
||||
auto v1 = 120_q_km / 2_q_h;
|
||||
auto v2 = length<kilometre>(distance) / time<hour>(duration);
|
||||
|
||||
- Quantity References::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
auto v1 = 120 * km / (2 * h);
|
||||
auto v2 = distance * (1 * km) / (duration * (1 * h));
|
||||
|
||||
References treat both cases in a unified way. It is also worth to notice that we work
|
||||
mostly with runtime variables and compile-time known values mostly appear only in physical
|
||||
constants and unit tests.
|
||||
|
||||
2. UDLs cannot be disambiguated with a namespace name
|
||||
|
||||
- UDLs::
|
||||
|
||||
using namespace units::isq::si::literals;
|
||||
using namespace units::isq::si::cgs::literals;
|
||||
auto d = 1_q_cm; // FAILS TO COMPILE
|
||||
|
||||
- Quantity References::
|
||||
|
||||
inline constexpr auto si_cm = units::isq::si::references::cm;
|
||||
inline constexpr auto cgs_cm = units::isq::si::cgs::references::cm;
|
||||
|
||||
auto d1 = 1. * si_cm; // si::length<si::centimetre>
|
||||
auto d2 = 1. * cgs_cm; // si::cgs::length<si::centimetre>
|
||||
|
||||
3. Poor control over the representation types as UDLs return only ``std::int64_t`` or
|
||||
``long double``
|
||||
|
||||
- UDLs::
|
||||
|
||||
using namespace units::isq::si::literals;
|
||||
auto d1 = 123._q_km; // si::length<si::kilometre, long double>
|
||||
auto d2 = 123_q_km; // si::length<si::kilometre, std::int64_t>
|
||||
|
||||
No possibility to obtain any other representation type. Additionally this gets contagious
|
||||
as the result of every arithmetic expression on quantities is always expanded to the common
|
||||
type of its arguments. For example `si::length<si::metre, int>(1) + 1_q_m` results in a
|
||||
`si::length<si::metre, int64_t>` type.
|
||||
|
||||
- Quantity References::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
auto d1 = 123. * km; // si::length<si::kilometre, double>
|
||||
auto d2 = 123 * km; // si::length<si::kilometre, int>
|
||||
auto d3 = 123.f * km; // si::length<si::kilometre, float>
|
||||
auto d4 = 123.L * km; // si::length<si::kilometre, long double>
|
||||
auto d5 = 123ul * km; // si::length<si::kilometre, unsigned long>
|
||||
auto d6 = 123ll * km; // si::length<si::kilometre, long long>
|
||||
|
||||
4. UDLs are verbose to define and standardize
|
||||
|
||||
- UDLs:
|
||||
|
||||
- for each unit an integral and a floating-point UDL have to be defined
|
||||
- have to be provided for unnamed derived units (i.e. ``_q_km_per_h``)
|
||||
|
||||
- Quantity References:
|
||||
|
||||
- one reference per unit
|
||||
- unnamed derived units are constructed from base references so no explicit
|
||||
definition is required (i.e. ``km / h``)
|
||||
|
||||
5. Typical UDL definition for quantities when compiled with a ``-Wsign-conversion``
|
||||
flag results in a compilation warning. This warning could be silenced with a
|
||||
``static_cast<std::int64_t>(value)`` in every UDL, but in a such case other safety
|
||||
and security issues could be silently introduced.
|
||||
Quantity References, on the opposite, always use the exact representation type provided
|
||||
by the user so there is no chance for a truncating conversion on a quantity construction.
|
||||
|
||||
6. UDLs take long to compile
|
||||
|
||||
- UDLs:
|
||||
|
||||
Every unit requires two UDLs to be defined which in turns requires two instantiations
|
||||
of "heavy" `quantity` class template. Those are then not often used by non-UDL construction
|
||||
as most users instantiate `quantity` class template with `int` or `double` which
|
||||
again have to be separately instantiated. This has a significant impact on the compile-time
|
||||
performance.
|
||||
|
||||
- Quantity References:
|
||||
|
||||
`reference` class template is "cheaper" to instantiate. Additionally, every unit requires
|
||||
only one instantiation of a `reference` class template. Such pre-defined reference instance
|
||||
is then shared among all the instantiations of `quantity` class template for this specific
|
||||
unit (no matter of its representation type). With this approach we end up with much less class
|
||||
template instantiations in the application.
|
||||
|
||||
|
||||
Quantity References vs Unit-specific Aliases
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
1. Shadowing issues
|
||||
|
||||
- Quantity References
|
||||
|
||||
References occupy a pool of many short identifiers which sometimes shadow the variables,
|
||||
function arguments, or even template parameters provided by the user or other libraries. This
|
||||
results in warnings being generated by some compilers. The most restrictive here is MSVC which
|
||||
for example emits a warning of shadowing ``N`` template parameter for an array size provided
|
||||
in a header file with Newton unit included via namespace declaration in the ``main()`` program
|
||||
function (see `experimental_angle <https://github.com/mpusz/units/blob/master/example/references/experimental_angle.cpp>`_).
|
||||
In other cases user is forced to rename its local identifiers to not collide with predefined
|
||||
references (see `capacitor_time_curve <https://github.com/mpusz/units/blob/master/example/references/capacitor_time_curve.cpp>`_).
|
||||
|
||||
- Unit-specific Aliases
|
||||
|
||||
As aliases are defined in terms of types rather variables no major shadowing issues were found
|
||||
so far. In case of identifiers ambiguity it was always possible to disambiguate with more
|
||||
namespaces prefixed in front of the alias.
|
||||
|
||||
2. Adjustable verbosity
|
||||
|
||||
- Quantity References
|
||||
|
||||
References allow creating custom helpers for complex units. Instead of typing::
|
||||
|
||||
static_assert(2 * km / (2 * (km / h)) == 1 * h);
|
||||
|
||||
one can do the following::
|
||||
|
||||
inline constexpr auto kmph = km / h;
|
||||
static_assert(2 * km / (2 * kmph) == 1 * h);
|
||||
|
||||
- Unit-specific Aliases
|
||||
|
||||
There is no need to create custom helpers for complex units as most of them are predefined in
|
||||
a library already. However, this feature also allows controlling verbosity of the code. For
|
||||
example in the below example ``d1``, ``d2``, and ``d3`` will end up being of the same type
|
||||
and having the same value::
|
||||
|
||||
auto d1 = m(123.45);
|
||||
double a = 123.45;
|
||||
auto d2 = m(a);
|
||||
auto d3 = length::m(a);
|
||||
|
||||
3. Readability
|
||||
|
||||
- Quantity References
|
||||
|
||||
As long as references are easy to understand in the following code::
|
||||
|
||||
auto d = 123 * m;
|
||||
|
||||
it is not that nice when a variable is used instead of a compile time number::
|
||||
|
||||
constexpr Speed auto avg_speed(double d, double t)
|
||||
{
|
||||
using namespace units::isq::si::length_references;
|
||||
using namespace units::isq::si::time_references;
|
||||
return d * m / (t * s);
|
||||
}
|
||||
|
||||
Notice that if ``using namespace units::isq::si::references;`` was used instead above it could
|
||||
cause a clash of ``t`` function parameter with ``si::tonne`` unit symbol if ``si/mass.h`` was
|
||||
included.
|
||||
|
||||
- Unit-specific Aliases
|
||||
|
||||
The same using aliases can look as follows::
|
||||
|
||||
constexpr Speed auto avg_speed(double d, double t)
|
||||
{
|
||||
using namespace units::aliases::isq::si;
|
||||
return m(d) / s(t);
|
||||
}
|
||||
|
||||
or::
|
||||
|
||||
constexpr Speed auto avg_speed(double d, double t)
|
||||
{
|
||||
using namespace units::aliases::isq::si;
|
||||
return length::m(d) / time::s(t);
|
||||
}
|
||||
|
||||
4. Operators Precedence
|
||||
|
||||
- Quantity References
|
||||
|
||||
The syntax for references uses ``*`` operator which has some predefined precedence. This operator
|
||||
always takes a magnitude or a reference as ``lhs`` and a reference as ``rhs``. All other combinations
|
||||
are not allowed. It means that in order to satisfy the operators precedence sometimes quite a lot
|
||||
of parenthesis have to be sprinkled in the code in order for the code to compile::
|
||||
|
||||
static_assert(2 * km / (2 * (km / h)) == 1 * h);
|
||||
|
||||
- Unit-specific Aliases
|
||||
|
||||
Aliases do not use operator syntax thus they are not affected by the precedence issue.
|
||||
|
||||
5. Composition for unnamed derived units
|
||||
|
||||
- Quantity References
|
||||
|
||||
References have only to be defined for named units. Also for the user's convenience references are
|
||||
predefined for units raised to a specific power (e.g. ``m2``, ``km3``, etc). All other derived units
|
||||
can be constructed using the provided ones already even if they do not correspond to any predefined
|
||||
dimension::
|
||||
|
||||
inline constexpr auto kmph = km / h;
|
||||
inline constexpr auto kmph3 = kmph * kmph * kmph;
|
||||
|
||||
- Unit-specific Aliases
|
||||
|
||||
Such a feature is not possible with aliases. In order to create a derived unit a full alias template
|
||||
has to be explicitly provided::
|
||||
|
||||
template<Representation Rep = double> using km_per_h = units::isq::si::speed<units::isq::si::kilometre_per_hour, Rep>;
|
||||
|
||||
6. Explicit control over the representation type
|
||||
|
||||
Both options here allow to preserve user provide representation type but only aliases allow
|
||||
to override it if needed.
|
||||
|
||||
7. Simplified quantity casting
|
||||
|
||||
Aliases can easily replace ``quantity_cast<Unit>()`` which is not possible with references::
|
||||
|
||||
constexpr auto meter = 1 * m;
|
||||
std::cout << " = " << quantity_cast<si::international::foot>(meter) << '\n';
|
||||
|
||||
The above code for references may look as follows::
|
||||
|
||||
constexpr auto meter = m(1);
|
||||
std::cout << " = " << international::ft(meter) << '\n';
|
||||
std::cout << " = " << ft(meter) << '\n';
|
||||
|
||||
The above will preserve the representation type of the source type.
|
||||
|
||||
8. Compilation performance
|
||||
|
||||
For our experiments it seems that aliases are 2-5x faster to compile than references (declaring an
|
||||
alias template is much faster than instantiating a class template).
|
||||
|
||||
|
||||
Summary
|
||||
+++++++
|
||||
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Feature | Aliases | References | UDLs |
|
||||
+===============================================+=============+============+===============+
|
||||
| Literals and variables support | **Yes** | **Yes** | Literals only |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Preserves user provided representation type | **Yes** | **Yes** | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Explicit control over the representation type | **Yes** | No | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Possibility to resolve ambiguity | **Yes** | **Yes** | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Readability | **Good** | Medium | **Good** |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Hard to resolve shadowing issues | **No** | Yes | **No** |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Operators precedence issue | **No** | Yes | **No** |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Controlled verbosity | **Yes** | No | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Easy composition for derived units | No | **Yes** | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Simplified quantity casting | **Yes** | No | No |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Implementation and standardization effort | Medium | **Lowest** | Highest |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
| Compile-time performance | **Fastest** | Medium | Slowest |
|
||||
+-----------------------------------------------+-------------+------------+---------------+
|
||||
|
||||
|
||||
Don't pay for what you don't use (compile-time performance)
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
As noted in the previous chapter, each quantity creation helper has a different impact on the compile-time
|
||||
performance. Aliases tend to be the fastest to compile but even their definition can be expensive for some
|
||||
if it is not used in the source code. This is why it is possible to opt-out from each or every quantity
|
||||
creation helper with the following preprocessor defines::
|
||||
|
||||
#define UNITS_NO_ALIASES
|
||||
#define UNITS_NO_REFERENCES
|
||||
#define UNITS_NO_LITERALS
|
||||
|
||||
|
||||
Dimension-specific Concepts
|
||||
---------------------------
|
||||
|
||||
In case the user does not care about the specific unit and representation but
|
||||
requires quantity of a concrete dimension than dimension-specific concepts can
|
||||
be used::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
constexpr Length auto d = 123 * km; // si::length<si::kilometre, int>
|
||||
|
||||
.. note::
|
||||
|
||||
All instances of `quantity` class always match the `Quantity` concept.
|
||||
All other regular types that are not quantities are called
|
||||
:term:`scalable numbers <scalable number>` by the library and match the
|
||||
`Representation` concept.
|
||||
|
||||
However, the above is not the most important usage of those concepts. Let's
|
||||
assume that the user wants to implement an ``avg_speed`` function that will
|
||||
be calculating the average speed based on provided distance and duration
|
||||
quantities. The usage of such a function can look as follows::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
using namespace units::isq::si::international::references;
|
||||
constexpr Speed auto v1 = avg_speed(220 * km, 2 * h);
|
||||
constexpr Speed auto v2 = avg_speed(140 * mi, 2 * h);
|
||||
|
||||
In this and all other physical units libraries such a function can be
|
||||
implemented as::
|
||||
|
||||
constexpr si::speed<si::metre_per_second> avg_speed(si::length<si::metre> d,
|
||||
si::time<si::second> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
While being correct, this function performs unnecessary intermediate
|
||||
conversions (from kilometers to meters, from hours to seconds,
|
||||
and from meters per second to kilometers per hour) which can affect
|
||||
runtime performance and the precision of the final result. To eliminate
|
||||
all that overhead we have to write a template function::
|
||||
|
||||
template<typename U1, typename R1, typename U2, typename R2>
|
||||
constexpr auto avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
This function will work for every SI unit and representation without any
|
||||
unnecessary overhead. It is also simple enough to prove its implementation
|
||||
being correct just by a simple inspection. However, it might not always be
|
||||
the case. For more complicated calculations we would like to ensure that we
|
||||
are returning a physical quantity of a correct dimension. For this
|
||||
dimension-specific concepts come handy again and with usage of C++20 generic
|
||||
functions our function can look as simple as::
|
||||
|
||||
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
Now we are sure that the dimension of returned quantity is correct. Also
|
||||
please note that with the above code we implemented a truly generic function
|
||||
that works efficiently not only with SI units but also with other systems of
|
||||
units like CGS.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Please refer to :ref:`examples/basics/avg_speed:avg_speed` example for more
|
||||
information on different kinds of interfaces supported by the library.
|
||||
|
||||
|
||||
Working With Constrained Deduced Quantity Types
|
||||
-----------------------------------------------
|
||||
|
||||
It is important to note that when we assign a result from the function to an
|
||||
automatically deduced type, even if it is constrained by a dimension-specific
|
||||
concept, we still do not know what is the exact unit and representation type
|
||||
of such a quantity. In many cases it might be exactly what we want to get,
|
||||
but often we would like to know a specific type too. We have two options here:
|
||||
|
||||
- query the actual dimension, unit, and representation types::
|
||||
|
||||
constexpr Speed auto v = avg_speed(220 * km, 2 * h);
|
||||
using quantity_type = decltype(v);
|
||||
using dimension_type = quantity_type::dimension;
|
||||
using unit_type = quantity_type::unit;
|
||||
using rep_type = quantity_type::rep;
|
||||
|
||||
- convert or cast to a desired quantity type::
|
||||
|
||||
constexpr Speed auto v1 = avg_speed(220. * km, 2 * h);
|
||||
constexpr si::speed<si::metre_per_second> v2 = v1;
|
||||
constexpr Speed auto v3 = quantity_cast<si::speed<si::metre_per_second>(v1);
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information on this subject can be found in the
|
||||
:ref:`framework/conversions_and_casting:Conversions and Casting` chapter.
|
||||
|
||||
|
||||
Dimensionless Quantities
|
||||
------------------------
|
||||
|
||||
Whenever we divide two quantities of the same dimension we end up with a
|
||||
:term:`dimensionless quantity` otherwise known as :term:`quantity of dimension one`::
|
||||
|
||||
static_assert(10 * km / (5 * km) == 2);
|
||||
static_assert(std::is_same_v<decltype(10 * km / (5 * km)), quantity<dim_one, one, int>>);
|
||||
|
||||
According to the official ISO definition `dim_one` is a dimension "for which all the
|
||||
exponents of the factors corresponding to the base quantities in its quantity dimension
|
||||
are zero".
|
||||
|
||||
.. seealso::
|
||||
|
||||
Reasoning for the above design is provided in
|
||||
:ref:`faq:Why a dimensionless quantity is not just an fundamental arithmetic type?`
|
||||
|
||||
To simplify the usage of the dimensionless quantity a following concept and alias template
|
||||
are provided::
|
||||
|
||||
template<typename T>
|
||||
concept Dimensionless = QuantityOf<T, dim_one>;
|
||||
|
||||
template<Unit U, Representation Rep = double>
|
||||
using dimensionless = quantity<dim_one, U, Rep>;
|
||||
|
||||
There are two special units provided for usage with such a quantity:
|
||||
|
||||
- `one` which is the :term:`coherent derived unit` of dimensionless quantity and does not
|
||||
provide any textual symbol (according to the ISO definition "the measurement units and
|
||||
values of quantities of dimension one are numbers"),
|
||||
- `percent` which has the symbol ``%`` and ``ratio(1, 100)`` of the `one` unit.
|
||||
|
||||
For example the following code::
|
||||
|
||||
std::cout << quantity_cast<percent>(50. * m / (100. * m)) << '\n';
|
||||
|
||||
will print ``50 %`` to the console output.
|
||||
|
||||
Again, according to the ISO definition "such quantities convey more information than a
|
||||
number". This is exactly what we observe in the above example. The value stored inside
|
||||
the quantity, the text output, and the value returned by the `quantity::number()` member
|
||||
function is ``50`` rather than ``0.5``. It means that dimensionless quantities behave
|
||||
like all other quantities and store the value in terms of a ratio of a coherent unit.
|
||||
This allows us to not loose precision when we divide quantities of the same dimensions
|
||||
but with units having vastly different ratios, e.g.
|
||||
`Dimensionless Hubble parameter <https://en.wikipedia.org/wiki/Hubble%27s_law#Dimensionless_Hubble_parameter>`_
|
||||
is expressed as a ratio of kilometers and megaparsecs.
|
||||
|
||||
.. seealso::
|
||||
|
||||
More information on dimensionless quantities can be found in the
|
||||
:ref:`framework/conversions_and_casting:Implicit conversions of dimensionless quantities`
|
||||
chapter.
|
@ -1,77 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Quantity Kinds
|
||||
==============
|
||||
|
||||
A quantity kind is a quantity of more specific usage.
|
||||
It is represented in the library with a `quantity_kind` class template.
|
||||
|
||||
|
||||
Kind Creation
|
||||
-------------
|
||||
|
||||
We need a `kind` to represent the more specific usage of a quantity::
|
||||
|
||||
struct radius : kind<radius, si::dim_length> {};
|
||||
|
||||
Quantities of kind ``radius`` represent a radius.
|
||||
They are clearly distinct from more generic usages of length quantities.
|
||||
|
||||
|
||||
Construction
|
||||
------------
|
||||
|
||||
To create the quantity kind object from a `quantity` we just have to pass
|
||||
the value to the `quantity_kind` class template constructor::
|
||||
|
||||
quantity_kind<radius, si::kilometre, double> d(123 * km);
|
||||
|
||||
.. note::
|
||||
|
||||
As the constructor without the kind argument is explicit,
|
||||
the quantity object can be created from a quantity only via
|
||||
`direct initialization <https://en.cppreference.com/w/cpp/language/direct_initialization>`_.
|
||||
This is why the code below using
|
||||
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
||||
**does not compile**::
|
||||
|
||||
quantity_kind<radius, si::kilometre, double> d = 123 * km; // ERROR
|
||||
|
||||
|
||||
Differences To Quantity
|
||||
-----------------------
|
||||
|
||||
The library provides:
|
||||
|
||||
- no kinds, such as ``radius`` or ``width``, therefore
|
||||
|
||||
* no UDLs or quantity references,
|
||||
* no kind-specific concepts, such as ``Radius``,
|
||||
(there's the generic `QuantityKind` and kind-specifiable `QuantityKindOf`),
|
||||
|
||||
- a slightly larger set of operations on quantity kinds
|
||||
(see the :ref:`framework/dimensions:Quantity Kinds` chapter).
|
||||
|
||||
|
||||
Quantity Point Kinds
|
||||
--------------------
|
||||
|
||||
A quantity point kind is the analogous of a quantity point for quantity kinds
|
||||
(see the :ref:`framework/quantity_points:Quantity Points` chapter).
|
||||
|
||||
They are represented in the library with a `quantity_point_kind` class template.
|
||||
|
||||
First, we need a `point_kind` for a `kind`::
|
||||
|
||||
struct width : kind<width, si::dim_length> {};
|
||||
struct x_coordinate : point_kind<x_coordinate, width> {};
|
||||
|
||||
Now ``x`` coordinates can be constructed::
|
||||
|
||||
quantity_point_kind<x_coordinate, si::metre, int> auto x_pos(123 * m); // QuantityPointKindOf<x_coordinate>
|
||||
auto x = x_pos.relative(); // quantity_kind<width, si::metre, int>(123 * m)
|
||||
|
||||
.. seealso::
|
||||
|
||||
Please refer to :ref:`examples/basics/glide_computer:glide_computer` example for more
|
||||
information on the quantity kinds usage.
|
@ -1,51 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Quantity-like Types
|
||||
===================
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<object data="../_images/quantity_like.svg" type="image/svg+xml" class="align-center" style="max-width: 100%;"></object>
|
||||
|
||||
..
|
||||
https://www.planttext.com
|
||||
|
||||
@startuml
|
||||
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide members
|
||||
hide circle
|
||||
|
||||
class quantity [[../framework/quantities.html]]
|
||||
class quantity_point [[../framework/quantity_points.html]]
|
||||
class quantity_kind [[../framework/quantity_kinds.html]]
|
||||
class quantity_point_kind [[../framework/quantity_kinds.html#quantity-point-kinds]]
|
||||
|
||||
Rep <-- quantity : number()
|
||||
quantity <-- quantity_point : relative()
|
||||
quantity <-- quantity_kind : common()
|
||||
quantity_kind <-- quantity_point_kind : relative()
|
||||
|
||||
@enduml
|
||||
|
||||
|
||||
[ISO80000]_ defines a :term:`quantity` as a:
|
||||
|
||||
Property of a phenomenon, body, or substance, where the property has a magnitude that can be expressed by
|
||||
means of a number and a reference.
|
||||
|
||||
You can use `quantity::number()` member function to get a concrete amount of a unit expressed with a specific
|
||||
representation type ``Rep``.
|
||||
|
||||
:term:`Kind of quantity <kind of quantity>` is defined as:
|
||||
|
||||
Aspect common to mutually comparable quantities.
|
||||
|
||||
We can obtain a `quantity` with a `quantity_kind::common()` member function.
|
||||
|
||||
`quantity_point` and `quantity_point_kind` are absolute quantities and quantity kinds relative to some
|
||||
specific origin. `quantity` and `quantity_point` types can be obtained from them using a ``relative()`` member
|
||||
function (`quantity_point::relative()`, `quantity_point_kind::relative()`).
|
@ -1,52 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Quantity Points
|
||||
===============
|
||||
|
||||
A quantity point is an absolute quantity with respect to an origin
|
||||
and is represented in the library with a `quantity_point` class template.
|
||||
|
||||
Point Origins
|
||||
-------------
|
||||
|
||||
We need a `point_origin` to represent the origin of a quantity point::
|
||||
|
||||
struct mean_sea_level : point_origin<si::dim_length> {};
|
||||
|
||||
Quantities points with this origin represent a point from the mean sea level.
|
||||
|
||||
The library offers a `dynamic_origin<Dimension>`
|
||||
for quantity points whose origin is not specified in the type system.
|
||||
|
||||
|
||||
Construction
|
||||
------------
|
||||
|
||||
To create the quantity point object from a `quantity` we just have to pass
|
||||
the value to the `quantity_point` class template explicit constructor::
|
||||
|
||||
quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d(123 * km);
|
||||
|
||||
.. note::
|
||||
|
||||
As the constructor is explicit, the quantity object can be created from
|
||||
a quantity only via
|
||||
`direct initialization <https://en.cppreference.com/w/cpp/language/direct_initialization>`_.
|
||||
This is why the code below using
|
||||
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
||||
**does not compile**::
|
||||
|
||||
quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d = 123 * km; // ERROR
|
||||
|
||||
|
||||
Differences To Quantity
|
||||
-----------------------
|
||||
|
||||
Unlike `quantity`, the library provides:
|
||||
|
||||
- no helper aliases for quantity points, such as ``length_point``,
|
||||
- no UDLs for quantity points,
|
||||
- no dimension-specific concepts, such as ``LengthPoint``
|
||||
(there's the dimension-agnostic `QuantityPoint`),
|
||||
- a more limited set of operations on quantity points
|
||||
(see the :ref:`framework/arithmetics:Quantity Points` chapter)
|
@ -1,224 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Text Output
|
||||
===========
|
||||
|
||||
Beside providing dimensional analysis and units conversions, the library
|
||||
also tries really hard to print any quantity in the most user friendly way.
|
||||
|
||||
.. note::
|
||||
|
||||
The library provides no text output for
|
||||
quantity points or quantity (point) kinds.
|
||||
|
||||
Output Streams
|
||||
--------------
|
||||
|
||||
.. tip::
|
||||
|
||||
The streaming support is provided via the ``<units/quantity_io.h>`` header file.
|
||||
|
||||
The easiest way to print a quantity is to provide its object to the output
|
||||
stream::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
using namespace units::isq::si::international::references;
|
||||
constexpr Speed auto v1 = avg_speed(220. * km, 2 * h);
|
||||
constexpr Speed auto v2 = avg_speed(140. * mi, 2 * h);
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
|
||||
The text output will always print the :term:`value of a quantity` followed
|
||||
by a space and then the symbol of a :term:`unit` associated with this quantity.
|
||||
|
||||
.. important::
|
||||
|
||||
Remember that it is a good practice to always `quantity_cast()` a quantity
|
||||
of an unknown ``auto`` type before passing it to the text output::
|
||||
|
||||
std::cout << quantity_cast<si::kilometre_per_hour>(v1) << '\n'; // 110 km/h
|
||||
std::cout << quantity_cast<si::metre_per_second>(v1) << '\n'; // 30.5556 m/s
|
||||
|
||||
|
||||
Stream Output Formatting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Only a basic formatting can be applied for output streams. It includes control
|
||||
over width, fill, and alignment::
|
||||
|
||||
os << "|" << std::setw(10) << 123 * m << "|"; // | 123 m|
|
||||
os << "|" << std::setw(10) << std::left << 123 * m << "|"; // |123 m |
|
||||
os << "|" << std::setw(10) << std::setfill('*') << 123 * m << "|"; // |*****123 m|
|
||||
|
||||
|
||||
std::format
|
||||
-----------
|
||||
|
||||
.. tip::
|
||||
|
||||
The text formatting support is provided via the ``<units/format.h>`` header file.
|
||||
|
||||
The **mp-units** via ``std::format`` provides a fine-grained control over what
|
||||
and how is being printed on the text output.
|
||||
|
||||
|
||||
Grammar
|
||||
^^^^^^^
|
||||
|
||||
.. productionlist::
|
||||
units-format-spec: [fill-and-align] [width] [units-specs]
|
||||
units-specs: conversion-spec
|
||||
: units-specs conversion-spec
|
||||
: units-specs literal-char
|
||||
literal-char: any character other than '{' or '}'
|
||||
conversion-spec: '%' units-type
|
||||
units-type: [units-rep-modifier] 'Q'
|
||||
: [units-unit-modifier] 'q'
|
||||
: one of "nt%"
|
||||
units-rep-modifier: [sign] [#] [precision] [L] [units-rep-type]
|
||||
units-rep-type: one of "aAbBdeEfFgGoxX"
|
||||
units-unit-modifier: 'A'
|
||||
|
||||
In the above grammar:
|
||||
|
||||
- ``fill-and-align``, ``width``, ``sign``, ``#``, ``precision`` and ``L`` tokens and
|
||||
individual tokens of :token:`units-rep-type` are defined in the
|
||||
`format.string.std <https://wg21.link/format.string.std>`_ chapter of the C++
|
||||
standard specification,
|
||||
- tokens ``Q``, ``q``, ``n``, ``t``, and ``%`` of :token:`units-type` are described
|
||||
in the `time.format <https://wg21.link/time.format>`_ chapter of the C++ standard
|
||||
specification,
|
||||
- ``A`` token of :token:`units-unit-modifier` forces ASCII-only output (instead of the
|
||||
default Unicode symbols defined by the :term:`SI` specification).
|
||||
|
||||
|
||||
Default formatting
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To format `quantity` values the formatting facility uses :token:`units-format-spec`.
|
||||
In case it is left empty the default formatting of ``{:%Q %q}`` is applied. The same
|
||||
default formatting is also applied to the output streams. This is why the following
|
||||
code lines produce the same output::
|
||||
|
||||
std::cout << "Distance: " << 123 * km << "\n";
|
||||
std::cout << std::format("Distance: {}\n", 123 * km);
|
||||
std::cout << std::format("Distance: {:%Q %q}\n", 123 * km);
|
||||
|
||||
|
||||
Quantity Value, Symbol, or Both?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The user can easily decide to either print a whole quantity (value and symbol) or
|
||||
only its parts. Also a different quantity formatting might be applied::
|
||||
|
||||
std::cout << std::format("{:%Q}", 123 * km); // 123
|
||||
std::cout << std::format("{:%q}", 123 * km); // km
|
||||
std::cout << std::format("{:%Q%q}", 123 * km); // 123km
|
||||
|
||||
|
||||
Controlling Width, Fill, and Alignment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To control width, fill, and alignment the C++ standard grammar tokens ``fill-and-align``
|
||||
and ``width`` are being used and they treat a quantity value and symbol as a contiguous
|
||||
text::
|
||||
|
||||
std::cout << std::format("|{:0}|", 123 * m); // |123 m|
|
||||
std::cout << std::format("|{:10}|", 123 * m); // | 123 m|
|
||||
std::cout << std::format("|{:<10}|", 123 * m); // |123 m |
|
||||
std::cout << std::format("|{:>10}|", 123 * m); // | 123 m|
|
||||
std::cout << std::format("|{:^10}|", 123 * m); // | 123 m |
|
||||
std::cout << std::format("|{:*<10}|", 123 * m); // |123 m*****|
|
||||
std::cout << std::format("|{:*>10}|", 123 * m); // |*****123 m|
|
||||
std::cout << std::format("|{:*^10}|", 123 * m); // |**123 m***|
|
||||
|
||||
|
||||
ASCII-only Quantity Symbols
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Unit symbols of some quantities are specified to use Unicode signs by the :term:`SI`
|
||||
standard (i.e. ``Ω`` symbol for the resistance quantity). **mp-units** library follows
|
||||
this by default. From the engineering point of view sometimes Unicode text might
|
||||
not be a solution as terminals of many (especially embedded) devices are ASCII-only.
|
||||
In such a case the unit symbol can be forced to be printed using ASCII-only characters::
|
||||
|
||||
std::cout << std::format("{}", 10 * R); // 10 Ω
|
||||
std::cout << std::format("{:%Q %Aq}", 10 * R); // 10 ohm
|
||||
std::cout << std::format("{}", 125 * us); // 125 µs
|
||||
std::cout << std::format("{:%Q %Aq}", 125 * us); // 125 us
|
||||
inline constexpr auto s2 = s * s;
|
||||
std::cout << std::format("{}", 9.8 * (m / s2)); // 9.8 m/s²
|
||||
std::cout << std::format("{:%Q %Aq}", 9.8 * (m / s2)); // 9.8 m/s^2
|
||||
|
||||
|
||||
Controlling on How the Quantity Value Is Being Printed
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``sign`` token allows us to specify on how the value's sign is being printed::
|
||||
|
||||
std::cout << std::format("{0:%Q %q},{0:%+Q %q},{0:%-Q %q},{0:% Q %q}", 1 * m); // 1 m,+1 m,1 m, 1 m
|
||||
std::cout << std::format("{0:%Q %q},{0:%+Q %q},{0:%-Q %q},{0:% Q %q}", -1 * m); // -1 m,-1 m,-1 m,-1 m
|
||||
|
||||
where:
|
||||
|
||||
- ``+`` indicates that a sign should be used for both non-negative and negative numbers,
|
||||
- ``-`` indicates that a sign should be used for negative numbers and negative zero only
|
||||
(this is the default behavior),
|
||||
- ``<space>`` indicates that a leading space should be used for non-negative numbers other
|
||||
than negative zero, and a minus sign for negative numbers and negative zero.
|
||||
|
||||
``precision`` token is allowed only for floating-point representation types::
|
||||
|
||||
std::cout << std::format("{:%.0Q %q}", 1.2345 * m); // 1 m
|
||||
std::cout << std::format("{:%.1Q %q}", 1.2345 * m); // 1.2 m
|
||||
std::cout << std::format("{:%.2Q %q}", 1.2345 * m); // 1.23 m
|
||||
|
||||
|
||||
:token:`units-rep-type` specifies how a value of the representation type is being
|
||||
printed. For integral types::
|
||||
|
||||
std::cout << std::format("{:%bQ %q}", 42 * m); // 101010 m
|
||||
std::cout << std::format("{:%BQ %q}", 42 * m); // 101010 m
|
||||
std::cout << std::format("{:%dQ %q}", 42 * m); // 42 m
|
||||
std::cout << std::format("{:%oQ %q}", 42 * m); // 52 m
|
||||
std::cout << std::format("{:%xQ %q}", 42 * m); // 2a m
|
||||
std::cout << std::format("{:%XQ %q}", 42 * m); // 2A m
|
||||
|
||||
The above can be printed in an alternate version thanks to the ``#`` token::
|
||||
|
||||
std::cout << std::format("{:%#bQ %q}", 42 * m); // 0b101010 m
|
||||
std::cout << std::format("{:%#BQ %q}", 42 * m); // 0B101010 m
|
||||
std::cout << std::format("{:%#oQ %q}", 42 * m); // 052 m
|
||||
std::cout << std::format("{:%#xQ %q}", 42 * m); // 0x2a m
|
||||
std::cout << std::format("{:%#XQ %q}", 42 * m); // 0X2A m
|
||||
|
||||
For floating-point values the :token:`units-rep-type` token works as follows::
|
||||
|
||||
std::cout << std::format("{:%aQ %q}", 1.2345678 * m); // 0x9.e065152d8eae841p-3 m
|
||||
std::cout << std::format("{:%.3aQ %q}", 1.2345678 * m); // 0x9.e06p-3 m
|
||||
std::cout << std::format("{:%AQ %q}", 1.2345678 * m); // 0X9.E065152D8EAE841P-3 m
|
||||
std::cout << std::format("{:%.3AQ %q}", 1.2345678 * m); // 0X9.E06P-3 m
|
||||
std::cout << std::format("{:%eQ %q}", 1.2345678 * m); // 1.234568e+00 m
|
||||
std::cout << std::format("{:%.3eQ %q}", 1.2345678 * m); // 1.235e+00 m
|
||||
std::cout << std::format("{:%EQ %q}", 1.2345678 * m); // 1.234568E+00 m
|
||||
std::cout << std::format("{:%.3EQ %q}", 1.2345678 * m); // 1.235E+00 m
|
||||
std::cout << std::format("{:%gQ %q}", 1.2345678 * m); // 1.23457 m
|
||||
std::cout << std::format("{:%gQ %q}", 1.2345678e8 * m); // 1.23457e+08 m
|
||||
std::cout << std::format("{:%.3gQ %q}", 1.2345678 * m); // 1.23 m
|
||||
std::cout << std::format("{:%.3gQ %q}", 1.2345678e8 * m); // 1.23e+08 m
|
||||
std::cout << std::format("{:%GQ %q}", 1.2345678 * m); // 1.23457 m
|
||||
std::cout << std::format("{:%GQ %q}", 1.2345678e8 * m); // 1.23457E+08 m
|
||||
std::cout << std::format("{:%.3GQ %q}", 1.2345678 * m); // 1.23 m
|
||||
std::cout << std::format("{:%.3GQ %q}", 1.2345678e8 * m); // 1.23E+08 m
|
||||
|
||||
|
||||
Special Signs
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Beside adding any list of regular characters as a separator between the value and the
|
||||
symbol, it is possible to type a few special signs there too::
|
||||
|
||||
std::cout << std::format("{:%Q_%q}", 123 * km); // 123_km
|
||||
std::cout << std::format("{:%Q%t%q}", 123 * km); // 123\tkm <tab>
|
||||
std::cout << std::format("{:%Q%n%q}", 123 * km); // 123\nkm <new line>
|
||||
std::cout << std::format("{:%Q%% %q}", 123 * km); // 123% km
|
@ -1,453 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Units
|
||||
=====
|
||||
|
||||
Each quantity has a magnitude (a numerical value). In order to be able to
|
||||
compare quantities of the same dimension a notion of a :term:`measurement unit`
|
||||
was introduced. Units are designated by conventionally assigned names and
|
||||
symbols. Thanks to them it is possible to compare two quantities of the
|
||||
same dimension and express the ratio of the second quantity to the first
|
||||
one as a number. For example ``10 s`` is ``10`` times more than ``1 s``.
|
||||
|
||||
Base quantities are expressed in terms of :term:`base units <base unit>`
|
||||
(i.e. ``m`` (meter), ``s`` (second)), while derived quantities are expressed
|
||||
in terms of :term:`derived units <derived unit>`.
|
||||
|
||||
|
||||
Class Hierarchy
|
||||
---------------
|
||||
|
||||
All of the described here class templates to produce unit types inherit from some instance
|
||||
of a `scaled_unit` class template:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<object data="../_images/units.svg" type="image/svg+xml" class="align-center" style="max-width: 100%;"></object>
|
||||
|
||||
..
|
||||
https://www.planttext.com
|
||||
|
||||
@startuml
|
||||
|
||||
skinparam monochrome true
|
||||
skinparam shadowing false
|
||||
skinparam backgroundColor #fcfcfc
|
||||
|
||||
hide members
|
||||
hide circle
|
||||
|
||||
left to right direction
|
||||
|
||||
package Unit <<Frame>> [[../../framework/units.html]] {
|
||||
|
||||
abstract scaled_unit<UnitRatio, Unit>
|
||||
|
||||
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
|
||||
abstract alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
|
||||
abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
|
||||
abstract derived_unit [[../../framework/units.html#derived-unnamed-units]]
|
||||
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
|
||||
abstract named_scaled_unit<Symbol, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
|
||||
abstract named_unit<Symbol> [[../../framework/units.html#base-units]]
|
||||
|
||||
scaled_unit <|-- named_unit
|
||||
scaled_unit <|-- named_scaled_unit
|
||||
scaled_unit <|-- prefixed_unit
|
||||
scaled_unit <|-- derived_unit
|
||||
scaled_unit <|-- derived_scaled_unit
|
||||
scaled_unit <|-- alias_unit
|
||||
scaled_unit <|-- prefixed_alias_unit
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
||||
`scaled_unit` is a class template used exclusively by the library's framework
|
||||
and user should not instantiate it by him/her-self. However the user can sometimes
|
||||
observe this type in case an unit/dimension conversion expression will end up with an
|
||||
unknown/undefined unit type like in the below example::
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
|
||||
Length auto l = 100 * (km / h) * (10 * s);
|
||||
|
||||
The type of ``l`` above will be
|
||||
``si::length<scaled_unit<ratio(1, 36, 1), si::metre>, long double>``. This is caused
|
||||
by the fact that the library does not define a unit of a length quantity that has the
|
||||
ratio ``10/36`` of a ``si::metre``. If such a unit was predefined we would see its concrete
|
||||
type here instead.
|
||||
|
||||
|
||||
Base Units
|
||||
----------
|
||||
|
||||
:term:`Base units <base unit>` are the units of
|
||||
:term:`base quantities <base quantity>` defined for
|
||||
:term:`base dimensions <base dimension>`. For example in :term:`SI`
|
||||
``m`` (meter) is a base unit of length, ``s`` (second) is a base unit of
|
||||
time. In each :term:`coherent system of units`, there is only one base
|
||||
unit for each base quantity. This is why a base unit type is required by
|
||||
the `base_dimension` definition in this library. For example ``si::dim_length``
|
||||
can be defined in the following way::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct dim_length : base_dimension<"L", metre> {};
|
||||
|
||||
}
|
||||
|
||||
where ``si::metre`` is defined as::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct metre : named_unit<metre, "m", prefix> {};
|
||||
|
||||
}
|
||||
|
||||
In the above definition ``"m"`` is the unit symbol to be used in the text
|
||||
output, and ``si::prefix`` specifies that the library should allow
|
||||
definitions of prefixed units using ``si::metre`` as a reference (i.e.
|
||||
``si::centimetre``).
|
||||
|
||||
.. seealso::
|
||||
|
||||
For more information on prefixes and scaling please refer to
|
||||
`Scaled Units`_.
|
||||
|
||||
.. note::
|
||||
|
||||
The first template argument of `named_unit` is the type of the
|
||||
child class inherited from the instantiation of this `named_unit`
|
||||
class template. This is called a
|
||||
:abbr:`CRTP (Curiously Recurring Template Parameter)` Idiom and is used
|
||||
in many places in this library to provide
|
||||
:ref:`design/downcasting:The Downcasting Facility`.
|
||||
|
||||
|
||||
It is important to notice here that :term:`SI` is not the only system used
|
||||
in the industry and the library has to support other systems too. Also
|
||||
in some cases conversions between such systems should be allowed. Thanks to
|
||||
the fact that the `base_dimension` takes the base unit type in its definition
|
||||
allows us to easily define various systems of units for the same physical
|
||||
dimension. For example length in the
|
||||
`CGS <https://en.wikipedia.org/wiki/Centimetre%E2%80%93gram%E2%80%93second_system_of_units>`_
|
||||
could be defined as::
|
||||
|
||||
namespace si::cgs {
|
||||
|
||||
struct dim_length : base_dimension<"L", si::centimetre> {};
|
||||
|
||||
}
|
||||
|
||||
The fact that both base dimensions use the same identifier ``"L"`` tells
|
||||
the library that both definitions refer to the same physical dimension of
|
||||
length. The only difference is the measurement unit used to define their
|
||||
base dimensions. Thanks to using the unit that is defined in terms of the
|
||||
the same reference unit as the one provided to ``si::dim_length`` definition
|
||||
(namely ``si::centimetre`` which is ``1/100`` of ``si::metre``) we also enabled
|
||||
the ability to easily convert between those 2 base dimensions (as the library
|
||||
knows how to convert ``si::metre`` to ``si::centimetre`` and vice versa).
|
||||
|
||||
.. seealso::
|
||||
|
||||
More details on custom systems definitions and conversions between
|
||||
units of the same physical dimension can be found in the
|
||||
:ref:`use_cases/extensions:Custom Systems` chapter.
|
||||
|
||||
|
||||
Scaled Units
|
||||
------------
|
||||
|
||||
Described above base units (in case of base quantities) and
|
||||
:term:`coherent units <coherent derived unit>` (in case of derived quantities),
|
||||
in their system of units, have proportionality factor/ratio equal to one.
|
||||
However, quantities of such dimensions can also use units of measurement
|
||||
with other ratios to describe their magnitude (numerical value).
|
||||
|
||||
|
||||
Named Scaled Units
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
We are used to use minutes, hours, or days to measure quantities of time.
|
||||
Those units are the scaled versions of a time dimension's base unit,
|
||||
namely second. Those can be defined easily in the library using
|
||||
`named_scaled_unit` class template::
|
||||
|
||||
struct minute : named_scaled_unit<minute, "min", ratio(60), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", ratio(60), minute> {};
|
||||
struct day : named_scaled_unit<day, "d", ratio(24), hour> {};
|
||||
|
||||
The `ratio` type used in the definition is really similar to ``std::ratio`` but it takes
|
||||
an additional ``Exponent`` template parameter that defines the exponent of the ratio.
|
||||
Another important difference is the fact that the objects of that class are used
|
||||
as class NTTPs rather then a type template parameter kind.
|
||||
|
||||
Thanks to it we can address nearly infinite scaling factors between units
|
||||
and define units like::
|
||||
|
||||
struct electronvolt : named_scaled_unit<electronvolt, "eV", prefix,
|
||||
ratio(1'602'176'634, 1'000'000'000, -19), joule> {};
|
||||
|
||||
Finally, the last of the `named_scaled_unit` class template parameters
|
||||
provide a reference unit for scaling. Please note that it can be a dimension's
|
||||
base/coherent unit (like ``si::second``) or any other unit (i.e. ``si::minute``,
|
||||
``si::hour``) that is a scaled version of the dimension's base/coherent unit.
|
||||
|
||||
|
||||
Prefixed Unit
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Prefixed units are just scaled units with a standardized ratio. For example
|
||||
:term:`SI` defines prefixes based on the exponent of ``10``. Here is a
|
||||
complete list of all the :term:`SI` prefixes supported by the library::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct yocto : prefix<yocto, "y", mag_power<10, -24>()> {};
|
||||
struct zepto : prefix<zepto, "z", mag_power<10, -21>()> {};
|
||||
struct atto : prefix<atto, "a", mag_power<10, -18>()> {};
|
||||
struct femto : prefix<femto, "f", mag_power<10, -15>()> {};
|
||||
struct pico : prefix<pico, "p", mag_power<10, -12>()> {};
|
||||
struct nano : prefix<nano, "n", mag_power<10, -9>()> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"},
|
||||
mag_power<10, -6>()> {};
|
||||
struct milli : prefix<milli, "m", mag_power<10, -3>()> {};
|
||||
struct centi : prefix<centi, "c", mag_power<10, -2>()> {};
|
||||
struct deci : prefix<deci, "d", mag_power<10, -1>()> {};
|
||||
struct deca : prefix<deca, "da", mag_power<10, 1>()> {};
|
||||
struct hecto : prefix<hecto, "h", mag_power<10, 2>()> {};
|
||||
struct kilo : prefix<kilo, "k", mag_power<10, 3>()> {};
|
||||
struct mega : prefix<mega, "M", mag_power<10, 6>()> {};
|
||||
struct giga : prefix<giga, "G", mag_power<10, 9>()> {};
|
||||
struct tera : prefix<tera, "T", mag_power<10, 12>()> {};
|
||||
struct peta : prefix<peta, "P", mag_power<10, 15>()> {};
|
||||
struct exa : prefix<exa, "E", mag_power<10, 18>()> {};
|
||||
struct zetta : prefix<zetta, "Z", mag_power<10, 21>()> {};
|
||||
struct yotta : prefix<yotta, "Y", mag_power<10, 24>()> {};
|
||||
|
||||
}
|
||||
|
||||
Alternative hierarchy of prefixes is the one used in data information
|
||||
domain::
|
||||
|
||||
namespace iec80000 {
|
||||
|
||||
struct kibi : prefix<kibi, "Ki", mag_power<2, 10>()> {};
|
||||
struct mebi : prefix<mebi, "Mi", mag_power<2, 20>()> {};
|
||||
struct gibi : prefix<gibi, "Gi", mag_power<2, 30>()> {};
|
||||
struct tebi : prefix<tebi, "Ti", mag_power<2, 40>()> {};
|
||||
struct pebi : prefix<pebi, "Pi", mag_power<2, 50>()> {};
|
||||
struct exbi : prefix<exbi, "Ei", mag_power<2, 60>()> {};
|
||||
struct zebi : prefix<zebi, "Zi", mag_power<2, 70>()> {};
|
||||
struct yobi : prefix<yobi, "Yi", mag_power<2, 80>()> {};
|
||||
|
||||
}
|
||||
|
||||
With the definitions like above we can easily define prefixed unit. For
|
||||
example we can define ``si::kilometre`` as::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct kilometre : prefixed_unit<kilometre, kilo, metre> {};
|
||||
|
||||
}
|
||||
|
||||
.. important::
|
||||
|
||||
Prefixed units have to use named units as a reference. For unnamed
|
||||
units we could end up with some strange, misleading, and sometimes
|
||||
wrong definitions ("kilo square metre" seams strange and spelled
|
||||
as ``km²`` would be invalid).
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
[SIBrochure]_ states:
|
||||
|
||||
However, when prefixes are used with SI units, the resulting units are no
|
||||
longer coherent, because the prefix introduces a numerical factor other than one.
|
||||
|
||||
|
||||
Derived Units
|
||||
-------------
|
||||
|
||||
:term:`Derived units <derived unit>` are the units used to measure
|
||||
:term:`derived quantities <derived quantity>`. They can either have their own unique
|
||||
names (i.e. ``N`` (newton)) or can be composed from the names of units of quantities
|
||||
used to define thier derived quantity (i.e. ``km/h``).
|
||||
|
||||
The [SIBrochure]_ states:
|
||||
|
||||
Derived units are defined as products of powers of the base units. When the numerical
|
||||
factor of this product is one, the derived units are called coherent derived units. The base
|
||||
and coherent derived units of the SI form a coherent set, designated the set of coherent SI
|
||||
units. The word “coherent” here means that equations between the numerical values of
|
||||
quantities take exactly the same form as the equations between the quantities themselves.
|
||||
|
||||
Derived Named Units
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The [SIBrochure]_ also says:
|
||||
|
||||
Some of the coherent derived units in the SI are given special names.
|
||||
|
||||
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
|
||||
(pascal)) and they are defined in the same way as base units (which
|
||||
always have to be a named unit)::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct newton : named_unit<newton, "N", prefix> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Derived Unnamed Units
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Derived unnamed units are the units where the symbol is derived from the
|
||||
base quantities symbols and the expression of the dependence of the derived
|
||||
quantity on the base quantities (i.e. ``m/s`` (metre per second), ``m²``
|
||||
(square metre)). To support such use cases a library introduced a notion of
|
||||
:term:`derived dimension recipe` which stores the information about the
|
||||
order, exponents, and types of dimensions used to define this particular
|
||||
derived dimension. For example each of the below ``momentum`` definitions
|
||||
will result in a different unnamed unit symbol:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 2-4, 6-8, 10-12
|
||||
|
||||
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
|
||||
exponent<si::dim_mass, 1>,
|
||||
exponent<si::dim_length, 1>,
|
||||
exponent<si::dim_time, -1>> {}; // kg⋅m/s
|
||||
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
|
||||
exponent<si::dim_length, 1>,
|
||||
exponent<si::dim_mass, 1>,
|
||||
exponent<si::dim_time, -1>> {}; // m⋅kg/s
|
||||
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
|
||||
exponent<si::dim_time, -1>,
|
||||
exponent<si::dim_length, 1>,
|
||||
exponent<si::dim_mass, 1>> {}; // 1/s⋅m⋅kg
|
||||
|
||||
where ``kilogram_metre_per_second`` is defined as::
|
||||
|
||||
struct kilogram_metre_per_second : derived_unit<kilogram_metre_per_second> {};
|
||||
|
||||
However, the easiest way to define momentum is just to use the
|
||||
``si::dim_speed`` derived dimension in the recipe:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3
|
||||
|
||||
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
|
||||
exponent<si::dim_mass, 1>,
|
||||
exponent<si::dim_speed, 1>> {}; // kg⋅m/s
|
||||
|
||||
In such a case the library will do its magic and will automatically
|
||||
unpack a provided derived dimension to its base dimensions in order to
|
||||
end up with a :term:`normalized derived dimension` for a parent entity.
|
||||
|
||||
The need to support a derived dimension in the recipe is not just a
|
||||
syntactic sugar that allows us to do less typing. It is worth to notice
|
||||
here that some of the derived unnamed units are defined in terms of other
|
||||
derived named units (i.e. surface tension quantity is measured in terms
|
||||
of ``N/m``):
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 2
|
||||
|
||||
struct dim_surface_tension : derived_dimension<dim_surface_tension, newton_per_metre,
|
||||
exponent<si::dim_force, 1>,
|
||||
exponent<si::dim_length, -1>> {}; // N/m
|
||||
|
||||
If we defined the above in terms of base units we would end up with
|
||||
a ``kg/s²`` derived unit symbol.
|
||||
|
||||
|
||||
Derived Scaled Units
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For some units determining of a correct scaling ratio may not be trivial,
|
||||
and even if done correctly, may be a pain to maintain. For a simple example
|
||||
let's take a "kilometre per hour" unit. What is the easiest to maintain
|
||||
ratio in reference to the "metre per second":
|
||||
|
||||
- ``1000/3600``
|
||||
- ``10/36``
|
||||
- ``5/18``
|
||||
|
||||
Whichever, we choose there will always be someone not happy with our choice.
|
||||
|
||||
Thanks to a `derived_scaled_unit` class template provided by the library this problem
|
||||
does not exist at all. With it ``si::kilometre_per_hour`` can be defined as::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct kilometre_per_hour : derived_scaled_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
|
||||
|
||||
}
|
||||
|
||||
In case the scaled derived unit should serve as a named one we can use
|
||||
a `named_derived_unit` where the user is able to provide a symbol for the unit
|
||||
by him/her-self::
|
||||
|
||||
namespace si::fps {
|
||||
|
||||
struct knot : named_derived_unit<knot, dim_speed, "knot", nautical_mile, hour> {};
|
||||
|
||||
}
|
||||
|
||||
Please note that the dervided scaled units are the only unit-related class templates
|
||||
that take a dimension as its parameter. This derived dimension provides a :term:`recipe`
|
||||
used for its definition. Based on the information stored in the recipe
|
||||
(order, type, and exponents of composite dimensions) and the ratios of units
|
||||
provided in the template parameter list after the derived dimension parameter,
|
||||
the library calculates the final ratio for this unit.
|
||||
|
||||
|
||||
Aliased Units
|
||||
-------------
|
||||
|
||||
In order to make our life easier people tend to assign alternative/aliased names
|
||||
to some popular units. As an example we often use "tonne" instead of "megagram",
|
||||
"litre" instead of "cubic decimetre", or "hectare" instead of "square hectometre".
|
||||
|
||||
This library provides facilities to define aliased names to already defined units
|
||||
with `alias_unit` class template::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct litre : alias_unit<cubic_decimetre, "l", prefix> {};
|
||||
|
||||
}
|
||||
|
||||
Also, it is possible to add prefixes to such aliased units with `prefixed_alias_unit`
|
||||
class template::
|
||||
|
||||
namespace si {
|
||||
|
||||
struct millilitre : prefixed_alias_unit<cubic_centimetre, milli, litre> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
To learn more about unknown units please refer to the
|
||||
:ref:`use_cases/unknown_dimensions:Working with Unknown Dimensions and Their Units` chapter.
|
||||
|
||||
|
||||
## System reference
|
||||
|
||||
"It is important to emphasize that each physical quantity has only one coherent SI unit, even
|
||||
though this unit can be expressed in different forms by using some of the special names and
|
||||
symbols."
|
||||
The converse, however, is not true, because in general several different quantities may
|
||||
share the same SI unit.
|
||||
|
||||
|
||||
For example, for the quantity heat capacity as well as for the
|
||||
quantity entropy the SI unit is joule per kelvin. Similarly, for the base quantity electric
|
||||
current as well as the derived quantity magnetomotive force the SI unit is the ampere. It is
|
||||
therefore important not to use the unit alone to specify the quantity.
|
@ -1,4 +0,0 @@
|
||||
.. This file is a placeholder and will be replaced during Sphinx build
|
||||
|
||||
Index
|
||||
#####
|
83
docs/getting_started/code_example.md
Normal file
83
docs/getting_started/code_example.md
Normal file
@ -0,0 +1,83 @@
|
||||
# Code Example
|
||||
|
||||
Here is a small example of operations possible on scalar quantities:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// simple numeric operations
|
||||
static_assert(10 * km / 2 == 5 * km);
|
||||
|
||||
// unit conversions
|
||||
static_assert(1 * h == 3600 * s);
|
||||
static_assert(1 * km + 1 * m == 1001 * m);
|
||||
|
||||
// dimension conversions
|
||||
inline constexpr auto kmph = km / h;
|
||||
static_assert(1 * km / (1 * s) == 1000 * (m / s));
|
||||
static_assert(2 * kmph * (2 * h) == 4 * km);
|
||||
static_assert(2 * km / (2 * kmph) == 1 * h);
|
||||
|
||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||
|
||||
static_assert(10 * km / (5 * km) == 2);
|
||||
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/j8afKnarv)"
|
||||
|
||||
|
||||
This library requires some C++20 features ([concepts and constraints](https://en.cppreference.com/w/cpp/language/constraints),
|
||||
[classes as NTTP](https://en.cppreference.com/w/cpp/language/template_parameters), ...). Thanks to them,
|
||||
the user gets a powerful but still easy-to-use interface where all unit conversions and dimensional analysis can be
|
||||
performed without sacrificing accuracy. Please see the below example for a quick preview of basic library features:
|
||||
|
||||
*[NTTP]: Non-Type Template Parameter
|
||||
|
||||
```cpp
|
||||
#include <mp-units/format.h>
|
||||
#include <mp-units/iostream.h>
|
||||
#include <mp-units/systems/international/international.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
|
||||
QuantityOf<isq::time> auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
|
||||
constexpr auto v1 = 110 * (km / h);
|
||||
constexpr auto v2 = 70 * mph;
|
||||
constexpr auto v3 = avg_speed(220. * isq::distance[km], 2 * h);
|
||||
constexpr auto v4 = avg_speed(isq::distance(140. * mi), 2 * h);
|
||||
constexpr auto v5 = v3[m / s];
|
||||
constexpr auto v6 = value_cast<m / s>(v4);
|
||||
constexpr auto v7 = value_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/T8bovrqTP)"
|
||||
|
||||
!!! note
|
||||
|
||||
You can find more code examples in the Examples chapter.
|
176
docs/getting_started/faq.md
Normal file
176
docs/getting_started/faq.md
Normal file
@ -0,0 +1,176 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## Why do we spell `metre` instead of `meter`?
|
||||
|
||||
This is how ISO 80000 defines it (British English spelling by default).
|
||||
|
||||
|
||||
## Why don't we use UDLs to create quantities?
|
||||
|
||||
Many reasons make UDLs a poor choice for a physical units library:
|
||||
|
||||
1. UDLs work only with literals (compile-time known values). Our observation is that besides
|
||||
the unit tests, there are few compile-time known constants used in the production code.
|
||||
2. Typical implementations of UDLs tend to always use the widest representation type available.
|
||||
In the case of `std::chrono::duration`, the following is true:
|
||||
|
||||
```cpp
|
||||
using namespace std::chrono_literals;
|
||||
auto d1 = 42s;
|
||||
auto d2 = 42.s;
|
||||
static_assert(std::is_same_v<decltype(d1)::rep, std::int64_t>);
|
||||
static_assert(std::is_same_v<decltype(d2)::rep, long double>);
|
||||
```
|
||||
|
||||
3. While increasing the coverage for the library, we learned that many unit symbols conflict with
|
||||
built-in types or numeric extensions. A few of those are: `F` (farad), `J` (joule), `W` (watt),
|
||||
`K` (kelvin), `d` (day), `l` or `L` (litre), `erg`, `ergps`. For a while for those we used `_` prefix
|
||||
to make the library work at all, but at some point, we had to unify the naming, and we came up with `_q_`
|
||||
prefix, which resulted in creating a quantity of a provided unit. So in case the library is
|
||||
standardized, all quantities would be created with UDLs having `q_` prefix (i.e. `42q_s`)
|
||||
which is not that nice anymore.
|
||||
|
||||
4. UDLs with the same identifiers defined in different namespace can't be disambiguated in the C++
|
||||
language. If both SI and CGS systems define `_q_s` UDL for a second unit, then it would not be possible
|
||||
to specify which one to use in case both namespaces are "imported".
|
||||
|
||||
5. Another bad property of UDLs is that they do not compose. A coherent unit of angular momentum would
|
||||
have a UDL specified as `_q_kg_m2_per_s`. Now imagine that you want to make every possible user happy.
|
||||
How many variations of that unit would you predefine for differently scaled versions of unit ingredients?
|
||||
|
||||
6. UDLs are also really expensive to define and specify. For each unit, we need two definitions. One for
|
||||
integral and another one for floating-point representation. Before the V2 framework, the coherent unit of
|
||||
angular momentum was defined as:
|
||||
|
||||
```cpp
|
||||
constexpr auto operator"" _q_kg_m2_per_s(unsigned long long l)
|
||||
{
|
||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
|
||||
return angular_momentum<kilogram_metre_sq_per_second, std::int64_t>(static_cast<std::int64_t>(l));
|
||||
}
|
||||
constexpr auto operator"" _q_kg_m2_per_s(long double l)
|
||||
{
|
||||
return angular_momentum<kilogram_metre_sq_per_second, long double>(l);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Why `60 * km / h` does not compile?
|
||||
|
||||
The library design does not allow multiplying or dividing a quantity (the result of `60 * km`)
|
||||
by another unit. This significantly limits the number of possible errors and surprises in the
|
||||
quantity equations.
|
||||
|
||||
Consider the following expression:
|
||||
|
||||
```cpp
|
||||
auto q = 60 * km / 2 * h;
|
||||
```
|
||||
|
||||
Looks like `30 km/h`, right? But it is not. If the above code was allowed, it would result
|
||||
in `30 km⋅h`. In case you want to divide `60 * km` by `2 * h` a parenthesis is needed
|
||||
`60 * km / (2 * h)`.
|
||||
|
||||
Another surprising issue could result from the following code:
|
||||
|
||||
```cpp
|
||||
template<typename T>
|
||||
auto make_length(T v) { return v * si::metre; }
|
||||
|
||||
auto v = 42;
|
||||
auto q = make_length(v);
|
||||
```
|
||||
|
||||
The above might look like a good idea, but consider what would happen in the user provided
|
||||
an already existing quantity:
|
||||
|
||||
```cpp
|
||||
auto v = 42 * m;
|
||||
auto q = make_length(v);
|
||||
```
|
||||
|
||||
Fortunately, with the current design, such issues are detected at compile-time.
|
||||
|
||||
|
||||
## Why a dimensionless quantity is not just a fundamental arithmetic type?
|
||||
|
||||
In the initial design of this library, the resulting type of division of two quantities was their
|
||||
common representation type:
|
||||
|
||||
```cpp
|
||||
static_assert(std::is_same_v<decltype(10 * km / (5 * km)), std::int64_t>);
|
||||
```
|
||||
|
||||
First of all, this was consistent with
|
||||
[`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration/operator_arith4) behavior.
|
||||
Additional reasoning behind it was not providing a false impression of a strong `quantity` type for
|
||||
something that looks and feels like a regular number. Also, all of the mathematic and trigonometric functions
|
||||
were working fine out of the box with such representation types, so we did not have to rewrite
|
||||
`sin()`, `cos()`, `exp()`, and others.
|
||||
|
||||
However, the feedback we got from the production usage was that such an approach is really bad for generic
|
||||
programming. It is hard to handle the result of the two quantities' division (or multiplication) as
|
||||
it might be either a quantity or a fundamental type. If we want to raise such a result to some power, we
|
||||
must use `units::pow` or `std::pow` depending on the resulting type. Those are only a few issues related
|
||||
to such an approach.
|
||||
|
||||
Moreover, suppose you divide quantities of the same dimension but with units of significantly different
|
||||
magnitudes. In that case, you may end up with a really small or a huge floating-point value, which may result
|
||||
in losing lots of precision. Returning a dimensionless quantity from such cases allows us to benefit from
|
||||
all the properties of scaled units and is consistent with the rest of the library.
|
||||
|
||||
!!! info
|
||||
|
||||
More information on the current design can be found in the Dimensionless Quantities chapter.
|
||||
|
||||
|
||||
## Why Unicode quantity symbols are used by default instead of ASCII-only characters?
|
||||
|
||||
Both C++ and ISO 80000 are standardized by the ISO. ISO 80000 and the SI standards specify Unicode symbols
|
||||
as the official unit names for some quantities (i.e. `Ω` symbol for the resistance quantity).
|
||||
As **mp-units** library will be proposed for standardization as a part of the C++ Standard Library
|
||||
we have to obey the rules and be consistent with ISO specifications.
|
||||
|
||||
!!! info
|
||||
|
||||
We do understand engineering reality and the constraints of some environments. This is why the library
|
||||
has the option of ASCII-only Quantity Symbols.
|
||||
|
||||
|
||||
## Why don't you have CMake options to disable the building of tests and examples?
|
||||
|
||||
Over time many people provided PRs proposing adding options to build tests and examples conditionally.
|
||||
Here are a few examples:
|
||||
|
||||
- [Add CMake options for disabling docs, examples and tests](https://github.com/mpusz/mp-units/pull/124)
|
||||
- [build: add options to disable part of the build](https://github.com/mpusz/mp-units/pull/402)
|
||||
- [CMake Refactoring and Option Cleanup](https://github.com/mpusz/mp-units/pull/456)
|
||||
|
||||
We admit this is a common practice in the industry, but we also believe this is a bad pattern.
|
||||
|
||||
First, the only need for such options comes when a user wants to use `add_subdirectory()` in CMake
|
||||
to handle dependencies. Such an approach does not scale and should be discouraged. There is little
|
||||
use for such a practice in times when we have dedicated package managers like Conan.
|
||||
|
||||
The second thing is that our observation is that many people are fixed on disabling "unneeded" subdirectories
|
||||
from compilation, but they do not see or address the biggest issue, which is polluting user's build
|
||||
environment with our development-specific settings. Propagating our restrictive compilation flags to user's
|
||||
project is not the best idea as it might cause a lot of harm if this project stops to compile
|
||||
because of that.
|
||||
|
||||
Last but not least, not having those options is on purpose. Top level _CMakeLists.txt_ file should only
|
||||
be used by **mp-units** developers and contributors as an entry point for project's development.
|
||||
We want to ensure that everyone will build **ALL** the code correctly before pushing a commit. Having
|
||||
such options would allow unintended issues to leak to PRs and CI.
|
||||
|
||||
This is why our projects have two entry points:
|
||||
|
||||
- _./CMakeLists.txt_ is to be used by projects developers to build **ALL** the project code with really
|
||||
restrictive compilation flags,
|
||||
- _./src/CMakeLists.txt_ contains only a pure library definition and should be used by the customers
|
||||
that prefer to use CMake's `add_subdirectory()` to handle the dependencies.
|
||||
|
||||
!!! info
|
||||
|
||||
For more details on this please refer to the [CMake + Conan: 3 Years Later - Mateusz Pusz](https://youtu.be/mrSwJBJ-0z8?t=1931)
|
||||
lecture that Mateusz Pusz provided at the C++Now 2021 conference.
|
449
docs/getting_started/installation_and_usage.md
Normal file
449
docs/getting_started/installation_and_usage.md
Normal file
@ -0,0 +1,449 @@
|
||||
# Installation And Usage
|
||||
|
||||
!!! info
|
||||
|
||||
**mp-units** library tries to provide the best user experience possible with the C++ language.
|
||||
To achieve that, it extensively uses C++20 features and the
|
||||
[explicit object parameter](https://en.cppreference.com/w/cpp/language/member_functions#Explicit_object_parameter)
|
||||
from C++23.
|
||||
|
||||
Even though the library benefits from C++23 (if available), C++20 is enough to compile and
|
||||
use all of the library's functionality. C++23 features are hidden behind a preprocessor macro
|
||||
providing a backward-compatible way to use it.
|
||||
|
||||
Sadly, as of today, not many compilers provide full C++20 support. The library compiles fine
|
||||
on the following compilers (or newer):
|
||||
|
||||
- gcc-12.2
|
||||
|
||||
In the upcoming weeks, we will be actively working to extend the support to other compilers as well.
|
||||
|
||||
|
||||
## Repository Structure and Dependencies
|
||||
|
||||
This repository contains three independent CMake-based projects:
|
||||
|
||||
- _./src_
|
||||
|
||||
- header-only project containing whole **mp-units** library
|
||||
- _./src/CMakeList.txt_ file is intended as an **entry point for library users**
|
||||
- in case this library becomes part of the C++ standard, it will have no external dependencies
|
||||
but until then, it depends on the following:
|
||||
|
||||
- [gsl-lite](https://github.com/gsl-lite/gsl-lite) to verify runtime contracts with
|
||||
the `gsl_Expects` macro,
|
||||
- [{fmt}](https://github.com/fmtlib/fmt) to provide text formatting of quantities
|
||||
(if `std::format` is not supported yet on a specific compiler),
|
||||
- [only for clang < 14 with libc++] [range-v3](https://github.com/ericniebler/range-v3)
|
||||
to provide needed C++20 concepts and utilities.
|
||||
|
||||
- _._
|
||||
|
||||
- project used as an **entry point for library development and CI/CD**
|
||||
- it wraps _./src_ project together with usage examples and tests
|
||||
- additionally to the dependencies of _./src_ project, it uses:
|
||||
|
||||
- `Catch2 <https://github.com/catchorg/Catch2>`_ library as a unit tests framework,
|
||||
- `linear algebra <https://github.com/BobSteagall/wg21/tree/master/include>`_
|
||||
library based on proposal `P1385 <https://wg21.link/P1385>`_ used in some examples
|
||||
and tests.
|
||||
|
||||
- in case you also want to generate the project's documentation, you will need:
|
||||
|
||||
- [Material for MkDocs](https://squidfunk.github.io/mkdocs-material)
|
||||
|
||||
- *./test_package*
|
||||
|
||||
- library installation and Conan package verification.
|
||||
|
||||
|
||||
!!! tip
|
||||
|
||||
Top level _CMakeLists.txt_ file should only be used by **mp-units** developers and contributors
|
||||
as an entry point for the project's development. We want to ensure that everyone will build **ALL**
|
||||
the code correctly before pushing a commit. Having such options would allow unintended issues to
|
||||
leak to PRs and CI.
|
||||
|
||||
This is why our projects have two entry points:
|
||||
|
||||
- _./CMakeLists.txt_ is to be used by projects developers to build **ALL** the project code with really
|
||||
restrictive compilation flags,
|
||||
- _./src/CMakeLists.txt_ contains only a pure library definition and should be used by the customers
|
||||
that prefer to use CMake's `add_subdirectory()` to handle the dependencies.
|
||||
|
||||
To learn more about the rationale, please check our [FAQ](../faq/#why-dont-you-have-cmake-options-to-disable-building-of-tests-and-examples).
|
||||
|
||||
|
||||
## Obtaining Dependencies
|
||||
|
||||
This library assumes that most of the dependencies will be provided by the
|
||||
[Conan Package Manager](https://conan.io/). If you want to obtain required
|
||||
dependencies by other means, some modifications to the library's CMake files might be needed.
|
||||
The rest of the dependencies responsible for documentation generation are provided by
|
||||
`python3-pip`.
|
||||
|
||||
|
||||
### Conan Quick Intro
|
||||
|
||||
In case you are not familiar with Conan, to install it (or upgrade) just do:
|
||||
|
||||
```shell
|
||||
pip3 install -U conan
|
||||
```
|
||||
|
||||
After that, you might need to add a custom profile file for your development environment
|
||||
in _~/.conan2/profiles_ directory. An example profile can look as follows:
|
||||
|
||||
```ini hl_lines="5" title="~/.conan2/profiles/gcc12"
|
||||
[settings]
|
||||
arch=x86_64
|
||||
build_type=Release
|
||||
compiler=gcc
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.version=12
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
|
||||
Please note that the **mp-units** library requires C++20 to be set in a Conan profile or forced
|
||||
via the Conan command line. If you do the former, you will not need to provide `-s compiler.cppstd=20`
|
||||
every time your run a Conan command line (as provided in the command line instructions below).
|
||||
|
||||
Additionally, it is recommended to set Ninja as a CMake generator for Conan. To do so, you should create
|
||||
a _~/.conan2/global.conf_ file that will set `tools.cmake.cmaketoolchain:generator` to one of Ninja
|
||||
generators. For example:
|
||||
|
||||
```text title="~/.conan2/global.conf"
|
||||
tools.cmake.cmaketoolchain:generator="Ninja Multi-Config"
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
_~/.conan2/global.conf_ file may also set `tools.cmake.cmake_layout:build_folder_vars` which
|
||||
[makes working with several compilers or build configurations easier](https://docs.conan.io/2/reference/tools/cmake/cmake_layout.html#multi-setting-option-cmake-layout).
|
||||
For example, the below line will force Conan to generate separate CMake presets and folders for
|
||||
each compiler:
|
||||
|
||||
```text title="~/.conan2/global.conf"
|
||||
tools.cmake.cmake_layout:build_folder_vars=["settings.compiler", "settings.compiler.version"]
|
||||
```
|
||||
|
||||
In such a case, you will need to use a configuration-specific preset name in the Conan instructions
|
||||
provided below rather then just `conan-default` and `conan-release`
|
||||
(i.e. `conan-gcc-11` and `conan-gcc-11-release`)
|
||||
|
||||
|
||||
## Build Options
|
||||
|
||||
### Conan Configuration Properties
|
||||
|
||||
[`user.build:all`](#user-build-all){ #user-build-all }
|
||||
|
||||
: [:octicons-tag-24: 0.8.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
|
||||
Enables compilation of all the source code including tests and examples. To support
|
||||
this it requires some additional Conan build dependencies described in
|
||||
[Repository Structure and Dependencies](#repository-structure-and-dependencies).
|
||||
It also runs unit tests during Conan build (unless `tools.build:skip_test`
|
||||
configuration property is set to `True`).
|
||||
|
||||
[build all support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
|
||||
|
||||
|
||||
[`user.build:skip_la`](#user-skip-la){ #user-skip-la }
|
||||
|
||||
: [:octicons-tag-24: 0.8.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`)
|
||||
|
||||
If `user.build:all` is enabled, among others, Conan installs the external
|
||||
[wg21-linear_algebra](https://conan.io/center/wg21-linear_algebra)
|
||||
dependency and enables the compilation of linear algebra-based tests and usage examples.
|
||||
Such behavior can be disabled with this option.
|
||||
|
||||
[skip la support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0
|
||||
|
||||
|
||||
### CMake Options
|
||||
|
||||
[`MP_UNITS_AS_SYSTEM_HEADERS`](#MP_UNITS_AS_SYSTEM_HEADERS){ #MP_UNITS_AS_SYSTEM_HEADERS }
|
||||
|
||||
: [:octicons-tag-24: 2.0.0][as system headers support] · :octicons-milestone-24: `ON`/`OFF` (Default: `OFF`)
|
||||
|
||||
Exports library as system headers.
|
||||
|
||||
[as system headers support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
|
||||
|
||||
|
||||
[`MP_UNITS_BUILD_LA`](#MP_UNITS_BUILD_LA){ #MP_UNITS_BUILD_LA }
|
||||
|
||||
: [:octicons-tag-24: 2.0.0][build la support] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
|
||||
|
||||
Enables building code depending on the linear algebra library.
|
||||
|
||||
[build la support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
|
||||
|
||||
|
||||
[`MP_UNITS_IWYU`](#MP_UNITS_IWYU){ #MP_UNITS_IWYU }
|
||||
|
||||
: [:octicons-tag-24: 2.0.0][iwyu support] · :octicons-milestone-24: `ON`/`OFF` (Default: `OFF`)
|
||||
|
||||
Enables `include-what-you-use` when compiling with a clang compiler.
|
||||
Additionally turns on [`MP_UNITS_AS_SYSTEM_HEADERS`](#MP_UNITS_AS_SYSTEM_HEADERS).
|
||||
|
||||
[iwyu support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
|
||||
|
||||
|
||||
[`MP_UNITS_USE_LIBFMT`](#MP_UNITS_USE_LIBFMT){ #MP_UNITS_USE_LIBFMT }
|
||||
|
||||
: [:octicons-tag-24: 2.0.0][use libfmt support] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
|
||||
|
||||
Enables usage of [{fmt}](https://github.com/fmtlib/fmt) library instead of the C++20 Standard
|
||||
Library feature.
|
||||
|
||||
[use libfmt support]: https://github.com/mpusz/mp-units/releases/tag/v2.0.0
|
||||
|
||||
|
||||
## CMake with Presets Support
|
||||
|
||||
It is recommended to use at least CMake 3.23 to build this project as this version introduced support
|
||||
for CMake Presets schema version 4 used now by Conan to generate presets files. All build instructions
|
||||
below assume that you have such support. If not, your CMake invocations have to be replaced with something
|
||||
like:
|
||||
|
||||
```shell
|
||||
mkdir build && cd build
|
||||
cmake .. -G "Ninja Multi-Config" -DCMAKE_TOOLCHAIN_FILE=<path_to_generators_dir>/conan_toolchain.cmake
|
||||
cmake --build . --config Release
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
In case you can't use CMake 3.23 but you have access to CMake 3.20 or later, you can append
|
||||
`-c tools.cmake.cmaketoolchain.presets:max_schema_version=2` to the `conan install` command
|
||||
which will force Conan to use an older version of the CMake Presets schema.
|
||||
|
||||
|
||||
## Installation and Reuse
|
||||
|
||||
There are many different ways of installing/reusing **mp-units** in your project. Below we mention
|
||||
only a few of many options possible.
|
||||
|
||||
!!! info
|
||||
|
||||
The easiest and most recommended way to obtain **mp-units** is with the Conan package manager.
|
||||
See [Conan + CMake (release)](#conan-cmake-release) for a detailed instruction.
|
||||
|
||||
|
||||
### Copy
|
||||
|
||||
As **mp-units** is a C++ header-only library you can simply copy all needed _src/*/include_ subdirectories
|
||||
to your source tree.
|
||||
|
||||
!!! note
|
||||
|
||||
In such a case, you are on your own to ensure all the dependencies are installed, and their header
|
||||
files can be located during the build. Please also note that some compiler-specific flags are needed
|
||||
to make the code compile without issues.
|
||||
|
||||
|
||||
### Copy + CMake
|
||||
|
||||
If you copy the whole **mp-units** repository to your project's file tree, you can reuse CMake targets
|
||||
defined by the library. To do so, you should use _CMakeLists.txt_ file from the _./src_ directory:
|
||||
|
||||
```cmake
|
||||
add_subdirectory(<path_to_units_folder>/src)
|
||||
# ...
|
||||
target_link_libraries(<your_target> <PUBLIC|PRIVATE|INTERFACE> mp-units::mp-units)
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
You are still on your own to make sure all the dependencies are installed and their header and CMake
|
||||
configuration files can be located during the build.
|
||||
|
||||
|
||||
### Conan + CMake (release)
|
||||
|
||||
!!! tip
|
||||
|
||||
If you are new to the Conan package manager, it is highly recommended to read
|
||||
[Obtaining Dependencies](#obtaining-dependencies) and refer to
|
||||
[Consuming packages](https://docs.conan.io/2/tutorial/consuming_packages.html)
|
||||
chapter of the official Conan documentation for more information.
|
||||
|
||||
**mp-units** releases are hosted on [Conan-Center](https://conan.io/center/mp-units).
|
||||
To obtain an official library release, the following steps may be performed:
|
||||
|
||||
1. Create Conan configuration file (either _conanfile.txt_ or _conanfile.py_) in your
|
||||
project's top-level directory and add **mp-units** as a dependency of your project.
|
||||
For example, the simplest file may look as follows:
|
||||
|
||||
```ini title="conanfile.txt"
|
||||
[requires]
|
||||
mp-units/0.8.0
|
||||
|
||||
[layout]
|
||||
cmake_layout
|
||||
|
||||
[generators]
|
||||
CMakeToolchain
|
||||
CMakeDeps
|
||||
```
|
||||
|
||||
2. Import **mp-units** and its dependencies definitions to your project's build procedure
|
||||
with `find_package`:
|
||||
|
||||
```cmake
|
||||
find_package(mp-units CONFIG REQUIRED)
|
||||
```
|
||||
|
||||
3. Link your CMake targets with **mp-units**:
|
||||
|
||||
```cmake
|
||||
target_link_libraries(<your_target> <PUBLIC|PRIVATE|INTERFACE> mp-units::mp-units)
|
||||
```
|
||||
|
||||
4. Download, build, and install Conan dependencies before running the CMake configuration step:
|
||||
|
||||
```shell
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||
cmake --preset conan-default
|
||||
cmake --build --preset conan-release
|
||||
```
|
||||
|
||||
### Conan + CMake (Live At Head)
|
||||
|
||||
This chapter describes the procedure to Live At Head, which means using the latest version
|
||||
of **mp-units** all the time.
|
||||
|
||||
!!! note
|
||||
|
||||
Please note that even though the Conan packages that you will be using are generated **ONLY**
|
||||
for builds that are considered stable (passed our CI tests) some minor regressions may happen
|
||||
(our CI and C++20 build environment is not perfect yet). Also, please expect that the library
|
||||
interface might, and probably will, change occasionally. Even though we do our best, such
|
||||
changes might not be reflected in the project's documentation right away.
|
||||
|
||||
The procedure is similar to the one described in [Conan + CMake (release)](#conan-cmake-release)
|
||||
with the following differences:
|
||||
|
||||
1. Before starting the previous procedure, add **mp-units** remote to your Conan configuration:
|
||||
|
||||
```shell
|
||||
conan remote add conan-mpusz https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||
```
|
||||
|
||||
2. In your Conan configuration file, provide the package identifier of the `mpusz/testing` stream:
|
||||
|
||||
```ini title="conanfile.txt" hl_lines="2"
|
||||
[requires]
|
||||
mp-units/2.0.0@mpusz/testing
|
||||
|
||||
[layout]
|
||||
cmake_layout
|
||||
|
||||
[generators]
|
||||
CMakeToolchain
|
||||
CMakeDeps
|
||||
```
|
||||
|
||||
!!! tip
|
||||
|
||||
The identifiers of the latest packages can always be found in
|
||||
[the project's README file](https://github.com/mpusz/mp-units/blob/master/README.md) or on
|
||||
[the project's Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units).
|
||||
|
||||
3. Force Conan to check for updated recipes with `-u`:
|
||||
|
||||
```shell
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing -u
|
||||
```
|
||||
|
||||
|
||||
### Install
|
||||
|
||||
In case you don't want to use Conan in your project and just want to install the **mp-units**
|
||||
library on your file system and use `find_package(mp-units)` from another repository
|
||||
to find it, it is enough to perform the following steps:
|
||||
|
||||
```shell
|
||||
conan install . -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||
mv CMakeUserPresets.json src
|
||||
cd src
|
||||
cmake --preset conan-default -DCMAKE_INSTALL_PREFIX=<your_installation_path>
|
||||
cmake --build --preset conan-release --target install
|
||||
```
|
||||
|
||||
|
||||
## Contributing (or just building all the tests and examples)
|
||||
|
||||
In case you would like to build all the **mp-units** source code (with unit tests and examples),
|
||||
you should:
|
||||
|
||||
1. Use the _CMakeLists.txt_ from the top-level directory.
|
||||
2. Run Conan with [`user.build:all`](#user-build-all) = `True`.
|
||||
|
||||
```shell
|
||||
git clone https://github.com/mpusz/mp-units.git && cd units
|
||||
conan build . -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
|
||||
```
|
||||
|
||||
The above will download and install all of the dependencies needed for the development of the library,
|
||||
build all of the source code, and run unit tests.
|
||||
|
||||
If you prefer to build the project via CMake rather than Conan, then you should replace
|
||||
the `conan build` with `conan install` command and then follow with a regular CMake build:
|
||||
|
||||
```shell
|
||||
cmake --preset conan-default
|
||||
cmake --build --preset conan-release
|
||||
cmake --build --preset conan-release --target test
|
||||
```
|
||||
|
||||
|
||||
## Building documentation
|
||||
|
||||
Starting from **mp-units 2.0** we are using [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
|
||||
to build our documentation. The easiest way to install all the required dependencies
|
||||
is with `pip`:
|
||||
|
||||
```shell
|
||||
pip install -U mkdocs-material
|
||||
```
|
||||
|
||||
After that, you can either:
|
||||
|
||||
- easily [start a live server to preview the documentation as you write](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write)
|
||||
|
||||
```shell
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
- [build the documentation](https://squidfunk.github.io/mkdocs-material/creating-your-site/#building-your-site)
|
||||
|
||||
```shell
|
||||
mkdocs build
|
||||
```
|
||||
|
||||
|
||||
## Packaging
|
||||
|
||||
To test CMake installation and Conan packaging or create a Conan package run:
|
||||
|
||||
```shell
|
||||
conan create . <username>/<channel> -pr <your_conan_profile> -s compiler.cppstd=20 -c user.build:all=True -b missing
|
||||
```
|
||||
|
||||
The above will create a Conan package and run tests provided in _./test_package_ directory.
|
||||
|
||||
|
||||
## Uploading **mp-units** Package to the Conan Server
|
||||
|
||||
```shell
|
||||
conan upload -r <remote-name> --all mp-units/2.0.0@<user>/<channel>
|
||||
```
|
50
docs/getting_started/introduction.md
Normal file
50
docs/getting_started/introduction.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Introduction
|
||||
|
||||
**mp-units** is a Modern C++ library that provides compile-time dimensional analysis and unit/quantity
|
||||
manipulation. The initial versions of the library were inspired by the
|
||||
[`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration)
|
||||
but with each release, the interfaces diverged from the original to provide a better user
|
||||
experience.
|
||||
|
||||
|
||||
## Open Source
|
||||
|
||||
**mp-units** is Free and Open Source, with a permissive
|
||||
[MIT license](https://github.com/mpusz/mp-units/blob/master/LICENSE.md). Check out the source
|
||||
code and issue tracking (for questions and support, reporting bugs, suggesting feature requests
|
||||
and improvements) at <https://github.com/mpusz/mp-units>.
|
||||
|
||||
|
||||
## With the User's Experience in Mind
|
||||
|
||||
Most of the critical design decisions in the library are dictated by the requirement of
|
||||
providing the best user experience possible. Other C++ physical units libraries are
|
||||
"famous" for their enormous and hard-to-understand error messages (one line of the error log often
|
||||
do not fit on one slide). The ultimate goal of **mp-units** is to improve this and make compile-time
|
||||
errors and debugging as easy and user-friendly as possible.
|
||||
|
||||
To achieve this goal, several techniques are applied:
|
||||
|
||||
- usage of C++20 concepts,
|
||||
- using strong types for framework entities (instead of type aliases),
|
||||
- usage of expression templates to improve the readability of generated types,
|
||||
- limiting the number of template arguments to the bare minimum.
|
||||
|
||||
!!! note
|
||||
|
||||
In many generic C++ libraries compile-time errors do not happen often. It is hard to
|
||||
break `std::string` or `std::vector` in a way it won't compile with a huge error
|
||||
log. Physical Units libraries are different. **Generation of compile-time errors
|
||||
is the main reason to use such a library.**
|
||||
|
||||
|
||||
## Key Features
|
||||
|
||||
| Feature | Description |
|
||||
|------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Safety** | - The affine space strong types (`quantity` and `quantity_point`)<br>- Compile-time checked conversions of quantities and units<br>- Unique support for many quantities of the same kind<br>- Type-safe equations on scalar, vector, and tensor quantities and their units<br>- Value-preserving conversions |
|
||||
| **Performance** | - All the compile-time logic implemented as immediate (`consteval`) functions<br>- As fast or even faster than working with fundamental types<br>- No space size overhead needed to implement high-level abstractions |
|
||||
| **Great User Experience** | - Optimized for readable compilation errors and great debugging experience<br>- Efficient and composable way to specify a unit of choice<br>- Value-based dimension, unit, and quantity equations |
|
||||
| **Feature Rich** | - Systems of Quantities<br>- Systems of Units<br>- Scalar, vector, and tensor quantities<br>- The affine space<br>- [Natural units systems](https://en.wikipedia.org/wiki/Natural_units) support<br>- Strong angular system<br>- Supports any unit's magnitude (huge, small, floating-point)<br>- Faster-than-lightspeed constants<br>- Highly adjustable text-output formatting |
|
||||
| **Easy to Extend** | - Each entity can be defined with a single line of code<br>- User can easily extend the systems with custom dimensions, quantities, and units |
|
||||
| **Low Standardization Cost** | - Small number of predefined entities needed thanks to composability<br>- No external dependencies (assuming full C++20 support)<br>- No macros in the user interface (besides portability and standard-compliance issues)<br>- Possibility to be standardized as a [freestanding](https://en.cppreference.com/w/cpp/freestanding) part of the C++ Standard Library |
|
76
docs/getting_started/quick_start.md
Normal file
76
docs/getting_started/quick_start.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Quick Start
|
||||
|
||||
A **quantity** is a concrete amount of a unit for a quantity type of a specified dimension with a
|
||||
specific representation, and is represented in the library with a `quantity` class template.
|
||||
|
||||
|
||||
## Creating a quantity
|
||||
|
||||
The quantity is created by multiplying a number with a predefined unit:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
auto q = 42 * si::metre;
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
The above spelling of `metre` is not a typo. For motivation, please check our
|
||||
[FAQ](../faq/#why-do-we-spell-metre-instead-of-meter).
|
||||
|
||||
The above creates an instance of `quantity<si::metre(), int>`. The same can be obtained using
|
||||
an optional unit symbol:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
auto q = 42 * m;
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Unit symbols introduce a lot of short identifiers into the current namespace, and that is
|
||||
why they are opt-in. A user has to explicitly "import" them from a dedicated `unit_symbols`
|
||||
namespace.
|
||||
|
||||
|
||||
## User-provided unit wrappers
|
||||
|
||||
Sometimes it might be awkward to type some derived units:
|
||||
|
||||
```cpp
|
||||
auto speed = 60 * (km / h);
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Please note that `60 * km / h` will not compile. To read more about the rationale for such
|
||||
a design please check our [FAQ](../faq/#why-dont-we-use-udls-to-create-a-quantity).
|
||||
|
||||
In case such a unit is used a lot in the project, a user can easily provide a nicely named
|
||||
wrapper for it with:
|
||||
|
||||
```cpp
|
||||
constexpr auto kmph = km / h;
|
||||
auto speed = 60 * kmph;
|
||||
```
|
||||
|
||||
or even:
|
||||
|
||||
```cpp
|
||||
constexpr auto kilometre = si::kilo<si::metre>;
|
||||
constexpr auto kilometre_per_hour = kilometre / si::hour;
|
||||
constexpr auto kmph = kilometre_per_hour;
|
||||
auto speed = 60 * kmph;
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
In case you wonder why this library does not use UDLs to create quantities, please check
|
||||
our [FAQ](../faq/#why-dont-we-use-udls-to-create-quantities).
|
@ -1,222 +0,0 @@
|
||||
.. default-role:: term
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
ISO 80000 [1]_ definitions
|
||||
--------------------------
|
||||
|
||||
.. glossary::
|
||||
|
||||
quantity
|
||||
- Property of a phenomenon, body, or substance, where the property has a magnitude that can
|
||||
be expressed by means of a number and a reference.
|
||||
- A reference can be a measurement unit, a measurement procedure, a reference material, or
|
||||
a combination of such.
|
||||
- A quantity as defined here is a scalar. However, a vector or a tensor, the components of
|
||||
which are quantities, is also considered to be a quantity.
|
||||
- The concept ’quantity’ may be generically divided into, e.g. ‘physical quantity’,
|
||||
‘chemical quantity’, and ‘biological quantity’, or ‘base quantity’ and ‘derived quantity’.
|
||||
- Examples of quantities are: mass, length, density, magnetic field strength, etc.
|
||||
|
||||
kind of quantity
|
||||
kind
|
||||
- Aspect common to mutually comparable `quantities <quantity>`.
|
||||
- The division of the concept ‘quantity’ into several kinds is to some extent arbitrary
|
||||
|
||||
- i.e. the quantities diameter, circumference, and wavelength are generally considered
|
||||
to be quantities of the same kind, namely, of the kind of quantity called length.
|
||||
|
||||
- Quantities of the same kind within a given `system of quantities` have the same quantity
|
||||
`dimension`. However, `quantities <quantity>` of the same `dimension` are not necessarily
|
||||
of the same kind.
|
||||
|
||||
- For example, the absorbed dose and the dose equivalent have the same `dimension`.
|
||||
However, the former measures the absolute amount of radiation one receives whereas
|
||||
the latter is a weighted measurement taking into account the kind of radiation
|
||||
on was exposed to.
|
||||
|
||||
system of quantities
|
||||
system
|
||||
- Set of `quantities <quantity>` together with a set of non-contradictory equations
|
||||
relating those `quantities <quantity>`.
|
||||
- Examples of systems of quantities are: the International System of Quantities,
|
||||
the Imperial System, etc.
|
||||
|
||||
base quantity
|
||||
- `Quantity <quantity>` in a conventionally chosen subset of a given `system of quantities`,
|
||||
where no `quantity` in the subset can be expressed in terms of the other
|
||||
`quantities <quantity>` within that subset.
|
||||
- Base quantities are referred to as being mutually independent since a base quantity
|
||||
cannot be expressed as a product of powers of the other base quantities.
|
||||
|
||||
derived quantity
|
||||
- `Quantity <quantity>`, in a `system of quantities`, defined in terms of the base
|
||||
quantities of that system.
|
||||
|
||||
International System of Quantities
|
||||
ISQ
|
||||
- `System of quantities <system of quantities>` based on the seven
|
||||
`base quantities <base quantity>`: length, mass, time, electric current, thermodynamic
|
||||
temperature, amount of substance, and luminous intensity.
|
||||
- The International System of Units (SI) is based on the ISQ.
|
||||
|
||||
dimension of a quantity
|
||||
quantity dimension
|
||||
dimension
|
||||
- Expression of the dependence of a `quantity` on the `base quantities <base quantity>`
|
||||
of a `system of quantities` as a product of powers of factors corresponding to the
|
||||
`base quantities <base quantity>`, omitting any numerical factors.
|
||||
- A power of a factor is the factor raised to an exponent. Each factor is the dimension
|
||||
of a `base quantity`.
|
||||
- In deriving the dimension of a quantity, no account is taken of its scalar, vector, or
|
||||
tensor character.
|
||||
- In a given `system of quantities`:
|
||||
|
||||
- `quantities <quantity>` of the same `kind` have the same quantity dimension,
|
||||
- `quantities <quantity>` of different quantity dimensions are always of different `kinds <kind>`,
|
||||
- `quantities <quantity>` having the same quantity dimension are not necessarily of the same `kind`.
|
||||
|
||||
quantity of dimension one
|
||||
dimensionless quantity
|
||||
- `quantity` for which all the exponents of the factors corresponding to the
|
||||
`base quantities <base quantity>` in its `quantity dimension` are zero.
|
||||
- The term “dimensionless quantity” is commonly used and is kept here for historical
|
||||
reasons. It stems from the fact that all exponents are zero in the symbolic
|
||||
representation of the `dimension` for such `quantities <quantity>`. The term “quantity
|
||||
of dimension one” reflects the convention in which the symbolic representation of the
|
||||
`dimension` for such `quantities <quantity>` is the symbol ``1``. This `dimension` is
|
||||
not a number, but the neutral element for multiplication of `dimensions <dimension>`.
|
||||
- The `measurement units <measurement unit>` and values of quantities of dimension one
|
||||
are numbers, but such `quantities <quantity>` convey more information than a number.
|
||||
- Some quantities of dimension one are defined as the ratios of two
|
||||
`quantities of the same kind <kind>`. The `coherent derived unit` is the number one,
|
||||
symbol ``1``.
|
||||
- Numbers of entities are quantities of dimension one.
|
||||
|
||||
unit of measurement
|
||||
measurement unit
|
||||
unit
|
||||
- Real scalar `quantity`, defined and adopted by convention, with which any other
|
||||
`quantity of the same kind <kind>` can be compared to express the ratio of the
|
||||
second `quantity` to the first one as a number.
|
||||
- Measurement units are designated by conventionally assigned names and symbols.
|
||||
- Measurement units of `quantities <quantity>` of the same `quantity dimension` may
|
||||
be designated by the same name and symbol even when the `quantities <quantity>` are
|
||||
not of the same `kind`.
|
||||
|
||||
For example, joule per kelvin and J/K are respectively the name and symbol of both a
|
||||
measurement unit of heat capacity and a measurement unit of entropy, which are generally
|
||||
not considered to be `quantities of the same kind <kind>`. However, in some cases special
|
||||
measurement unit names are restricted to be used with `quantities <quantity>` of specific
|
||||
`kind` only. For example, the measurement unit ‘second to the power minus one’ (``1/s``) is
|
||||
called hertz (``Hz``) when used for frequencies and becquerel (``Bq``) when used for
|
||||
activities of radionuclides. As another example, the joule (``J``) is used as a unit of
|
||||
energy, but never as a unit of moment of force, i.e. the newton metre (``N · m``).
|
||||
- Measurement units of `quantities of dimension one <quantity of dimension one>` are
|
||||
numbers. In some cases, these measurement units are given special names, e.g. radian,
|
||||
steradian, and decibel, or are expressed by quotients such as millimole per mole equal
|
||||
to :math:`10^{−3}` and microgram per kilogram equal to :math:`10^{−9}`.
|
||||
|
||||
base unit
|
||||
- Measurement unit that is adopted by convention for a `base quantity`.
|
||||
- In each `coherent system of units`, there is only one base unit for each `base quantity`.
|
||||
- A base unit may also serve for a `derived quantity` of the same `quantity dimension`.
|
||||
- For example, the `ISQ` has the base units of: metre, kilogram, second, Ampere, Kelvin, mole,
|
||||
and candela.
|
||||
|
||||
derived unit
|
||||
- Measurement unit for a `derived quantity`.
|
||||
- For example, in the `ISQ` Newton, Pascal, and katal are derived units.
|
||||
|
||||
coherent derived unit
|
||||
- `Derived unit <derived unit>` that, for a given `system of quantities` and for a chosen
|
||||
set of `base units <base unit>`, is a product of powers of `base units <base unit>` with
|
||||
no other proportionality factor than one.
|
||||
- A power of a `base unit` is the `base unit` raised to an exponent.
|
||||
- Coherence can be determined only with respect to a particular `system of quantities`
|
||||
and a given set of `base units <base unit>`. That is, if the metre and the second are
|
||||
base units, the metre per second is the coherent derived unit of speed.
|
||||
|
||||
system of units
|
||||
- Set of `base units <base unit>` and `derived units <derived unit>`, together with
|
||||
their multiples and submultiples, defined in accordance with given rules, for a given
|
||||
`system of quantities`.
|
||||
|
||||
coherent system of units
|
||||
|
||||
- `System of units <system of units>`, based on a given `system of quantities`, in which
|
||||
the measurement unit for each `derived quantity` is a `coherent derived unit`.
|
||||
- A `system of units` can be coherent only with respect to a `system of quantities` and
|
||||
the adopted `base units <base unit>`.
|
||||
|
||||
off-system measurement unit
|
||||
off-system unit
|
||||
- `Measurement unit <measurement unit>` that does not belong to a given `system of units`.
|
||||
For example, the electronvolt (:math:`≈ 1,602 18 × 10^{–19} J`) is an off-system measurement
|
||||
unit of energy with respect to the `SI` or day, hour, minute are off-system measurement
|
||||
units of time with respect to the `SI`.
|
||||
|
||||
International System of Units
|
||||
SI
|
||||
- `System of units <system of units>`, based on the `International System of Quantities`,
|
||||
their names and symbols, including a series of prefixes and their names and symbols,
|
||||
together with rules for their use, adopted by the General Conference on Weights and
|
||||
Measures (CGPM)
|
||||
|
||||
quantity value
|
||||
value of a quantity
|
||||
value
|
||||
- Number and reference together expressing magnitude of a `quantity`.
|
||||
- The number can be complex.
|
||||
- A quantity value can be presented in more than one way.
|
||||
- In the case of vector or tensor quantities, each component has a quantity value.
|
||||
|
||||
- For example, force acting on a given particle, e.g. in Cartesian components
|
||||
:math:`(F_x; F_y; F_z) = (−31,5; 43,2; 17,0) N`, where
|
||||
:math:`(−31,5; 43,2; 17,0)` is a numerical-value vector and :math:`N` (newton)
|
||||
is the unit, or :math:`(F_x; F_y; F_z) = (−31,5 N; 43,2 N; 17,0 N)`
|
||||
where each component is a quantity.
|
||||
|
||||
|
||||
Other definitions
|
||||
-----------------
|
||||
|
||||
.. glossary::
|
||||
:sorted:
|
||||
|
||||
base dimension
|
||||
- A `dimension` of a `base quantity`.
|
||||
|
||||
derived dimension
|
||||
- A `dimension` of a `derived quantity`.
|
||||
- Often implemented as a list of exponents of `base dimensions <base dimension>`.
|
||||
|
||||
normalized derived dimension
|
||||
A `derived dimension` in which:
|
||||
|
||||
- `base dimensions <base dimension>` are not repeated in a list (each base dimension is provided at most once),
|
||||
- `base dimensions <base dimension>` are consistently ordered,
|
||||
- `base dimensions <base dimension>` having zero exponent are elided.
|
||||
|
||||
derived dimension recipe
|
||||
recipe
|
||||
- The ordered list of exponents used to define a derived dimension
|
||||
- The list may contain both base and derived dimensions (in the latter case
|
||||
the dimension is being extracted to base dimensions by the framework)
|
||||
- The order and types of dimensions used in the recipe determine how an unnamed
|
||||
dimension's unit symbol is being printed in the text output
|
||||
|
||||
scalable number
|
||||
- Not a `quantity`
|
||||
- Can be passed as a representation type to the :class:`units::quantity` type or be used as a factor
|
||||
while multiplying or dividing a `quantity`.
|
||||
|
||||
.. rubric:: Footnotes:
|
||||
|
||||
.. [1] [ISO80000]_ gives general information and definitions concerning quantities, systems of quantities,
|
||||
units, quantity and unit symbols, and coherent unit systems, especially the International System
|
||||
of Quantities, ISQ, and the International System of Units, SI. The principles laid down in
|
||||
ISO 80000-1:2009 are intended for general use within the various fields of science and technology
|
||||
and as an introduction to other parts of the Quantities and units series. Ordinal quantities and
|
||||
nominal properties are outside the scope of ISO 80000-1:2009.
|
32
docs/index.md
Normal file
32
docs/index.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Welcome to **mp-units**!
|
||||
|
||||
**mp-units** is a compile-time enabled feature-rich Modern C++ header-only library that provides
|
||||
compile-time dimensional analysis and unit/quantity manipulation. Its key strengths include safety,
|
||||
performance, and developer experience.
|
||||
|
||||
The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units) with a permissive
|
||||
[MIT license](https://github.com/mpusz/units/blob/master/LICENSE.md).
|
||||
|
||||
!!! info "Help needed!"
|
||||
|
||||
The **mp-units** library might be the subject of ISO standardization for C++29. More on this can
|
||||
be found in the ISO C++ proposal [P1935](https://wg21.link/p1935). We are actively looking for
|
||||
parties interested in field-trialing the library.
|
||||
|
||||
??? info "Supported compilers"
|
||||
|
||||
This library tries to provide the best user experience possible with the C++ language.
|
||||
To achieve that, it extensively uses C++20 features and the
|
||||
[explicit object parameter](https://en.cppreference.com/w/cpp/language/member_functions#Explicit_object_parameter)
|
||||
from C++23.
|
||||
|
||||
Even though the library benefits from C++23 (if available), C++20 is enough to compile and
|
||||
use all of the library's functionality. C++23 features are hidden behind a preprocessor macro
|
||||
providing a backward-compatible way to use it.
|
||||
|
||||
Sadly, as of today, only a few compilers provide full C++20 support. The library compiles fine
|
||||
on the following compilers (or newer):
|
||||
|
||||
- gcc-12.2
|
||||
|
||||
In the upcoming weeks, we will be actively working to extend the support to other compilers as well.
|
@ -1,62 +0,0 @@
|
||||
Welcome to mp-units!
|
||||
====================
|
||||
|
||||
**mp-units** is a compile-time enabled Modern C++ library that provides compile-time dimensional
|
||||
analysis and unit/quantity manipulation. Source code is hosted on `GitHub <https://github.com/mpusz/units>`_
|
||||
with a permissive `MIT license <https://github.com/mpusz/units/blob/master/LICENSE.md>`_.
|
||||
|
||||
|
||||
.. important::
|
||||
|
||||
The **mp-units** library is the subject of ISO standardization for C++23/26. More on this can
|
||||
be found in ISO C++ paper `P1935 <https://wg21.link/p1935>`_ and
|
||||
`NDC TechTown 2021 talk <https://www.youtube.com/watch?v=nudq58d0TFc>`_. We are actively looking for
|
||||
parties interested in field trialing the library.
|
||||
|
||||
.. note::
|
||||
|
||||
This library targets C++23/26 and extensively uses C++20 features. This is why it requires the latest C++
|
||||
compilers. The following compilers (or newer) are supported:
|
||||
|
||||
- gcc-10
|
||||
- clang-12
|
||||
- Visual Studio 16.9
|
||||
- Apple clang 13
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Getting Started:
|
||||
|
||||
introduction
|
||||
quick_start
|
||||
framework
|
||||
defining_systems
|
||||
use_cases
|
||||
design
|
||||
examples
|
||||
usage
|
||||
faq
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Reference:
|
||||
|
||||
reference/core
|
||||
reference/systems
|
||||
reference/math
|
||||
reference/random
|
||||
|
||||
.. note::
|
||||
|
||||
Source code documentation tools used to generate the above chapter still do not understand
|
||||
C++20 to well which results in some issues in the generated output. We do our best to address
|
||||
this ASAP.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Appendix:
|
||||
|
||||
glossary
|
||||
genindex
|
||||
CHANGELOG
|
||||
references
|
@ -1,71 +0,0 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
**mp-units** is a compile-time enabled Modern C++ library that provides compile-time
|
||||
dimensional analysis and unit/quantity manipulation. The basic idea and design
|
||||
heavily bases on `std::chrono::duration <https://en.cppreference.com/w/cpp/chrono/duration>`_
|
||||
and extends it to work properly with many dimensions.
|
||||
|
||||
Thanks to compile-time operations no runtime execution cost is introduced,
|
||||
facilitating the use of this library to provide dimension checking in
|
||||
performance-critical code. Support for quantities and units for arbitrary unit
|
||||
system models and arbitrary value types is provided, as is a fine-grained
|
||||
general facility for unit conversions.
|
||||
|
||||
The library architecture has been designed with flexibility and extensibility
|
||||
in mind. The demonstrations of the ease of adding new dimensions, their units,
|
||||
and unit conversions are provided in the :ref:`examples:Examples`.
|
||||
|
||||
Open Source
|
||||
-----------
|
||||
|
||||
**mp-units** is Free and Open Source, with a permissive
|
||||
`MIT license <https://github.com/mpusz/units/blob/master/LICENSE.md>`_. Check
|
||||
out the source code and issue tracking (for questions and support, reporting
|
||||
bugs and suggesting feature requests and improvements) at https://github.com/mpusz/units.
|
||||
|
||||
|
||||
Approach
|
||||
--------
|
||||
|
||||
1. Safety and performance
|
||||
|
||||
- strong types
|
||||
- compile-time safety
|
||||
- ``constexpr`` all the things
|
||||
- as fast or even faster than when working with fundamental types
|
||||
|
||||
2. The best possible user experience
|
||||
|
||||
- compiler errors
|
||||
- debugging
|
||||
|
||||
3. No macros in the user interface
|
||||
4. Easy extensibility
|
||||
5. No external dependencies
|
||||
6. Possibility to be standardized as a freestanding part of the C++ Standard
|
||||
Library
|
||||
|
||||
|
||||
With the User's Experience in Mind
|
||||
----------------------------------
|
||||
|
||||
Most of the important design decisions in the library are dictated by the requirement of
|
||||
providing the best user experience as possible. Other C++ physical units libraries are
|
||||
"famous" for their huge error messages (one line of the error log often do not fit on one
|
||||
slide). The ultimate goal of **mp-units** is to improve this and make compile-time errors
|
||||
and debugging as easy and user-friendly as possible.
|
||||
|
||||
To achieve this goal several techniques are applied:
|
||||
|
||||
- usage of C++20 concepts,
|
||||
- using strong types for framework entities (instead of type aliases),
|
||||
- limiting the number of template arguments to the bare minimum,
|
||||
- :ref:`design/downcasting:The Downcasting Facility`.
|
||||
|
||||
.. important::
|
||||
|
||||
In many generic C++ libraries compile-time errors do not happen often. It is hard to
|
||||
break ``std::string`` or ``std::vector`` in a way it won't compile with a huge error
|
||||
log. Physical Units libraries are different. **Generation of compile-time errors
|
||||
is the main reason to create such a library.**
|
7
docs/library_reference/core_library.md
Normal file
7
docs/library_reference/core_library.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Core Library
|
||||
|
||||
## Concepts
|
||||
|
||||
## Expression templates
|
||||
|
||||
## Dimensions
|
@ -1,88 +0,0 @@
|
||||
Quick Start
|
||||
===========
|
||||
|
||||
Here is a small example of possible operations::
|
||||
|
||||
#include <units/isq/si/area.h>
|
||||
#include <units/isq/si/frequency.h>
|
||||
#include <units/isq/si/length.h>
|
||||
#include <units/isq/si/speed.h>
|
||||
#include <units/isq/si/time.h>
|
||||
|
||||
using namespace units::isq::si::references;
|
||||
|
||||
// simple numeric operations
|
||||
static_assert(10 * km / 2 == 5 * km);
|
||||
|
||||
// unit conversions
|
||||
static_assert(1 * h == 3600 * s);
|
||||
static_assert(1 * km + 1 * m == 1001 * m);
|
||||
|
||||
// dimension conversions
|
||||
inline constexpr auto kmph = km / h;
|
||||
static_assert(1 * km / (1 * s) == 1000 * (m / s));
|
||||
static_assert(2 * kmph * (2 * h) == 4 * km);
|
||||
static_assert(2 * km / (2 * kmph) == 1 * h);
|
||||
|
||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||
|
||||
static_assert(10 * km / (5 * km) == 2);
|
||||
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
|
||||
.. admonition:: Try it on Compiler Explorer
|
||||
|
||||
`Example #1 <https://godbolt.org/z/qbbbnfK3s>`_
|
||||
|
||||
This library requires some C++20 features (concepts, classes as
|
||||
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
|
||||
but still easy to use interface where all unit conversions and dimensional analysis can be
|
||||
performed without sacrificing on accuracy. Please see the below example for a quick preview
|
||||
of basic library features::
|
||||
|
||||
#include <units/format.h>
|
||||
#include <units/isq/si/international/length.h>
|
||||
#include <units/isq/si/international/speed.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 <iostream>
|
||||
|
||||
using namespace units::isq;
|
||||
|
||||
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace units::isq::si::literals;
|
||||
using namespace units::isq::si::references;
|
||||
using namespace units::aliases::isq::si::international;
|
||||
|
||||
constexpr Speed auto v1 = 110 * (km / h);
|
||||
constexpr Speed auto v2 = mi_per_h(70.);
|
||||
constexpr Speed auto v3 = avg_speed(220_q_km, 2_q_h);
|
||||
constexpr Speed auto v4 = avg_speed(si::length<si::international::mile>(140), si::time<si::hour>(2));
|
||||
constexpr Speed auto v5 = quantity_cast<si::speed<si::metre_per_second>>(v3);
|
||||
constexpr Speed auto v6 = quantity_cast<si::metre_per_second>(v4);
|
||||
constexpr Speed auto v7 = quantity_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
|
||||
.. admonition:: Try it on Compiler Explorer
|
||||
|
||||
`Example #2 <https://godbolt.org/z/b4a3Ya6dY>`_
|
||||
|
||||
.. seealso::
|
||||
|
||||
You can find more code examples in the :ref:`examples:Examples` chapter.
|
@ -1,12 +0,0 @@
|
||||
Core Library
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
core/concepts
|
||||
core/types
|
||||
core/functions
|
||||
core/metafunctions
|
||||
core/customization_points
|
||||
core/downcasting
|
@ -1,169 +0,0 @@
|
||||
.. namespace:: units
|
||||
|
||||
Concepts
|
||||
========
|
||||
|
||||
.. note::
|
||||
|
||||
All names defined in this chapter reside in the :any:`units` namespace unless
|
||||
specified otherwise.
|
||||
|
||||
.. concept:: template<typename T> Prefix
|
||||
|
||||
A concept matching a symbol prefix. Satisfied by all instantiations of :struct:`prefix`.
|
||||
|
||||
.. concept:: template<ratio R> UnitRatio
|
||||
|
||||
Satisfied by all ratio values for which :expr:`R.num > 0` and :expr:`R.den > 0`.
|
||||
|
||||
.. concept:: template<typename T> BaseDimension
|
||||
|
||||
A concept matching all base dimensions in the library. Satisfied by all dimension types
|
||||
derived from the instantiation of :class:`base_dimension`.
|
||||
|
||||
.. concept:: template<typename T> Exponent
|
||||
|
||||
A concept matching dimension's exponents. Satisfied by all instantiations of :class:`exponent`.
|
||||
|
||||
.. concept:: template<typename T> DerivedDimension
|
||||
|
||||
A concept matching all derived dimensions in the library. Satisfied by all dimension
|
||||
types derived from the instantiation of ``detail::derived_dimension_base``.
|
||||
|
||||
.. concept:: template<typename T> Dimension
|
||||
|
||||
A concept matching all dimensions in the library. Satisfied by all dimension types for
|
||||
which either :expr:`BaseDimension<T>` or :expr:`DerivedDimension<T>` is ``true``.
|
||||
|
||||
.. concept:: template<typename T> Unit
|
||||
|
||||
A concept matching all unit types in the library. Satisfied by all unit types derived
|
||||
from the instantiation of :class:`scaled_unit`.
|
||||
|
||||
.. concept:: template<typename T> NamedUnit
|
||||
|
||||
A concept matching all unit types that have an atomic text symbol that can be used to aggregate it with
|
||||
other named units to form a final symbol of a derived unit.
|
||||
|
||||
.. concept:: template<typename T> AliasUnit
|
||||
|
||||
A concept matching all alias unit types in the library. Satisfied by all unit types derived
|
||||
from the instantiation of :class:`alias_unit`.
|
||||
|
||||
.. concept:: template<typename U, typename D> UnitOf
|
||||
|
||||
A concept matching only units of a specified dimension. Satisfied by all unit types that
|
||||
satisfy :expr:`Unit<U>`, :expr:`Dimension<D>`, and for which :expr:`U::reference` and
|
||||
``dimension_unit<D>::reference`` denote the same unit type.
|
||||
|
||||
:tparam U: Type to verify against concept constraints.
|
||||
:tparam D: Dimension type to use for verification.
|
||||
|
||||
.. concept:: template<typename T> Quantity
|
||||
|
||||
A concept matching all quantities in the library. Satisfied by all instantiations of :class:`quantity`.
|
||||
|
||||
.. concept:: template<typename T> QuantityLike
|
||||
|
||||
A concept matching all quantity-like types other than specialization of :class:`quantity`. Satisfied by
|
||||
all types for which a correct specialization of :class:`quantity_like_traits` type trait is provided.
|
||||
|
||||
.. concept:: template<typename T> QuantityPointLike
|
||||
|
||||
A concept matching all quantity-point-like types other than specialization of :class:`quantity_point`.
|
||||
Satisfied by all types for which a correct specialization of :class:`quantity_point_like_traits` type trait is provided.
|
||||
|
||||
.. concept:: template<typename T> WrappedQuantity
|
||||
|
||||
A concept matching types that wrap quantity objects. Satisfied by all wrapper types that
|
||||
satisfy :expr:`Quantity<typename T::value_type> || QuantityLike<typename T::value_type>` recursively
|
||||
(i.e. ``std::optional<si::length<si::metre>>``).
|
||||
|
||||
.. concept:: template<typename T> Representation
|
||||
|
||||
A concept matching types that can be used as a `Quantity` representation type. Satisfied
|
||||
by types that match ``(!Quantity<T>) && (!QuantityLike<T>) && (!WrappedQuantity<T>) && std::regular<T>``
|
||||
and satisfy one of the following:
|
||||
|
||||
- if ``common_type_with<T, std::intmax_t>`` is ``true``, then ``std::common_type_t<T, std::intmax_t>``
|
||||
must at least provide binary multiplication and division operators,
|
||||
- otherwise, ``T::value_type`` must be valid, ``common_type_with<T::value_type, std::intmax_t>`` be
|
||||
``true``, and ``std::common_type_t<T::value_type, std::intmax_t>`` must at least provide binary
|
||||
multiplication and division operators with itself and ``T``.
|
||||
|
||||
.. concept:: template<typename T> QuantityPoint
|
||||
|
||||
A concept matching all quantity points in the library. Satisfied by all instantiations of
|
||||
:class:`quantity_point`.
|
||||
|
||||
.. concept:: template<typename T> Kind
|
||||
|
||||
A concept matching all kind types. Satisfied by all kind types derived from an specialization of
|
||||
:class:`kind`.
|
||||
|
||||
.. concept:: template<typename T> PointKind
|
||||
|
||||
A concept matching all point kind types. Satisfied by all point kind types derived from an specialization of
|
||||
:class:`point_kind`.
|
||||
|
||||
.. concept:: template<typename T> QuantityKind
|
||||
|
||||
A concept matching all quantity kinds in the library. Satisfied by all specializations of
|
||||
:class:`quantity_kind`.
|
||||
|
||||
.. concept:: template<typename T> QuantityPointKind
|
||||
|
||||
A concept matching all quantity point kinds in the library. Satisfied by all specializations of
|
||||
:class:`quantity_point_kind`.
|
||||
|
||||
.. concept:: template<typename Dim, template<typename...> typename DimTemplate> DimensionOfT
|
||||
|
||||
A concept matching all dimensions being the instantiations derived from the provided dimension
|
||||
class template.
|
||||
|
||||
.. concept:: template<typename Q, template<typename...> typename DimTemplate> QuantityOfT
|
||||
|
||||
A concept matching all quantities with a dimension being the instantiation derived from
|
||||
the provided dimension class template.
|
||||
|
||||
.. concept:: template<typename Q, typename Dim> QuantityOf
|
||||
|
||||
A concept matching all quantities with a dimension being the instantiation derived from
|
||||
the provided dimension type.
|
||||
|
||||
.. concept:: template<typename Q1, typename Q2> QuantityEquivalentTo
|
||||
|
||||
A concept matching two equivalent quantities. Satisfied by quantities having equivalent dimensions.
|
||||
|
||||
.. concept:: template<typename QP, typename Dim> QuantityPointOf
|
||||
|
||||
A concept matching all quantity points with a dimension being the instantiation derived from
|
||||
the provided dimension type.
|
||||
|
||||
.. concept:: template<typename QP1, typename QP2> QuantityPointEquivalentTo
|
||||
|
||||
A concept matching two equivalent quantity points. Satisfied by quantity points having equivalent
|
||||
dimensions.
|
||||
|
||||
.. concept:: template<typename QK, typename K> QuantityKindOf
|
||||
|
||||
A concept matching only quantity kinds of a specific kind.
|
||||
|
||||
:tparam QK: Quantity kind to verify.
|
||||
:tparam K: Kind type to use for verification.
|
||||
|
||||
.. concept:: template<typename QK1, typename QK2> QuantityKindEquivalentTo
|
||||
|
||||
A concept matching two equivalent quantity kinds. Satisfied by quantity kinds having equivalent kinds.
|
||||
|
||||
.. concept:: template<typename QPK, typename PK> QuantityPointKindOf
|
||||
|
||||
A concept matching only quantity point kinds of a specific point kind.
|
||||
|
||||
:tparam QPK: Quantity point kind to verify.
|
||||
:tparam PK: Point kind type to use for verification.
|
||||
|
||||
.. concept:: template<typename QPK1, typename QPK2> QuantityPointKindEquivalentTo
|
||||
|
||||
A concept matching two equivalent quantity point kinds. Satisfied by quantity point kinds having
|
||||
equivalent kinds.
|
@ -1,13 +0,0 @@
|
||||
Customization Points
|
||||
====================
|
||||
|
||||
.. doxygenvariable:: units::treat_as_floating_point
|
||||
|
||||
.. doxygenstruct:: units::quantity_values
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::quantity_like_traits
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::quantity_point_like_traits
|
||||
:members:
|
@ -1,20 +0,0 @@
|
||||
The Downcasting Facility
|
||||
========================
|
||||
|
||||
.. doxygenenum:: downcast_mode
|
||||
|
||||
.. concept:: template<typename T> Downcastable
|
||||
|
||||
.. doxygenstruct:: units::downcast_base
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::downcast_child
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::downcast_poison
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::downcast_dispatch
|
||||
:members:
|
||||
|
||||
.. doxygentypedef:: units::downcast
|
@ -1,4 +0,0 @@
|
||||
Metafunctions
|
||||
=============
|
||||
|
||||
.. doxygentypedef:: dimension_unit
|
@ -1,16 +0,0 @@
|
||||
Types
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
types/quantity
|
||||
types/quantity_point
|
||||
types/kinds
|
||||
types/quantity_kind
|
||||
types/quantity_point_kind
|
||||
types/dimensions
|
||||
types/units
|
||||
types/prefixes
|
||||
types/reference
|
||||
types/utilities
|
@ -1,11 +0,0 @@
|
||||
Dimensions
|
||||
==========
|
||||
|
||||
.. doxygenstruct:: units::base_dimension
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::exponent
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::derived_dimension
|
||||
:members:
|
@ -1,8 +0,0 @@
|
||||
Kinds
|
||||
=====
|
||||
|
||||
.. doxygenstruct:: units::kind
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::point_kind
|
||||
:members:
|
@ -1,5 +0,0 @@
|
||||
Prefixes
|
||||
========
|
||||
|
||||
.. doxygenstruct:: units::prefix
|
||||
:members:
|
@ -1,6 +0,0 @@
|
||||
Quantity
|
||||
========
|
||||
|
||||
.. doxygenclass:: units::quantity
|
||||
:members:
|
||||
:undoc-members:
|
@ -1,6 +0,0 @@
|
||||
Quantity Kind
|
||||
=============
|
||||
|
||||
.. doxygenclass:: units::quantity_kind
|
||||
:members:
|
||||
:undoc-members:
|
@ -1,6 +0,0 @@
|
||||
Quantity Point
|
||||
==============
|
||||
|
||||
.. doxygenclass:: units::quantity_point
|
||||
:members:
|
||||
:undoc-members:
|
@ -1,6 +0,0 @@
|
||||
Quantity Point Kind
|
||||
===================
|
||||
|
||||
.. doxygenclass:: units::quantity_point_kind
|
||||
:members:
|
||||
:undoc-members:
|
@ -1,6 +0,0 @@
|
||||
Quantity Reference
|
||||
==================
|
||||
|
||||
.. doxygenstruct:: units::reference
|
||||
:members:
|
||||
:undoc-members:
|
@ -1,26 +0,0 @@
|
||||
Units
|
||||
=====
|
||||
|
||||
.. doxygenstruct:: units::scaled_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::named_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::named_scaled_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::prefixed_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::derived_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::derived_scaled_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::alias_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::prefixed_alias_unit
|
||||
:members:
|
@ -1,9 +0,0 @@
|
||||
Utilities
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
utilities/ratio
|
||||
utilities/basic_symbol_text
|
||||
utilities/basic_fixed_string
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user