Merge fixes into branch after updating with upstream changes

This commit is contained in:
Chip Hogg
2022-05-12 16:54:48 +00:00
164 changed files with 2468 additions and 1523 deletions

View File

@@ -4,19 +4,25 @@ parse:
pargs: pargs:
nargs: 1 nargs: 1
flags: flags:
- ALL - ALL
kwargs: kwargs:
BREATHE_PROJECT: 1 BREATHE_PROJECT: 1
CODE_SOURCE_DIR: 1 CODE_SOURCE_DIR: 1
INSTALL_DIR: 1 INSTALL_DIR: 1
CODE_DEPENDS: 1 CODE_DEPENDS: 1
DOCS_DEPENDS: 1 DOCS_DEPENDS: 1
add_units_module:
pargs:
nargs: 1
kwargs:
DEPENDENCIES: +
HEADERS: +
enable_iwyu: enable_iwyu:
pargs: pargs:
flags: flags:
- NO_FORWARD_DECLARATIONS - NO_FORWARD_DECLARATIONS
- QUOTED_INCLUDES_FIRST - QUOTED_INCLUDES_FIRST
- NO_COMMENTS - NO_COMMENTS
kwargs: kwargs:
MAPPING_FILE: 1 MAPPING_FILE: 1
MAX_LINE_LENGTH: 1 MAX_LINE_LENGTH: 1

2
.flake8 Normal file
View File

@@ -0,0 +1,2 @@
[flake8]
max-line-length = 120

View File

@@ -25,10 +25,10 @@ name: Conan CI
on: on:
push: push:
paths-ignore: paths-ignore:
- 'docs/**' - "docs/**"
pull_request: pull_request:
paths-ignore: paths-ignore:
- 'docs/**' - "docs/**"
jobs: jobs:
build: build:
@@ -38,51 +38,108 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
config: config:
- { - {
name: "Windows MSVC 14.2", name: "Windows MSVC 14.2",
os: windows-2019, os: windows-2019,
compiler: { type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" } compiler:
} { type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" },
- { }
name: "Windows MSVC 14.3", - {
os: windows-2022, name: "Windows MSVC 14.3",
compiler: { type: MSVC, version: 193, std: 23, cc: "cl", cxx: "cl" } os: windows-2022,
} compiler:
- { { type: MSVC, version: 193, std: 23, cc: "cl", cxx: "cl" },
name: "Ubuntu GCC-10", }
os: ubuntu-20.04, - {
compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10", std: 20 }, name: "Ubuntu GCC-10",
lib: "libstdc++11" os: ubuntu-20.04,
} compiler:
- { {
name: "Ubuntu GCC-11", type: GCC,
os: ubuntu-20.04, version: 10,
compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11", std: 20 }, cc: "gcc-10",
lib: "libstdc++11" cxx: "g++-10",
} std: 20,
- { },
name: "Ubuntu Clang-12 + libstdc++11", lib: "libstdc++11",
os: ubuntu-20.04, }
compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12", std: 20 }, - {
lib: "libstdc++11" name: "Ubuntu GCC-11",
} os: ubuntu-20.04,
- { compiler:
name: "Ubuntu Clang-12 + libc++", {
os: ubuntu-20.04, type: GCC,
compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12", std: 20 }, version: 11,
lib: "libc++" cc: "gcc-11",
} cxx: "g++-11",
- { std: 20,
name: "Ubuntu Clang-13 + libc++", },
os: ubuntu-20.04, lib: "libstdc++11",
compiler: { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13", std: 20 }, }
lib: "libc++" - {
} name: "Ubuntu Clang-12 + libstdc++11",
- { os: ubuntu-20.04,
name: "MacOS Apple Clang 13", compiler:
os: macos-11, {
compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++", std: 20 } type: CLANG,
} version: 12,
cc: "clang-12",
cxx: "clang++-12",
std: 20,
},
lib: "libstdc++11",
}
- {
name: "Ubuntu Clang-12 + libc++",
os: ubuntu-20.04,
compiler:
{
type: CLANG,
version: 12,
cc: "clang-12",
cxx: "clang++-12",
std: 20,
},
lib: "libc++",
}
- {
name: "Ubuntu Clang-13 + libc++",
os: ubuntu-20.04,
compiler:
{
type: CLANG,
version: 13,
cc: "clang-13",
cxx: "clang++-13",
std: 20,
},
lib: "libc++",
}
- {
name: "Ubuntu Clang-14 + libc++",
os: ubuntu-20.04,
compiler:
{
type: CLANG,
version: 14,
cc: "clang-14",
cxx: "clang++-14",
std: 20,
},
lib: "libc++",
}
- {
name: "MacOS Apple Clang 13",
os: macos-11,
compiler:
{
type: APPLE_CLANG,
version: "13.0",
cc: "clang",
cxx: "clang++",
std: 20,
},
}
# In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows # In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows
# - { # - {
# name: "Ubuntu GCC 10.2.0", # name: "Ubuntu GCC 10.2.0",
@@ -90,8 +147,8 @@ jobs:
# compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, # compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
# docker_image: conanio/gcc10 # docker_image: conanio/gcc10
# } # }
build_type: [ "Release", "Debug" ] build_type: ["Release", "Debug"]
downcast_mode: [ "on", "auto" ] downcast_mode: ["on", "auto"]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: hendrikmuhs/ccache-action@v1 - uses: hendrikmuhs/ccache-action@v1
@@ -141,7 +198,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: '3.8' python-version: "3.8"
- name: Install Conan Package Tools - name: Install Conan Package Tools
run: | run: |
pip install -U conan_package_tools pip install -U conan_package_tools

View File

@@ -25,14 +25,14 @@ name: CMake Test Package CI
on: on:
push: push:
paths-ignore: paths-ignore:
- 'docs/**' - "docs/**"
- 'example/**' - "example/**"
- 'test/**' - "test/**"
pull_request: pull_request:
paths-ignore: paths-ignore:
- 'docs/**' - "docs/**"
- 'example/**' - "example/**"
- 'test/**' - "test/**"
jobs: jobs:
test_package: test_package:
@@ -42,46 +42,62 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
config: config:
- { - {
name: "Windows MSVC 2019", name: "Windows MSVC 2019",
os: windows-latest, os: windows-latest,
compiler: { type: VISUAL, version: 16, cc: "", cxx: "" } compiler: { type: VISUAL, version: 16, cc: "", cxx: "" },
} }
- { - {
name: "Ubuntu GCC 10.3.0", name: "Ubuntu GCC 10.3.0",
os: ubuntu-20.04, os: ubuntu-20.04,
compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
lib: "libstdc++11" lib: "libstdc++11",
} }
- { - {
name: "Ubuntu GCC 11.1.0", name: "Ubuntu GCC 11.1.0",
os: ubuntu-20.04, os: ubuntu-20.04,
compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" }, compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" },
lib: "libstdc++11" lib: "libstdc++11",
} }
- { - {
name: "Ubuntu Clang 12.0.0 + libstdc++11", name: "Ubuntu Clang 12.0.0 + libstdc++11",
os: ubuntu-20.04, os: ubuntu-20.04,
compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, compiler:
lib: "libstdc++11" { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" },
} lib: "libstdc++11",
- { }
name: "Ubuntu Clang 12.0.0 + libc++", - {
os: ubuntu-20.04, name: "Ubuntu Clang 12.0.0 + libc++",
compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, os: ubuntu-20.04,
lib: "libc++" compiler:
} { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" },
- { lib: "libc++",
name: "Ubuntu Clang 13.0.0 + libc++", }
os: ubuntu-20.04, - {
compiler: { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13" }, name: "Ubuntu Clang 13.0.0 + libc++",
lib: "libc++" os: ubuntu-20.04,
} compiler:
- { { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13" },
name: "MacOS Apple Clang 13", lib: "libc++",
os: macos-11, }
compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++" } - {
} name: "Ubuntu Clang 14.0.0 + libc++",
os: ubuntu-20.04,
compiler:
{ type: CLANG, version: 14, cc: "clang-14", cxx: "clang++-14" },
lib: "libc++",
}
- {
name: "MacOS Apple Clang 13",
os: macos-11,
compiler:
{
type: APPLE_CLANG,
version: "13.0",
cc: "clang",
cxx: "clang++",
},
}
# In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows # In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows
# - { # - {
# name: "Ubuntu GCC 10.2.0", # name: "Ubuntu GCC 10.2.0",
@@ -89,7 +105,7 @@ jobs:
# compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, # compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
# docker_image: conanio/gcc10 # docker_image: conanio/gcc10
# } # }
build_type: [ "Release", "Debug" ] build_type: ["Release", "Debug"]
env: env:
CC: ${{ matrix.config.compiler.cc }} CC: ${{ matrix.config.compiler.cc }}
@@ -151,7 +167,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: '3.8' python-version: "3.8"
- name: Install Conan - name: Install Conan
shell: bash shell: bash
run: | run: |
@@ -185,13 +201,13 @@ jobs:
working-directory: build/${{ matrix.build_type }} working-directory: build/${{ matrix.build_type }}
run: | run: |
call conanvcvars.bat call conanvcvars.bat
cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Configure mp-units CMake - name: Configure mp-units CMake
if: matrix.config.compiler.type != 'VISUAL' if: matrix.config.compiler.type != 'VISUAL'
shell: bash shell: bash
working-directory: build/${{ matrix.build_type }} working-directory: build/${{ matrix.build_type }}
run: | run: |
cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Install mp-units - name: Install mp-units
shell: bash shell: bash
working-directory: build/${{ matrix.build_type }} working-directory: build/${{ matrix.build_type }}
@@ -208,14 +224,14 @@ jobs:
working-directory: test_package/build/${{ matrix.build_type }} working-directory: test_package/build/${{ matrix.build_type }}
run: | run: |
call conanvcvars.bat call conanvcvars.bat
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }}
cmake --build . cmake --build .
- name: Build test_package CMake (local build) - name: Build test_package CMake (local build)
if: matrix.config.compiler.type != 'VISUAL' if: matrix.config.compiler.type != 'VISUAL'
shell: bash shell: bash
working-directory: test_package/build/${{ matrix.build_type }} working-directory: test_package/build/${{ matrix.build_type }}
run: | run: |
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }}
cmake --build . cmake --build .
- name: Build test_package CMake (installation) - name: Build test_package CMake (installation)
if: matrix.config.compiler.type == 'VISUAL' if: matrix.config.compiler.type == 'VISUAL'
@@ -223,14 +239,14 @@ jobs:
working-directory: test_package/build/${{ matrix.build_type }} working-directory: test_package/build/${{ matrix.build_type }}
run: | run: |
call conanvcvars.bat call conanvcvars.bat
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
cmake --build . cmake --build .
- name: Build test_package CMake (installation) - name: Build test_package CMake (installation)
if: matrix.config.compiler.type != 'VISUAL' if: matrix.config.compiler.type != 'VISUAL'
shell: bash shell: bash
working-directory: test_package/build/${{ matrix.build_type }} working-directory: test_package/build/${{ matrix.build_type }}
run: | run: |
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
cmake --build . cmake --build .
- name: Run test_package - name: Run test_package
shell: bash shell: bash

3
.gitignore vendored
View File

@@ -40,6 +40,9 @@
/out/ /out/
_build/ _build/
# CMake
CMakeUserPresets.json
# Conan # Conan
*.pyc *.pyc
/test_package/build/ /test_package/build/

2
.gitpod.Dockerfile vendored
View File

@@ -3,10 +3,12 @@ FROM trainiteu/gitpod-cpp
# Add clang-12 and clang-15 apt repositories # Add clang-12 and clang-15 apt repositories
RUN lsb_rel=`lsb_release -cs` \ RUN lsb_rel=`lsb_release -cs` \
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-12 main" \ && sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-12 main" \
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-13 main" \
&& sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel} main" && sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel} main"
# Install older compilers supported by the project as well as clang-format-15 for code formatting # Install older compilers supported by the project as well as clang-format-15 for code formatting
RUN sudo install-packages \ RUN sudo install-packages \
g++-10 \ g++-10 \
clang-12 \ clang-12 \
clang-13 \
clang-format-15 clang-format-15

View File

@@ -84,6 +84,7 @@ tasks:
cp default gcc11 cp default gcc11
cp default clang12 cp default clang12
cp default clang13 cp default clang13
cp default clang14
popd popd
conan profile update settings.compiler.version=10 gcc10 conan profile update settings.compiler.version=10 gcc10
conan profile update env.CXX=/usr/bin/g++-10 gcc10 conan profile update env.CXX=/usr/bin/g++-10 gcc10
@@ -95,9 +96,14 @@ tasks:
conan profile update env.CC=/usr/bin/clang-12 clang12 conan profile update env.CC=/usr/bin/clang-12 clang12
conan profile update settings.compiler=clang clang13 conan profile update settings.compiler=clang clang13
conan profile update settings.compiler.version=13 clang13 conan profile update settings.compiler.version=13 clang13
conan profile update settings.compiler.libcxx=libc++ clang13 conan profile update settings.compiler.libcxx=libstdc++11 clang13
conan profile update env.CXX=/usr/bin/clang++-13 clang13 conan profile update env.CXX=/usr/bin/clang++-13 clang13
conan profile update env.CC=/usr/bin/clang-13 clang13 conan profile update env.CC=/usr/bin/clang-13 clang13
conan profile update settings.compiler=clang clang14
conan profile update settings.compiler.version=14 clang14
conan profile update settings.compiler.libcxx=libc++ clang14
conan profile update env.CXX=/usr/bin/clang++-14 clang14
conan profile update env.CC=/usr/bin/clang-14 clang14
gp sync-done conan-init gp sync-done conan-init
exit exit
- name: gcc-10 - name: gcc-10
@@ -149,6 +155,18 @@ tasks:
ctest -C Release ctest -C Release
ctest -C Debug ctest -C Debug
echo "🛠️ clang-13 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" echo "🛠️ clang-13 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
- name: clang-14
init: |
gp sync-await conan-init
mkdir -p build/Clang-14 && cd build/Clang-14
conan install ../.. -pr clang4 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated
conan install ../.. -pr clang14 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug
cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-14
cmake --build . --config Release -j
cmake --build . --config Debug -j
ctest -C Release
ctest -C Debug
echo "🛠️ clang-14 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️"
- name: documentation - name: documentation
init: | init: |
gp sync-await conan-init gp sync-await conan-init

View File

@@ -2,7 +2,7 @@ default_stages: [commit]
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0 rev: v4.2.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
@@ -16,5 +16,19 @@ repos:
- id: cmake-format - id: cmake-format
additional_dependencies: ["cmakelang[YAML]"] additional_dependencies: ["cmakelang[YAML]"]
# - id: cmake-lint # - id: cmake-lint
# additional_dependencies: ["cmakelang"] # additional_dependencies: ["cmakelang"]
# exclude: "cmake/.*" # exclude: "cmake/.*"
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
args: [--profile, black, --multi-line, "3"]
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
- id: flake8

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
project(mp-units-dev LANGUAGES CXX) project(mp-units-dev LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -71,3 +71,7 @@ add_subdirectory(docs)
# add unit tests # add unit tests
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
# tests for standalone headers
include(TestPublicHeaders)
add_public_header_test(test_headers mp-units::mp-units)

View File

@@ -31,16 +31,14 @@ from cpt.packager import ConanMultiPackager
if __name__ == "__main__": if __name__ == "__main__":
builder = ConanMultiPackager( builder = ConanMultiPackager(
# package id # package id
channel = "testing", channel="testing",
stable_branch_pattern = r"v\d+\.\d+\.\d+.*", stable_branch_pattern=r"v\d+\.\d+\.\d+.*",
# dependencies # dependencies
build_policy = ["mp-units", "outdated"], build_policy=["mp-units", "outdated"],
upload_dependencies = "all", upload_dependencies="all",
pip_install = ["sphinx", "recommonmark", "breathe"], pip_install=["sphinx", "recommonmark", "breathe"],
# build configurations # build configurations
archs = ["x86_64"], # limit to 64-bit only archs=["x86_64"], # limit to 64-bit only
) )
builder.add_common_builds(pure_c=True) builder.add_common_builds(pure_c=True)
for settings, options, env_vars, build_requires, reference in builder.items: for settings, options, env_vars, build_requires, reference in builder.items:

129
cmake/TestHeaders.cmake Normal file
View File

@@ -0,0 +1,129 @@
# Copyright Louis Dionne 2013-2017
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
#
# This CMake module provides a function generating a unit test to make sure
# that every public header can be included on its own.
#
# When a C++ library or application has many header files, it can happen that
# a header does not include all the other headers it depends on. When this is
# the case, it can happen that including that header file on its own will
# break the compilation. This CMake module generates a dummy executable
# comprised of many .cpp files, each of which includes a header file that
# is part of the public API. In other words, the executable is comprised
# of .cpp files of the form:
#
# #include <the/public/header.hpp>
#
# and then exactly one `main` function. If this succeeds to compile, it means
# that the header can be included on its own, which is what clients expect.
# Otherwise, you have a problem. Since writing these dumb unit tests by hand
# is tedious and repetitive, you can use this CMake module to automate this
# task.
# add_header_test(<target> [EXCLUDE_FROM_ALL] [EXCLUDE excludes...] HEADERS headers...)
#
# Generates header-inclusion unit tests for all the specified headers.
#
# This function creates a target which builds a dummy executable including
# each specified header file individually. If this target builds successfully,
# it means that all the specified header files can be included individually.
#
# Parameters
# ----------
# <target>:
# The name of the target to generate.
#
# HEADERS headers:
# A list of header files to generate the inclusion tests for. All headers
# in this list must be represented as relative paths from the root of the
# include directory added to the compiler's header search path. In other
# words, it should be possible to include all headers in this list as
#
# #include <${header}>
#
# For example, for a library with the following structure:
#
# project/
# doc/
# test/
# ...
# include/
# boost/
# hana.hpp
# hana/
# transform.hpp
# tuple.hpp
# pair.hpp
# ...
#
# When building the unit tests for that library, we'll add `-I project/include'
# to the compiler's arguments. The list of public headers should therefore contain
#
# boost/hana.hpp
# boost/hana/transform.hpp
# boost/hana/tuple.hpp
# boost/hana/pair.hpp
# ...
#
# Usually, all the 'public' header files of a library should be tested for
# standalone inclusion. A header is considered 'public' if a client should
# be able to include that header on its own.
#
# [EXCLUDE excludes]:
# An optional list of headers or regexes for which no unit test should be
# generated. Basically, any header in the list specified by the `HEADERS`
# argument that matches anything in `EXCLUDE` will be skipped.
#
# [EXCLUDE_FROM_ALL]:
# If provided, the generated target is excluded from the 'all' target.
#
function(add_header_test target)
cmake_parse_arguments(
ARGS
"EXCLUDE_FROM_ALL" # options
"" # 1 value args
"HEADERS;EXCLUDE" # multivalued args
${ARGN}
)
if(NOT ARGS_HEADERS)
message(FATAL_ERROR "The `HEADERS` argument must be provided.")
endif()
if(ARGS_EXCLUDE_FROM_ALL)
set(ARGS_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL")
else()
set(ARGS_EXCLUDE_FROM_ALL "")
endif()
foreach(header ${ARGS_HEADERS})
set(skip FALSE)
foreach(exclude ${ARGS_EXCLUDE})
if(${header} MATCHES ${exclude})
set(skip TRUE)
break()
endif()
endforeach()
if(skip)
continue()
endif()
get_filename_component(filename "${header}" NAME_WE)
get_filename_component(directory "${header}" DIRECTORY)
set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${directory}/${filename}.cpp")
if(NOT EXISTS "${source}")
file(WRITE "${source}" "#include <${header}>")
endif()
list(APPEND sources "${source}")
endforeach()
set(standalone_main "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp")
if(NOT EXISTS "${standalone_main}")
file(WRITE "${standalone_main}" "int main() { }")
endif()
add_executable(
${target} ${ARGS_EXCLUDE_FROM_ALL} ${sources} "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp"
)
endfunction()

View File

@@ -0,0 +1,67 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.19)
function(get_target_linked_targets target targets_out)
get_target_property(linked_libs ${target} INTERFACE_LINK_LIBRARIES)
foreach(linked_lib ${linked_libs})
if(NOT linked_lib IN_LIST targets)
if(TARGET ${linked_lib})
get_target_linked_targets(${linked_lib} child_targets)
list(APPEND targets ${linked_lib} ${child_targets})
endif()
endif()
endforeach()
list(REMOVE_DUPLICATES targets)
list(REMOVE_DUPLICATES link_libs)
set(${targets_out} ${targets} PARENT_SCOPE)
endfunction()
function(get_target_sources target paths_out)
get_target_linked_targets(${target} targets)
list(APPEND targets ${target})
foreach(t ${targets})
get_target_property(sources ${t} SOURCES)
if(sources)
get_target_property(source_dir ${t} SOURCE_DIR)
foreach(f ${sources})
file(REAL_PATH "${f}" path BASE_DIRECTORY "${source_dir}")
file(RELATIVE_PATH path ${CMAKE_CURRENT_LIST_DIR} "${path}")
list(APPEND paths "${path}")
endforeach()
endif()
endforeach()
set(${paths_out} ${paths} PARENT_SCOPE)
endfunction()
include(TestHeaders)
function(add_public_header_test target test_target)
get_target_sources(${test_target} sources)
add_header_test(${target} HEADERS ${sources})
target_link_libraries(${target} PRIVATE ${test_target})
target_include_directories(${target} PRIVATE .)
endfunction()

View File

@@ -20,67 +20,88 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
from conans import ConanFile, tools import os
from conans.tools import Version, check_min_cppstd import re
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
from conans.errors import ConanInvalidConfiguration from conan import ConanFile
import os, re from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain
from conan.tools.files import copy, load, rmdir
from conan.tools.scm import Version
from conans.errors import ConanInvalidConfiguration
# TODO replace with new tools for Conan 2.0
from conans.tools import check_min_cppstd, get_env
required_conan_version = ">=1.48.0"
required_conan_version = ">=1.44.0"
class MPUnitsConan(ConanFile): class MPUnitsConan(ConanFile):
name = "mp-units" name = "mp-units"
homepage = "https://github.com/mpusz/units" homepage = "https://github.com/mpusz/units"
description = "Physical Units library for C++" description = "Physical Units library for C++"
topics = ("units", "dimensions", "quantities", "dimensional-analysis", "physical-quantities", "physical-units", "system-of-units", "cpp23", "cpp20", "library", "quantity-manipulation") topics = (
"units",
"dimensions",
"quantities",
"dimensional-analysis",
"physical-quantities",
"physical-units",
"system-of-units",
"cpp23",
"cpp20",
"library",
"quantity-manipulation",
)
license = "MIT" license = "MIT"
url = "https://github.com/mpusz/units" url = "https://github.com/mpusz/units"
settings = "os", "compiler", "build_type", "arch" settings = "os", "compiler", "build_type", "arch"
requires = ( requires = "gsl-lite/0.40.0"
"gsl-lite/0.38.1" options = {"downcast_mode": ["off", "on", "auto"], "build_docs": [True, False]}
) default_options = {"downcast_mode": "on", "build_docs": True}
options = {
"downcast_mode": ["off", "on", "auto"],
"build_docs": [True, False]
}
default_options = {
"downcast_mode": "on",
"build_docs": True
}
exports = ["LICENSE.md"] exports = ["LICENSE.md"]
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"] exports_sources = [
"docs/*",
"src/*",
"test/*",
"cmake/*",
"example/*",
"CMakeLists.txt",
]
no_copy_source = True
generators = "cmake_paths" generators = "cmake_paths"
@property @property
def _run_tests(self): def _run_tests(self):
return tools.get_env("CONAN_RUN_TESTS", False) return get_env("CONAN_RUN_TESTS", False)
@property @property
def _use_libfmt(self): def _use_libfmt(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
std_support = \ std_support = (
(compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23) or \ compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23
(compiler == "msvc" and version >= 193 and compiler.cppstd == 23) ) or (compiler == "msvc" and version >= 193 and compiler.cppstd == 23)
return not std_support return not std_support
@property @property
def _use_range_v3(self): def _use_range_v3(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
return ("clang" in compiler and compiler.libcxx == "libc++" and version < 14) return "clang" in compiler and compiler.libcxx == "libc++" and version < 14
@property @property
def _msvc_version(self): def _msvc_version(self):
compiler = self.settings.compiler compiler = self.settings.compiler
if (compiler.update): if compiler.update:
return int(f"{compiler.version}{compiler.update}") return int(f"{compiler.version}{compiler.update}")
else: else:
return int(f"{compiler.version}0") return int(f"{compiler.version}0")
def set_version(self): def set_version(self):
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt")) content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) version = re.search(
r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content
).group(1)
self.version = version.strip() self.version = version.strip()
def requirements(self): def requirements(self):
@@ -92,12 +113,13 @@ class MPUnitsConan(ConanFile):
def build_requirements(self): def build_requirements(self):
if self._run_tests: if self._run_tests:
self.test_requires("catch2/2.13.7") self.test_requires("catch2/2.13.9")
self.test_requires("wg21-linear_algebra/0.7.2") self.test_requires("wg21-linear_algebra/0.7.2")
if self.options.build_docs: if self.options.build_docs:
self.tool_requires("doxygen/1.9.2") self.tool_requires("doxygen/1.9.4")
def validate(self): # TODO Replace with `valdate()` for Conan 2.0 (https://github.com/conan-io/conan/issues/10723)
def configure(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
if compiler == "gcc": if compiler == "gcc":
@@ -108,10 +130,14 @@ class MPUnitsConan(ConanFile):
raise ConanInvalidConfiguration("mp-units requires at least clang++-12") raise ConanInvalidConfiguration("mp-units requires at least clang++-12")
elif compiler == "apple-clang": elif compiler == "apple-clang":
if version < 13: if version < 13:
raise ConanInvalidConfiguration("mp-units requires at least AppleClang 13") raise ConanInvalidConfiguration(
"mp-units requires at least AppleClang 13"
)
elif compiler == "Visual Studio": elif compiler == "Visual Studio":
if version < 16: if version < 16:
raise ConanInvalidConfiguration("mp-units requires at least Visual Studio 16.9") raise ConanInvalidConfiguration(
"mp-units requires at least Visual Studio 16.9"
)
elif compiler == "msvc": elif compiler == "msvc":
if self._msvc_version < 1928: if self._msvc_version < 1928:
raise ConanInvalidConfiguration("mp-units requires at least MSVC 19.28") raise ConanInvalidConfiguration("mp-units requires at least MSVC 19.28")
@@ -146,16 +172,22 @@ class MPUnitsConan(ConanFile):
self.info.header_only() self.info.header_only()
def package(self): def package(self):
self.copy("LICENSE.md", dst="licenses") copy(
self,
"LICENSE.md",
self.source_folder,
os.path.join(self.package_folder, "licenses"),
)
cmake = CMake(self) cmake = CMake(self)
cmake.install() cmake.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake")) rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
def package_info(self): def package_info(self):
compiler = self.settings.compiler compiler = self.settings.compiler
# core # core
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"] self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
self.cpp_info.components["core"].includedirs = ["include"]
if compiler == "Visual Studio": if compiler == "Visual Studio":
self.cpp_info.components["core"].cxxflags = ["/utf-8"] self.cpp_info.components["core"].cxxflags = ["/utf-8"]
if self._use_range_v3: if self._use_range_v3:
@@ -163,19 +195,60 @@ class MPUnitsConan(ConanFile):
# rest # rest
self.cpp_info.components["core-io"].requires = ["core"] self.cpp_info.components["core-io"].requires = ["core"]
self.cpp_info.components["core-io"].includedirs = ["include"]
self.cpp_info.components["core-fmt"].requires = ["core"] self.cpp_info.components["core-fmt"].requires = ["core"]
self.cpp_info.components["core-fmt"].includedirs = ["include"]
if self._use_libfmt: if self._use_libfmt:
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt") self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
self.cpp_info.components["isq"].requires = ["core"] self.cpp_info.components["isq"].requires = ["core"]
self.cpp_info.components["isq"].includedirs = ["include"]
self.cpp_info.components["isq-natural"].requires = ["isq"] self.cpp_info.components["isq-natural"].requires = ["isq"]
self.cpp_info.components["isq-natural"].includedirs = ["include"]
self.cpp_info.components["si"].requires = ["isq"] self.cpp_info.components["si"].requires = ["isq"]
self.cpp_info.components["si"].includedirs = ["include"]
self.cpp_info.components["si-cgs"].requires = ["si"] self.cpp_info.components["si-cgs"].requires = ["si"]
self.cpp_info.components["si-fps"].requires = ["si"] self.cpp_info.components["si-cgs"].includedirs = ["include"]
self.cpp_info.components["si-fps"].requires = ["si-international"]
self.cpp_info.components["si-fps"].includedirs = ["include"]
self.cpp_info.components["si-hep"].requires = ["si"] self.cpp_info.components["si-hep"].requires = ["si"]
self.cpp_info.components["si-hep"].includedirs = ["include"]
self.cpp_info.components["si-iau"].requires = ["si"] self.cpp_info.components["si-iau"].requires = ["si"]
self.cpp_info.components["si-iau"].includedirs = ["include"]
self.cpp_info.components["si-imperial"].requires = ["si"] self.cpp_info.components["si-imperial"].requires = ["si"]
self.cpp_info.components["si-imperial"].includedirs = ["include"]
self.cpp_info.components["si-international"].requires = ["si"] self.cpp_info.components["si-international"].requires = ["si"]
self.cpp_info.components["si-international"].includedirs = ["include"]
self.cpp_info.components["si-typographic"].requires = ["si"] self.cpp_info.components["si-typographic"].requires = ["si"]
self.cpp_info.components["si-typographic"].includedirs = ["include"]
self.cpp_info.components["si-uscs"].requires = ["si"] self.cpp_info.components["si-uscs"].requires = ["si"]
self.cpp_info.components["si-uscs"].includedirs = ["include"]
self.cpp_info.components["isq-iec80000"].requires = ["si"] self.cpp_info.components["isq-iec80000"].requires = ["si"]
self.cpp_info.components["systems"].requires = ["isq", "isq-natural", "si", "si-cgs", "si-fps", "si-hep", "si-iau", "si-imperial", "si-international", "si-typographic", "si-uscs", "isq-iec80000"] self.cpp_info.components["isq-iec80000"].includedirs = ["include"]
self.cpp_info.components["systems"].requires = [
"isq",
"isq-natural",
"si",
"si-cgs",
"si-fps",
"si-hep",
"si-iau",
"si-imperial",
"si-international",
"si-typographic",
"si-uscs",
"isq-iec80000",
]

View File

@@ -2,18 +2,60 @@
- **0.8.0 WIP** - **0.8.0 WIP**
- (!) refactor: `common_quantity`, `common_quantity_for`, `common_quantity_point`, `common_quantity_kind`, and `common_quantity_point_kind` removed - (!) 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: `quantity` `op+()` and `op-()` reimplemented in terms of `reference` rather then `quantity` types
- feat: `std::format` support for compliant compilers added - 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: 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: 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: 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: account for different dimensions in `quantity_point_cast`'s constraint
- build: Minimum Conan version changed to 1.40 - 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: fmt updated to 8.0.1
- build: gsl-lite updated to 0.38.1 - build: gsl-lite updated to 0.40.0
- build: catch2 updated to 2.13.7 - build: catch2 updated to 2.13.9
- build: doxygen updated to 1.9.2 - build: doxygen updated to 1.9.4
- build: linear algebra switched to wg21-linear_algebra/0.7.2 - 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** - **0.7.0 May 11, 2021**
- (!) refactor: `ScalableNumber` renamed to `Representation` - (!) refactor: `ScalableNumber` renamed to `Representation`

View File

@@ -1,122 +1,158 @@
<?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="619px" preserveAspectRatio="none" style="width:678px;height:619px;background:#FCFCFC;" version="1.1" viewBox="0 0 678 619" width="678px" zoomAndPan="magnify"><defs/><g><!--MD5=[197a77df23d290968e58c76a2239d979] <?xml version="1.0" encoding="UTF-8" standalone="no"?>
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 fill="#FCFCFC" height="606" style="stroke:#000000;stroke-width:1.5;" width="665" x="7" y="7"/><path d="M51,7 L51,16.2969 L41,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="34" x="10" y="20.9951">Unit</text></a><!--MD5=[fe9c23f38d3f164e458ed7686471f90d] <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">
class prefix_family--><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"><rect codeLine="11" fill="#F8F8F8" height="23.9688" id="prefix_family" style="stroke:#383838;stroke-width:1.5;" width="82" x="65" y="72"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="76" x="68" y="88.1387">prefix_family</text></a><!--MD5=[2c438ee281b14598fe4adbd039a51ed9] <defs />
class no_prefix--><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"><rect codeLine="12" fill="#F8F8F8" height="23.9688" id="no_prefix" style="stroke:#383838;stroke-width:1.5;" width="61" x="422" y="101"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="55" x="425" y="117.1387">no_prefix</text></a><!--MD5=[8ec8902a0493db0501cc5ae48138d755] <g>
class prefix--><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"><rect codeLine="13" fill="#F8F8F8" height="23.9688" id="prefix" style="stroke:#383838;stroke-width:1.5;" width="207" x="349" y="42"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="34" x="352" y="58.1387">prefix</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="165" x="394" y="39"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="163" x="395" y="51.1387">PrefixFamily, Symbol, Ratio</text></a><!--MD5=[124cbcdfdb408a63d08476bd52d3bb38] <!--MD5=[197a77df23d290968e58c76a2239d979]
class scaled_unit--><rect codeLine="26" fill="#F8F8F8" height="23.9688" id="scaled_unit" style="stroke:#383838;stroke-width:1.5;" width="166" x="23" y="367"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="68" x="26" y="383.1387">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="102" y="364"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="88" x="103" y="376.1387">UnitRatio, Unit</text><!--MD5=[c262fc293e71d96455ecd38c5cba51e9] cluster Unit-->
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"><rect codeLine="28" fill="#F8F8F8" height="23.9688" id="prefixed_alias_unit" style="stroke:#383838;stroke-width:1.5;" width="247" x="329" y="573"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="111" x="332" y="589.1387">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="451" y="570"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="126" x="452" y="582.1387">Unit, Prefix, AliasUnit</text></a><!--MD5=[80b1f1fe027b66c9bd530ac9502a064a] <g id="cluster_Unit">
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"><rect codeLine="29" fill="#F8F8F8" height="23.9688" id="alias_unit" style="stroke:#383838;stroke-width:1.5;" width="224" x="340.5" y="514"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="56" x="343.5" y="530.1387">alias_unit</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="160" x="407.5" y="511"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="158" x="408.5" y="523.1387">Unit, Symbol, PrefixFamily</text></a><!--MD5=[a28d6ca64d3db0c31a0f1e5dbad7ee82] <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">
class named_derived_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"><rect codeLine="30" fill="#F8F8F8" height="23.9688" id="named_derived_unit" style="stroke:#383838;stroke-width:1.5;" width="407" x="249" y="455"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="123" x="252" y="471.1387">named_derived_unit</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="276" x="383" y="452"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="274" x="384" y="464.1387">Dimension, Symbol, PrefixFamily, Unit, Unit...</text></a><!--MD5=[21a38f8b465de3a6a580896bb83abf03] <rect height="443" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;fill:none;" width="578" x="7" y="7" />
class derived_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"><rect codeLine="31" fill="#F8F8F8" height="23.9688" id="derived_unit" style="stroke:#383838;stroke-width:1.5;" width="226" x="339.5" y="396"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="75" x="342.5" y="412.1387">derived_unit</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="143" x="425.5" y="393"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="141" x="426.5" y="405.1387">Dimension, Unit, Unit...</text></a><!--MD5=[002996a525ad7ee43e1a2ae0bbb7adb6] <path d="M51,7 L51,16.2969 L41,26.2969 L7,26.2969 " fill="none" style="stroke:#181818;stroke-width:1.0;" />
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"><rect codeLine="32" fill="#F8F8F8" height="23.9688" id="prefixed_unit" style="stroke:#383838;stroke-width:1.5;" width="155" x="375" y="337"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="79" x="378" y="353.1387">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="465" y="334"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="66" x="466" y="346.1387">Prefix, Unit</text></a><!--MD5=[3a0c8cf47fc662100af5bce8b7f7e204] <text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="34" x="10" y="20.9951">Unit</text>
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"><rect codeLine="33" fill="#F8F8F8" height="23.9688" id="named_scaled_unit" style="stroke:#383838;stroke-width:1.5;" width="322" x="291.5" y="278"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="116" x="294.5" y="294.1387">named_scaled_unit</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="198" x="418.5" y="275"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="196" x="419.5" y="287.1387">Symbol, PrefixFamily, Ratio, Unit</text></a><!--MD5=[5e57872b30d77ee0da3206dd3d117986] </a>
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"><rect codeLine="34" fill="#F8F8F8" height="23.9688" id="named_unit" style="stroke:#383838;stroke-width:1.5;" width="207" x="349" y="219"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="72" x="352" y="235.1387">named_unit</text><rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="127" x="432" y="216"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="125" x="433" y="228.1387">Symbol, PrefixFamily</text></a><!--MD5=[71453aad0c321cc4e5ffc62c5a278467] </g> <!--MD5=[124cbcdfdb408a63d08476bd52d3bb38]
class 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"><rect codeLine="35" fill="#F8F8F8" height="23.9688" id="unit" style="stroke:#383838;stroke-width:1.5;" width="30" x="437.5" y="160"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="24" x="440.5" y="176.1387">unit</text></a><!--MD5=[d5573293cc2f3397d55e23fbd852731b] class scaled_unit-->
reverse link prefix_family to no_prefix--><path codeLine="15" d="M167.21,89.068 C241.552,95.327 365.078,105.725 421.603,110.483 " fill="none" id="prefix_family-backto-no_prefix" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="166.535,96.037,147.193,87.383,167.709,82.086,166.535,96.037" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[a9e0649862d8c9099c6cf94917b5c4f3] <g id="elem_scaled_unit">
reverse link prefix_family to prefix--><path codeLine="16" d="M152.197,80.064 C201.883,75.737 283.334,68.644 348.732,62.949 " fill="none" id="prefix_family-backto-prefix" style="stroke:#383838;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#383838" points="147.193,80.5,156.5065,83.703,152.1741,80.0656,155.8115,75.7332,147.193,80.5" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[f28f95aa1567536fda19ae5fa7526b9f] <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" />
reverse link scaled_unit to unit--><path codeLine="37" d="M121.677,348.907 C143.37,307.974 188.09,235.861 249,201 C311.726,165.099 402.687,167.95 437.358,170.629 " fill="none" id="scaled_unit-backto-unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="127.857,352.199,112.578,366.881,115.366,345.876,127.857,352.199" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[d10f3427b03caf67d8b4e569e5f4936e] <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>
reverse link scaled_unit to named_unit--><path codeLine="38" d="M130.613,351.798 C156.605,323.813 201.102,281.383 249,260 C279.89,246.21 315.826,238.667 348.778,234.632 " fill="none" id="scaled_unit-backto-named_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="135.822,356.473,117.258,366.689,125.4,347.126,135.822,356.473" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[c4573f7b87c3262f7d3adc92106a39ed] <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" />
reverse link scaled_unit to named_scaled_unit--><path codeLine="39" d="M148.735,357.996 C176.499,344.874 214.14,328.686 249,319 C275.263,311.703 303.979,306.175 331.318,302.01 " fill="none" id="scaled_unit-backto-named_scaled_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="151.495,364.437,130.445,366.872,145.382,351.842,151.495,364.437" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[65b74da07c0359a7bcc888d9c9b6e7d5] <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>
reverse link scaled_unit to prefixed_unit--><path codeLine="40" d="M209.206,370.1 C262.255,365.48 325.987,359.93 374.771,355.682 " fill="none" id="scaled_unit-backto-prefixed_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="209.611,377.091,189.079,371.852,208.396,363.144,209.611,377.091" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[29a2e6b65a8256359df6b41e4d3b7c7c] </g> <!--MD5=[c262fc293e71d96455ecd38c5cba51e9]
reverse link scaled_unit to derived_unit--><path codeLine="41" d="M209.24,387.607 C250.204,391.055 297.536,395.039 339.433,398.566 " fill="none" id="scaled_unit-backto-derived_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="208.421,394.562,189.079,385.909,209.595,380.612,208.421,394.562" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[70b39df7ba7c3deccddaa8e432f196b0] class prefixed_alias_unit-->
reverse link scaled_unit to named_derived_unit--><path codeLine="42" d="M149.575,399.543 C177.302,412.126 214.589,427.572 249,437 C277.193,444.724 308.173,450.582 337.239,454.975 " fill="none" id="scaled_unit-backto-named_derived_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="146.43,405.801,131.253,391.014,152.338,393.109,146.43,405.801" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[19d99332ae619b76851ceaa34f4e9014] <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">
reverse link scaled_unit to alias_unit--><path codeLine="43" d="M131.097,406.082 C157.237,433.557 201.619,474.947 249,496 C277.337,508.591 309.881,516.084 340.472,520.492 " fill="none" id="scaled_unit-backto-alias_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="125.691,410.543,117.316,391.079,136.001,401.072,125.691,410.543" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[a61d68e6008f4d1392d92030b50774f1] <g id="elem_prefixed_alias_unit">
reverse link scaled_unit to prefixed_alias_unit--><path codeLine="44" d="M121.723,408.926 C143.469,449.631 188.251,521.342 249,556 C273.061,569.7274 301.259,577.7818 328.839,582.3459 " fill="none" id="scaled_unit-backto-prefixed_alias_unit" style="stroke:#383838;stroke-width:1.0;"/><polygon fill="none" points="115.457,412.048,112.598,391.052,127.926,405.682,115.457,412.048" style="stroke:#383838;stroke-width:1.0;"/><!--MD5=[0d042b3ffad7c4747f62a95996e464a5] <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 @startuml
skinparam monochrome true skinparam monochrome true
skinparam shadowing false skinparam shadowing false
skinparam backgroundColor #fcfcfc skinparam backgroundColor #fcfcfc
hide members hide members
hide circle hide circle
left to right direction left to right direction
package Unit <<Frame>> [[../../framework/units.html]] { package Unit <<Frame>> [[../../framework/units.html]] {
abstract prefix_family [[../../framework/units.html#prefixed-unit]]
abstract no_prefix [[../../framework/units.html#named-scaled-units]]
abstract prefix<PrefixFamily, Symbol, Ratio> [[../../framework/units.html#prefixed-unit]]
prefix_family <|- - no_prefix abstract scaled_unit<UnitRatio, Unit>
prefix_family <.. prefix
' prefix_family <.. named_unit abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
' prefix_family <.. named_scaled_unit abstract alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
' prefix_family <.. named_derived_unit abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
' prefix_family <.. alias_unit 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]]
' prefix <.. prefixed_unit scaled_unit <|- - named_unit
' prefix <.. prefixed_alias_unit scaled_unit <|- - named_scaled_unit
scaled_unit <|- - prefixed_unit
abstract scaled_unit<UnitRatio, Unit> scaled_unit <|- - derived_unit
scaled_unit <|- - derived_scaled_unit
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]] scaled_unit <|- - alias_unit
abstract alias_unit<Unit, Symbol, PrefixFamily> [[../../framework/units.html#aliased-units]] scaled_unit <|- - prefixed_alias_unit
abstract named_derived_unit<Dimension, Symbol, PrefixFamily, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]] }
abstract derived_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
abstract named_scaled_unit<Symbol, PrefixFamily, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
abstract named_unit<Symbol, PrefixFamily> [[../../framework/units.html#base-units]]
abstract unit [[../../framework/units.html#derived-unnamed-units]]
scaled_unit <|- - unit
scaled_unit <|- - named_unit
scaled_unit <|- - named_scaled_unit
scaled_unit <|- - prefixed_unit
scaled_unit <|- - derived_unit
scaled_unit <|- - named_derived_unit
scaled_unit <|- - alias_unit
scaled_unit <|- - prefixed_alias_unit
}
@enduml @enduml
@startuml PlantUML version 1.2022.5(Sat Apr 30 10:55:52 UTC 2022)
skinparam monochrome true
skinparam shadowing false
skinparam backgroundColor #fcfcfc
hide members
hide circle
left to right direction
package Unit <<Frame>> [[../../framework/units.html]] {
abstract prefix_family [[../../framework/units.html#prefixed-unit]]
abstract no_prefix [[../../framework/units.html#named-scaled-units]]
abstract prefix<PrefixFamily, Symbol, Ratio> [[../../framework/units.html#prefixed-unit]]
prefix_family <|- - no_prefix
prefix_family <.. prefix
abstract scaled_unit<UnitRatio, Unit>
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
abstract alias_unit<Unit, Symbol, PrefixFamily> [[../../framework/units.html#aliased-units]]
abstract named_derived_unit<Dimension, Symbol, PrefixFamily, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract derived_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
abstract named_scaled_unit<Symbol, PrefixFamily, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
abstract named_unit<Symbol, PrefixFamily> [[../../framework/units.html#base-units]]
abstract unit [[../../framework/units.html#derived-unnamed-units]]
scaled_unit <|- - unit
scaled_unit <|- - named_unit
scaled_unit <|- - named_scaled_unit
scaled_unit <|- - prefixed_unit
scaled_unit <|- - derived_unit
scaled_unit <|- - named_derived_unit
scaled_unit <|- - alias_unit
scaled_unit <|- - prefixed_alias_unit
}
@enduml
PlantUML version 1.2021.12(Tue Oct 05 16:01:58 UTC 2021)
(GPL source distribution) (GPL source distribution)
Java Runtime: Java(TM) SE Runtime Environment Java Runtime: Java(TM) SE Runtime Environment
JVM: Java HotSpot(TM) 64-Bit Server VM JVM: Java HotSpot(TM) 64-Bit Server VM
Default Encoding: UTF-8 Default Encoding: UTF-8
Language: en Language: en
Country: US Country: US
--></g></svg> -->
</g>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -9,155 +9,315 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os
import re import re
import sphinx_rtd_theme import subprocess
from pygments.lexer import RegexLexer, include, bygroups, using, \ from pygments.lexer import (
this, inherit, default, words RegexLexer,
bygroups,
default,
include,
inherit,
this,
using,
words,
)
from pygments.token import (
Comment,
Error,
Keyword,
Name,
Number,
Operator,
Punctuation,
String,
Text,
)
from pygments.util import get_bool_opt from pygments.util import get_bool_opt
from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
Number, Punctuation, Error
from sphinx.highlighting import lexers from sphinx.highlighting import lexers
class MyCFamilyLexer(RegexLexer): class MyCFamilyLexer(RegexLexer):
#: optional Comment or Whitespace #: optional Comment or Whitespace
_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+' _ws = r"(?:\s|//.*?\n|/[*].*?[*]/)+"
# The trailing ?, rather than *, avoids a geometric performance drop here. # The trailing ?, rather than *, avoids a geometric performance drop here.
#: only one /* */ style comment #: only one /* */ style comment
_ws1 = r'\s*(?:/[*].*?[*]/\s*)?' _ws1 = r"\s*(?:/[*].*?[*]/\s*)?"
tokens = { tokens = {
'whitespace': [ "whitespace": [
# preprocessor directives: without whitespace # preprocessor directives: without whitespace
(r'^#if\s+0', Comment.Preproc, 'if0'), (r"^#if\s+0", Comment.Preproc, "if0"),
('^#', Comment.Preproc, 'macro'), ("^#", Comment.Preproc, "macro"),
# or with whitespace # or with whitespace
('^(' + _ws1 + r')(#if\s+0)', (
bygroups(using(this), Comment.Preproc), 'if0'), "^(" + _ws1 + r")(#if\s+0)",
('^(' + _ws1 + ')(#)', bygroups(using(this), Comment.Preproc),
bygroups(using(this), Comment.Preproc), 'macro'), "if0",
(r'\n', Text), ),
(r'\s+', Text), ("^(" + _ws1 + ")(#)", bygroups(using(this), Comment.Preproc), "macro"),
(r'\\\n', Text), # line continuation (r"\n", Text),
(r'//(\n|[\w\W]*?[^\\]\n)', Comment.Single), (r"\s+", Text),
(r'/(\\\n)?[*][\w\W]*?[*](\\\n)?/', Comment.Multiline), (r"\\\n", Text), # line continuation
(r"//(\n|[\w\W]*?[^\\]\n)", Comment.Single),
(r"/(\\\n)?[*][\w\W]*?[*](\\\n)?/", Comment.Multiline),
# Open until EOF, so no ending delimeter # Open until EOF, so no ending delimeter
(r'/(\\\n)?[*][\w\W]*', Comment.Multiline), (r"/(\\\n)?[*][\w\W]*", Comment.Multiline),
], ],
'statements': [ "statements": [
(r'(L?)(")', bygroups(String.Affix, String), 'string'), (r'(L?)(")', bygroups(String.Affix, String), "string"),
(r"(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')", (
bygroups(String.Affix, String.Char, String.Char, String.Char)), r"(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')",
(r'\*/', Error), bygroups(String.Affix, String.Char, String.Char, String.Char),
(r'[~!%^&*+=|?:<>/-]', Operator), ),
(r'[()\[\],.]', Punctuation), (r"\*/", Error),
(words(('asm', 'auto', 'break', 'case', 'const', 'continue', (r"[~!%^&*+=|?:<>/-]", Operator),
'default', 'do', 'else', 'enum', 'extern', 'for', 'goto', (r"[()\[\],.]", Punctuation),
'if', 'register', 'restricted', 'return', 'sizeof', (
'static', 'struct', 'switch', 'typedef', 'union', words(
'volatile', 'while'), (
suffix=r'\b'), Keyword), "asm",
(r'(bool|int|long|float|short|double|char|unsigned|signed|void)\b', "auto",
Keyword.Type), "break",
(words(('inline', '_inline', '__inline', 'naked', 'restrict', "case",
'thread', 'typename'), suffix=r'\b'), Keyword.Reserved), "const",
"continue",
"default",
"do",
"else",
"enum",
"extern",
"for",
"goto",
"if",
"register",
"restricted",
"return",
"sizeof",
"static",
"struct",
"switch",
"typedef",
"union",
"volatile",
"while",
),
suffix=r"\b",
),
Keyword,
),
(
r"(bool|int|long|float|short|double|char|unsigned|signed|void)\b",
Keyword.Type,
),
(
words(
(
"inline",
"_inline",
"__inline",
"naked",
"restrict",
"thread",
"typename",
),
suffix=r"\b",
),
Keyword.Reserved,
),
# Vector intrinsics # Vector intrinsics
(r'(__m(128i|128d|128|64))\b', Keyword.Reserved), (r"(__m(128i|128d|128|64))\b", Keyword.Reserved),
# Microsoft-isms # Microsoft-isms
(words(( (
'asm', 'int8', 'based', 'except', 'int16', 'stdcall', 'cdecl', words(
'fastcall', 'int32', 'declspec', 'finally', 'int64', 'try', (
'leave', 'wchar_t', 'w64', 'unaligned', 'raise', 'noop', "asm",
'identifier', 'forceinline', 'assume'), "int8",
prefix=r'__', suffix=r'\b'), Keyword.Reserved), "based",
(r'(true|false|NULL)\b', Name.Builtin), "except",
(r'([a-zA-Z_]\w*)(\s*)(:)(?!:)', bygroups(Name.Label, Text, Punctuation)), "int16",
(r'[a-zA-Z_]\w*', Name), "stdcall",
"cdecl",
"fastcall",
"int32",
"declspec",
"finally",
"int64",
"try",
"leave",
"wchar_t",
"w64",
"unaligned",
"raise",
"noop",
"identifier",
"forceinline",
"assume",
),
prefix=r"__",
suffix=r"\b",
),
Keyword.Reserved,
),
(r"(true|false|NULL)\b", Name.Builtin),
(r"([a-zA-Z_]\w*)(\s*)(:)(?!:)", bygroups(Name.Label, Text, Punctuation)),
(r"[a-zA-Z_]\w*", Name),
], ],
'root': [ "root": [
include('whitespace'), include("whitespace"),
# functions # functions
(r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments (
r'([a-zA-Z_]\w*)' # method name r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments
r'(\s*\([^;]*?\))' # signature r"([a-zA-Z_]\w*)" # method name
r'([^;{]*)(\{)', r"(\s*\([^;]*?\))" # signature
bygroups(using(this), Name.Function, using(this), using(this), r"([^;{]*)(\{)",
Punctuation), bygroups(
'function'), using(this), Name.Function, using(this), using(this), Punctuation
),
"function",
),
# function declarations # function declarations
(r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments (
r'([a-zA-Z_]\w*)' # method name r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments
r'(\s*\([^;]*?\))' # signature r"([a-zA-Z_]\w*)" # method name
r'([^;]*)(;)', r"(\s*\([^;]*?\))" # signature
bygroups(using(this), Name.Function, using(this), using(this), r"([^;]*)(;)",
Punctuation)), bygroups(
default('statement'), using(this), Name.Function, using(this), using(this), Punctuation
),
),
default("statement"),
], ],
'statement': [ "statement": [
include('whitespace'), include("whitespace"),
include('statements'), include("statements"),
('[{}]', Punctuation), ("[{}]", Punctuation),
(';', Punctuation, '#pop'), (";", Punctuation, "#pop"),
], ],
'function': [ "function": [
include('whitespace'), include("whitespace"),
include('statements'), include("statements"),
(';', Punctuation), (";", Punctuation),
(r'\{', Punctuation, '#push'), (r"\{", Punctuation, "#push"),
(r'\}', Punctuation, '#pop'), (r"\}", Punctuation, "#pop"),
], ],
'string': [ "string": [
(r'"', String, '#pop'), (r'"', String, "#pop"),
(r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|' (
r'u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})', String.Escape), r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|'
r"u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})",
String.Escape,
),
(r'[^\\"\n]+', String), # all other characters (r'[^\\"\n]+', String), # all other characters
(r'\\\n', String), # line continuation (r"\\\n", String), # line continuation
(r'\\', String), # stray backslash (r"\\", String), # stray backslash
], ],
'macro': [ "macro": [
(r'(include)(' + _ws1 + r')([^\n]+)', (
bygroups(Comment.Preproc, Text, Comment.PreprocFile)), r"(include)(" + _ws1 + r")([^\n]+)",
(r'[^/\n]+', Comment.Preproc), bygroups(Comment.Preproc, Text, Comment.PreprocFile),
(r'/[*](.|\n)*?[*]/', Comment.Multiline), ),
(r'//.*?\n', Comment.Single, '#pop'), (r"[^/\n]+", Comment.Preproc),
(r'/', Comment.Preproc), (r"/[*](.|\n)*?[*]/", Comment.Multiline),
(r'(?<=\\)\n', Comment.Preproc), (r"//.*?\n", Comment.Single, "#pop"),
(r'\n', Comment.Preproc, '#pop'), (r"/", Comment.Preproc),
(r"(?<=\\)\n", Comment.Preproc),
(r"\n", Comment.Preproc, "#pop"),
],
"if0": [
(r"^\s*#if.*?(?<!\\)\n", Comment.Preproc, "#push"),
(r"^\s*#el(?:se|if).*\n", Comment.Preproc, "#pop"),
(r"^\s*#endif.*?(?<!\\)\n", Comment.Preproc, "#pop"),
(r".*?\n", Comment),
], ],
'if0': [
(r'^\s*#if.*?(?<!\\)\n', Comment.Preproc, '#push'),
(r'^\s*#el(?:se|if).*\n', Comment.Preproc, '#pop'),
(r'^\s*#endif.*?(?<!\\)\n', Comment.Preproc, '#pop'),
(r'.*?\n', Comment),
]
} }
stdlib_types = { stdlib_types = {
'size_t', 'ssize_t', 'off_t', 'wchar_t', 'ptrdiff_t', 'sig_atomic_t', 'fpos_t', "size_t",
'clock_t', 'time_t', 'va_list', 'jmp_buf', 'FILE', 'DIR', 'div_t', 'ldiv_t', "ssize_t",
'mbstate_t', 'wctrans_t', 'wint_t', 'wctype_t'} "off_t",
"wchar_t",
"ptrdiff_t",
"sig_atomic_t",
"fpos_t",
"clock_t",
"time_t",
"va_list",
"jmp_buf",
"FILE",
"DIR",
"div_t",
"ldiv_t",
"mbstate_t",
"wctrans_t",
"wint_t",
"wctype_t",
}
c99_types = { c99_types = {
'_Bool', '_Complex', 'int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', "_Bool",
'uint16_t', 'uint32_t', 'uint64_t', 'int_least8_t', 'int_least16_t', "_Complex",
'int_least32_t', 'int_least64_t', 'uint_least8_t', 'uint_least16_t', "int8_t",
'uint_least32_t', 'uint_least64_t', 'int_fast8_t', 'int_fast16_t', 'int_fast32_t', "int16_t",
'int_fast64_t', 'uint_fast8_t', 'uint_fast16_t', 'uint_fast32_t', 'uint_fast64_t', "int32_t",
'intptr_t', 'uintptr_t', 'intmax_t', 'uintmax_t'} "int64_t",
"uint8_t",
"uint16_t",
"uint32_t",
"uint64_t",
"int_least8_t",
"int_least16_t",
"int_least32_t",
"int_least64_t",
"uint_least8_t",
"uint_least16_t",
"uint_least32_t",
"uint_least64_t",
"int_fast8_t",
"int_fast16_t",
"int_fast32_t",
"int_fast64_t",
"uint_fast8_t",
"uint_fast16_t",
"uint_fast32_t",
"uint_fast64_t",
"intptr_t",
"uintptr_t",
"intmax_t",
"uintmax_t",
}
linux_types = { linux_types = {
'clockid_t', 'cpu_set_t', 'cpumask_t', 'dev_t', 'gid_t', 'id_t', 'ino_t', 'key_t', "clockid_t",
'mode_t', 'nfds_t', 'pid_t', 'rlim_t', 'sig_t', 'sighandler_t', 'siginfo_t', "cpu_set_t",
'sigset_t', 'sigval_t', 'socklen_t', 'timer_t', 'uid_t'} "cpumask_t",
"dev_t",
"gid_t",
"id_t",
"ino_t",
"key_t",
"mode_t",
"nfds_t",
"pid_t",
"rlim_t",
"sig_t",
"sighandler_t",
"siginfo_t",
"sigset_t",
"sigval_t",
"socklen_t",
"timer_t",
"uid_t",
}
def __init__(self, **options): def __init__(self, **options):
self.stdlibhighlighting = get_bool_opt(options, 'stdlibhighlighting', True) self.stdlibhighlighting = get_bool_opt(options, "stdlibhighlighting", True)
self.c99highlighting = get_bool_opt(options, 'c99highlighting', True) self.c99highlighting = get_bool_opt(options, "c99highlighting", True)
self.platformhighlighting = get_bool_opt(options, 'platformhighlighting', True) self.platformhighlighting = get_bool_opt(options, "platformhighlighting", True)
RegexLexer.__init__(self, **options) RegexLexer.__init__(self, **options)
def get_tokens_unprocessed(self, text): def get_tokens_unprocessed(self, text):
for index, token, value in \ for index, token, value in RegexLexer.get_tokens_unprocessed(self, text):
RegexLexer.get_tokens_unprocessed(self, text):
if token is Name: if token is Name:
if self.stdlibhighlighting and value in self.stdlib_types: if self.stdlibhighlighting and value in self.stdlib_types:
token = Keyword.Type token = Keyword.Type
@@ -172,65 +332,147 @@ class MyCppLexer(MyCFamilyLexer):
""" """
For C++ source code with preprocessor directives. For C++ source code with preprocessor directives.
""" """
name = 'My C++'
aliases = ['cpp', 'c++'] name = "My C++"
filenames = ['*.cpp', '*.hpp', '*.c++', '*.h++', aliases = ["cpp", "c++"]
'*.cc', '*.hh', '*.cxx', '*.hxx', filenames = [
'*.C', '*.H', '*.cp', '*.CPP'] "*.cpp",
mimetypes = ['text/x-c++hdr', 'text/x-c++src'] "*.hpp",
"*.c++",
"*.h++",
"*.cc",
"*.hh",
"*.cxx",
"*.hxx",
"*.C",
"*.H",
"*.cp",
"*.CPP",
]
mimetypes = ["text/x-c++hdr", "text/x-c++src"]
priority = 0.1 priority = 0.1
tokens = { tokens = {
'statements': [ "statements": [
(words(( (
'catch', 'const_cast', 'delete', 'dynamic_cast', 'explicit', words(
'export', 'friend', 'mutable', 'namespace', 'new', 'operator', (
'private', 'protected', 'public', 'reinterpret_cast', "catch",
'restrict', 'static_cast', 'template', 'this', 'throw', 'throws', "const_cast",
'try', 'typeid', 'typename', 'using', 'virtual', "delete",
'constexpr', 'nullptr', 'decltype', 'thread_local', "dynamic_cast",
'alignas', 'alignof', 'static_assert', 'noexcept', 'override', "explicit",
'final', 'constinit', 'consteval', 'constinit', 'concept', 'co_await', "export",
'co_return', 'co_yield', 'requires', 'import', 'module'), suffix=r'\b'), Keyword), "friend",
(r'char(16_t|32_t|8_t)\b', Keyword.Type), "mutable",
(r'(class)(\s+)', bygroups(Keyword, Text), 'classname'), "namespace",
"new",
"operator",
"private",
"protected",
"public",
"reinterpret_cast",
"restrict",
"static_cast",
"template",
"this",
"throw",
"throws",
"try",
"typeid",
"typename",
"using",
"virtual",
"constexpr",
"nullptr",
"decltype",
"thread_local",
"alignas",
"alignof",
"static_assert",
"noexcept",
"override",
"final",
"constinit",
"consteval",
"constinit",
"concept",
"co_await",
"co_return",
"co_yield",
"requires",
"import",
"module",
),
suffix=r"\b",
),
Keyword,
),
(r"char(16_t|32_t|8_t)\b", Keyword.Type),
(r"(class)(\s+)", bygroups(Keyword, Text), "classname"),
# C++11 raw strings # C++11 raw strings
(r'(R)(")([^\\()\s]{,16})(\()((?:.|\n)*?)(\)\3)(")', (
bygroups(String.Affix, String, String.Delimiter, String.Delimiter, r'(R)(")([^\\()\s]{,16})(\()((?:.|\n)*?)(\)\3)(")',
String, String.Delimiter, String)), bygroups(
String.Affix,
String,
String.Delimiter,
String.Delimiter,
String,
String.Delimiter,
String,
),
),
# C++11 UTF-8/16/32 strings # C++11 UTF-8/16/32 strings
(r'(u8|u|U)(")', bygroups(String.Affix, String), 'string'), (r'(u8|u|U)(")', bygroups(String.Affix, String), "string"),
# C++14 number separators # C++14 number separators
(r'(\d[\d\']*\.[\d\']*|\.\d[\d\']*|\d[\d\']*)[eE][+-]?\d[\d\']*[LlUu]*', Number.Float), (
(r'(\d[\d\']*\.[\d\']*|\.\d[\d\']*|\d[\d\']*[fF])[fF]?', Number.Float), r"(\d[\d\']*\.[\d\']*|\.\d[\d\']*|\d[\d\']*)[eE][+-]?\d[\d\']*[LlUu]*",
(r'0x[0-9a-fA-F\']+[LlUu]*', Number.Hex), Number.Float,
(r'0[0-7\']+[LlUu]*', Number.Oct), ),
(r'\d[\d\']*[LlUu]*', Number.Integer), (r"(\d[\d\']*\.[\d\']*|\.\d[\d\']*|\d[\d\']*[fF])[fF]?", Number.Float),
(r"0x[0-9a-fA-F\']+[LlUu]*", Number.Hex),
(r"0[0-7\']+[LlUu]*", Number.Oct),
(r"\d[\d\']*[LlUu]*", Number.Integer),
inherit, inherit,
], ],
'root': [ "root": [
inherit, inherit,
# C++ Microsoft-isms # C++ Microsoft-isms
(words(('virtual_inheritance', 'uuidof', 'super', 'single_inheritance', (
'multiple_inheritance', 'interface', 'event'), words(
prefix=r'__', suffix=r'\b'), Keyword.Reserved), (
"virtual_inheritance",
"uuidof",
"super",
"single_inheritance",
"multiple_inheritance",
"interface",
"event",
),
prefix=r"__",
suffix=r"\b",
),
Keyword.Reserved,
),
# Offload C++ extensions, http://offload.codeplay.com/ # Offload C++ extensions, http://offload.codeplay.com/
(r'__(offload|blockingoffload|outer)\b', Keyword.Pseudo), (r"__(offload|blockingoffload|outer)\b", Keyword.Pseudo),
], ],
'classname': [ "classname": [
(r'[a-zA-Z_]\w*', Name.Class, '#pop'), (r"[a-zA-Z_]\w*", Name.Class, "#pop"),
# template specification # template specification
(r'\s*(?=>)', Text, '#pop'), (r"\s*(?=>)", Text, "#pop"),
], ],
} }
def analyse_text(text): def analyse_text(text):
if re.search('#include <[a-z_]+>', text): if re.search("#include <[a-z_]+>", text):
return 0.2 return 0.2
if re.search('using namespace ', text): if re.search("using namespace ", text):
return 0.4 return 0.4
lexers['cpp'] = MyCppLexer(startinline=True)
lexers["cpp"] = MyCppLexer(startinline=True)
# TODO Remove the above when Pygments release with fixes is available # TODO Remove the above when Pygments release with fixes is available
@@ -241,13 +483,14 @@ lexers['cpp'] = MyCppLexer(startinline=True)
# For a full list see the documentation: # For a full list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html # https://www.sphinx-doc.org/en/master/usage/configuration.html
import subprocess, os, re
def get_version(): def get_version():
try: try:
with open('../src/CMakeLists.txt', 'r') as file: with open("../src/CMakeLists.txt", "r") as file:
content = file.read() content = file.read()
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) version = re.search(
r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content
).group(1)
return version.strip() return version.strip()
except Exception: except Exception:
return None return None
@@ -255,9 +498,9 @@ def get_version():
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = 'mp-units' project = "mp-units"
copyright = '2018-present, Mateusz Pusz' copyright = "2018-present, Mateusz Pusz"
author = 'Mateusz Pusz' author = "Mateusz Pusz"
# The major project version, used as the replacement for |version|. # The major project version, used as the replacement for |version|.
version = get_version() version = get_version()
@@ -270,21 +513,21 @@ release = get_version()
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
'sphinx.ext.autosectionlabel', "sphinx.ext.autosectionlabel",
'sphinx.ext.githubpages', "sphinx.ext.githubpages",
'sphinx.ext.graphviz', "sphinx.ext.graphviz",
'sphinx_rtd_theme', "sphinx_rtd_theme",
'recommonmark', "recommonmark",
'breathe' "breathe",
] ]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path. # This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# If true, Sphinx will warn about all references where the target cannot # If true, Sphinx will warn about all references where the target cannot
# be found. Default is False. # be found. Default is False.
@@ -305,29 +548,29 @@ autosectionlabel_prefix_document = True
# The name of the default domain. Can also be None to disable a default # The name of the default domain. Can also be None to disable a default
# domain. The default is 'py'. # domain. The default is 'py'.
primary_domain = 'cpp' primary_domain = "cpp"
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.
default_role = 'cpp:any' default_role = "cpp:any"
# The default language to highlight source code in. The default is 'python3'. # 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). # The value should be a valid Pygments lexer name (https://pygments.org/docs/lexers).
highlight_language = 'cpp' highlight_language = "cpp"
# The style name to use for Pygments highlighting of source code. If not set, # The style name to use for Pygments highlighting of source code. If not set,
# either the themes default style or 'sphinx' is selected for HTML output. # either the themes default style or 'sphinx' is selected for HTML output.
pygments_style = 'default' pygments_style = "default"
# A list of prefixes that will be ignored when sorting C++ objects in the global # A list of prefixes that will be ignored when sorting C++ objects in the global
# index. For example ['awesome_lib::']. # index. For example ['awesome_lib::'].
cpp_index_common_prefix = ['units::'] cpp_index_common_prefix = ["units::"]
# -- Options for HTML output ------------------------------------------------- # -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'sphinx_rtd_theme' html_theme = "sphinx_rtd_theme"
# A dictionary of options that influence the look and feel of the selected theme. # A dictionary of options that influence the look and feel of the selected theme.
# These are theme-specific. # These are theme-specific.
@@ -339,7 +582,7 @@ html_theme_options = {
# Add any paths that contain custom static files (such as style sheets) here, # 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, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ["_static"]
# If given, this must be the name of an image file (path relative to the # 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 # configuration directory) that is the logo of the docs. It is placed at the
@@ -349,45 +592,45 @@ html_static_path = ['_static']
# These paths are either relative to html_static_path or fully qualified # These paths are either relative to html_static_path or fully qualified
# paths (eg. https://...) # paths (eg. https://...)
html_css_files = [ html_css_files = ["css/custom.css"]
'css/custom.css'
]
# -- Breathe configuration --------------------------------------------------- # -- Breathe configuration ---------------------------------------------------
def configureDoxyfile(input_dir, output_dir): def configureDoxyfile(input_dir, output_dir):
with open('Doxyfile.in', 'r') as file: with open("Doxyfile.in", "r") as file:
filedata = file.read() filedata = file.read()
filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir) filedata = filedata.replace("@DOXYGEN_INPUT_DIR@", input_dir)
filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir) filedata = filedata.replace("@DOXYGEN_OUTPUT_DIR@", output_dir)
with open('Doxyfile', 'w') as file: with open("Doxyfile", "w") as file:
file.write(filedata) file.write(filedata)
# Check if we're running on Read the Docs' servers # Check if we're running on Read the Docs' servers
read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True"
# This should be a dictionary in which the keys are project names and the values # 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. # are paths to the folder containing the doxygen output for that project.
breathe_projects = {} breathe_projects = {}
if read_the_docs_build: if read_the_docs_build:
input_dir = '../src' input_dir = "../src"
output_dir = 'build' output_dir = "build"
configureDoxyfile(input_dir, output_dir) configureDoxyfile(input_dir, output_dir)
subprocess.call('doxygen', shell=True) subprocess.call("doxygen", shell=True)
breathe_projects['mp-units'] = output_dir + '/xml' breathe_projects["mp-units"] = output_dir + "/xml"
# This should match one of the keys in the breathe_projects dictionary and # 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 # indicates which project should be used when the project is not specified on
# the directive. # the directive.
breathe_default_project = 'mp-units' breathe_default_project = "mp-units"
# Allows you to specify domains for particular files according to their extension. # Allows you to specify domains for particular files according to their extension.
breathe_domain_by_extension = {"h" : "cpp"} breathe_domain_by_extension = {"h": "cpp"}
# Provides the directive flags that should be applied to all directives which # Provides the directive flags that should be applied to all directives which
# take :members:, :private-members: and :undoc-members: options. By default, # take :members:, :private-members: and :undoc-members: options. By default,
# this is set to an empty list, which means no members are displayed. # this is set to an empty list, which means no members are displayed.
breathe_default_members = ('members', ) breathe_default_members = ("members",)

View File

@@ -40,38 +40,22 @@ of a `scaled_unit` class template:
left to right direction left to right direction
package Unit <<Frame>> [[../../framework/units.html]] { package Unit <<Frame>> [[../../framework/units.html]] {
abstract prefix_family [[../../framework/units.html#prefixed-unit]]
abstract no_prefix [[../../framework/units.html#named-scaled-units]]
abstract prefix<PrefixFamily, Symbol, Ratio> [[../../framework/units.html#prefixed-unit]]
prefix_family <|-- no_prefix
prefix_family <.. prefix
' prefix_family <.. named_unit
' prefix_family <.. named_scaled_unit
' prefix_family <.. named_derived_unit
' prefix_family <.. alias_unit
' prefix <.. prefixed_unit
' prefix <.. prefixed_alias_unit
abstract scaled_unit<UnitRatio, Unit> abstract scaled_unit<UnitRatio, Unit>
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]] abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
abstract alias_unit<Unit, Symbol, PrefixFamily> [[../../framework/units.html#aliased-units]] abstract alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
abstract named_derived_unit<Dimension, Symbol, PrefixFamily, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]] abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract derived_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 prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
abstract named_scaled_unit<Symbol, PrefixFamily, Ratio, Unit> [[../../framework/units.html#named-scaled-units]] abstract named_scaled_unit<Symbol, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
abstract named_unit<Symbol, PrefixFamily> [[../../framework/units.html#base-units]] abstract named_unit<Symbol> [[../../framework/units.html#base-units]]
abstract unit [[../../framework/units.html#derived-unnamed-units]]
scaled_unit <|-- unit
scaled_unit <|-- named_unit scaled_unit <|-- named_unit
scaled_unit <|-- named_scaled_unit scaled_unit <|-- named_scaled_unit
scaled_unit <|-- prefixed_unit scaled_unit <|-- prefixed_unit
scaled_unit <|-- derived_unit scaled_unit <|-- derived_unit
scaled_unit <|-- named_derived_unit scaled_unit <|-- derived_scaled_unit
scaled_unit <|-- alias_unit scaled_unit <|-- alias_unit
scaled_unit <|-- prefixed_alias_unit scaled_unit <|-- prefixed_alias_unit
} }
@@ -191,14 +175,11 @@ Those units are the scaled versions of a time dimension's base unit,
namely second. Those can be defined easily in the library using namely second. Those can be defined easily in the library using
`named_scaled_unit` class template:: `named_scaled_unit` class template::
struct minute : named_scaled_unit<minute, "min", no_prefix, ratio(60), second> {}; struct minute : named_scaled_unit<minute, "min", ratio(60), second> {};
struct hour : named_scaled_unit<hour, "h", no_prefix, ratio(60), minute> {}; struct hour : named_scaled_unit<hour, "h", ratio(60), minute> {};
struct day : named_scaled_unit<hour, "d", no_prefix, ratio(24), hour> {}; struct day : named_scaled_unit<day, "d", ratio(24), hour> {};
where `no_prefix` is a special tag type describing that the library should The `ratio` type used in the definition is really similar to ``std::ratio`` but it takes
not allow to define a new prefixed unit that would use this unit as a
reference ("kilohours" does not have much sense, right?). 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. 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 Another important difference is the fact that the objects of that class are used
as class NTTPs rather then a type template parameter kind. as class NTTPs rather then a type template parameter kind.
@@ -227,28 +208,26 @@ complete list of all the :term:`SI` prefixes supported by the library::
namespace si { namespace si {
struct prefix : prefix_family {}; struct yocto : units::prefix<yocto, "y", ratio(1, 1, -24)> {};
struct zepto : units::prefix<zepto, "z", ratio(1, 1, -21)> {};
struct yocto : units::prefix<yocto, prefix, "y", ratio(1, 1, -24)> {}; struct atto : units::prefix<atto, "a", ratio(1, 1, -18)> {};
struct zepto : units::prefix<zepto, prefix, "z", ratio(1, 1, -21)> {}; struct femto : units::prefix<femto, "f", ratio(1, 1, -15)> {};
struct atto : units::prefix<atto, prefix, "a", ratio(1, 1, -18)> {}; struct pico : units::prefix<pico, "p", ratio(1, 1, -12)> {};
struct femto : units::prefix<femto, prefix, "f", ratio(1, 1, -15)> {}; struct nano : units::prefix<nano, "n", ratio(1, 1, -9)> {};
struct pico : units::prefix<pico, prefix, "p", ratio(1, 1, -12)> {}; struct micro : units::prefix<micro, ", ratio(1, 1, -6)> {};
struct nano : units::prefix<nano, prefix, "n", ratio(1, 1, -9)> {}; struct milli : units::prefix<milli, "m", ratio(1, 1, -3)> {};
struct micro : units::prefix<micro, prefix, "µ", ratio(1, 1, -6)> {}; struct centi : units::prefix<centi, "c", ratio(1, 1, -2)> {};
struct milli : units::prefix<milli, prefix, "m", ratio(1, 1, -3)> {}; struct deci : units::prefix<deci, "d", ratio(1, 1, -1)> {};
struct centi : units::prefix<centi, prefix, "c", ratio(1, 1, -2)> {}; struct deca : units::prefix<deca, "da",ratio(1, 1, 1)> {};
struct deci : units::prefix<deci, prefix, "d", ratio(1, 1, -1)> {}; struct hecto : units::prefix<hecto, "h", ratio(1, 1, 2)> {};
struct deca : units::prefix<deca, prefix, "da", ratio(1, 1, 1)> {}; struct kilo : units::prefix<kilo, "k", ratio(1, 1, 3)> {};
struct hecto : units::prefix<hecto, prefix, "h", ratio(1, 1, 2)> {}; struct mega : units::prefix<mega, "M", ratio(1, 1, 6)> {};
struct kilo : units::prefix<kilo, prefix, "k", ratio(1, 1, 3)> {}; struct giga : units::prefix<giga, "G", ratio(1, 1, 9)> {};
struct mega : units::prefix<mega, prefix, "M", ratio(1, 1, 6)> {}; struct tera : units::prefix<tera, "T", ratio(1, 1, 12)> {};
struct giga : units::prefix<giga, prefix, "G", ratio(1, 1, 9)> {}; struct peta : units::prefix<peta, "P", ratio(1, 1, 15)> {};
struct tera : units::prefix<tera, prefix, "T", ratio(1, 1, 12)> {}; struct exa : units::prefix<exa, "E", ratio(1, 1, 18)> {};
struct peta : units::prefix<peta, prefix, "P", ratio(1, 1, 15)> {}; struct zetta : units::prefix<zetta, "Z", ratio(1, 1, 21)> {};
struct exa : units::prefix<exa, prefix, "E", ratio(1, 1, 18)> {}; struct yotta : units::prefix<yotta, "Y", ratio(1, 1, 24)> {};
struct zetta : units::prefix<zetta, prefix, "Z", ratio(1, 1, 21)> {};
struct yotta : units::prefix<yotta, prefix, "Y", ratio(1, 1, 24)> {};
} }
@@ -257,14 +236,12 @@ domain::
namespace iec80000 { namespace iec80000 {
struct binary_prefix : prefix_family {}; struct kibi : units::prefix<kibi, "Ki", ratio( 1'024)> {};
struct mebi : units::prefix<mebi, "Mi", ratio( 1'048'576)> {};
struct kibi : units::prefix<kibi, binary_prefix, "Ki", ratio( 1'024)> {}; struct gibi : units::prefix<gibi, "Gi", ratio( 1'073'741'824)> {};
struct mebi : units::prefix<mebi, binary_prefix, "Mi", ratio( 1'048'576)> {}; struct tebi : units::prefix<tebi, "Ti", ratio( 1'099'511'627'776)> {};
struct gibi : units::prefix<gibi, binary_prefix, "Gi", ratio( 1'073'741'824)> {}; struct pebi : units::prefix<pebi, "Pi", ratio( 1'125'899'906'842'624)> {};
struct tebi : units::prefix<tebi, binary_prefix, "Ti", ratio( 1'099'511'627'776)> {}; struct exbi : units::prefix<exbi, "Ei", ratio(1'152'921'504'606'846'976)> {};
struct pebi : units::prefix<pebi, binary_prefix, "Pi", ratio( 1'125'899'906'842'624)> {};
struct exbi : units::prefix<exbi, binary_prefix, "Ei", ratio(1'152'921'504'606'846'976)> {};
} }
@@ -338,7 +315,7 @@ will result in a different unnamed unit symbol:
where ``kilogram_metre_per_second`` is defined as:: where ``kilogram_metre_per_second`` is defined as::
struct kilogram_metre_per_second : unit<kilogram_metre_per_second> {}; struct kilogram_metre_per_second : derived_unit<kilogram_metre_per_second> {};
However, the easiest way to define momentum is just to use the However, the easiest way to define momentum is just to use the
``si::dim_speed`` derived dimension in the recipe: ``si::dim_speed`` derived dimension in the recipe:
@@ -385,12 +362,12 @@ ratio in reference to the "metre per second":
Whichever, we choose there will always be someone not happy with our choice. Whichever, we choose there will always be someone not happy with our choice.
Thanks to a `derived_unit` class template provided by the library this problem 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:: does not exist at all. With it ``si::kilometre_per_hour`` can be defined as::
namespace si { namespace si {
struct kilometre_per_hour : derived_unit<kilometre_per_hour, dim_speed, kilometre, hour> {}; struct kilometre_per_hour : derived_scaled_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
} }
@@ -400,7 +377,7 @@ by him/her-self::
namespace si::fps { namespace si::fps {
struct knot : named_derived_unit<knot, dim_speed, "knot", no_prefix, nautical_mile, hour> {}; struct knot : named_derived_unit<knot, dim_speed, "knot", nautical_mile, hour> {};
} }

View File

@@ -8,10 +8,6 @@ Concepts
All names defined in this chapter reside in the :any:`units` namespace unless All names defined in this chapter reside in the :any:`units` namespace unless
specified otherwise. specified otherwise.
.. concept:: template<typename T> PrefixFamily
A concept matching a prefix family. Satisfied by all types derived from :class:`prefix_family`.
.. concept:: template<typename T> Prefix .. concept:: template<typename T> Prefix
A concept matching a symbol prefix. Satisfied by all instantiations of :struct:`prefix`. A concept matching a symbol prefix. Satisfied by all instantiations of :struct:`prefix`.
@@ -44,6 +40,11 @@ Concepts
A concept matching all unit types in the library. Satisfied by all unit types derived A concept matching all unit types in the library. Satisfied by all unit types derived
from the instantiation of :class:`scaled_unit`. 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 U, typename D> UnitOf .. concept:: template<typename U, typename D> UnitOf
A concept matching only units of a specified dimension. Satisfied by all unit types that A concept matching only units of a specified dimension. Satisfied by all unit types that

View File

@@ -1,11 +1,5 @@
Prefixes Prefixes
======== ========
.. doxygenstruct:: units::prefix_family
:members:
.. doxygenstruct:: units::no_prefix
:members:
.. doxygenstruct:: units::prefix .. doxygenstruct:: units::prefix
:members: :members:

View File

@@ -4,9 +4,6 @@ Units
.. doxygenstruct:: units::scaled_unit .. doxygenstruct:: units::scaled_unit
:members: :members:
.. doxygenstruct:: units::unit
:members:
.. doxygenstruct:: units::named_unit .. doxygenstruct:: units::named_unit
:members: :members:
@@ -19,7 +16,7 @@ Units
.. doxygenstruct:: units::derived_unit .. doxygenstruct:: units::derived_unit
:members: :members:
.. doxygenstruct:: units::named_derived_unit .. doxygenstruct:: units::derived_scaled_unit
:members: :members:
.. doxygenstruct:: units::alias_unit .. doxygenstruct:: units::alias_unit

View File

@@ -294,7 +294,7 @@ library release the following steps may be performed:
mkdir my_project/build && cd my_project/build mkdir my_project/build && cd my_project/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
@@ -345,7 +345,7 @@ differences:
mkdir my_project/build && cd my_project/build mkdir my_project/build && cd my_project/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
@@ -360,7 +360,7 @@ to find it, it is enough to perform the following steps:
mkdir units/build && cd units/build mkdir units/build && cd units/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --install . --prefix <install_dir> cmake --install . --prefix <install_dir>
@@ -392,7 +392,7 @@ step with the CMake build:
.. code-block:: shell .. code-block:: shell
# ... # ...
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
ctest ctest

View File

@@ -22,7 +22,7 @@ Defining a New Unit
My working desk is of ``180 cm x 60 cm`` which gives an area of ``0.3 m²``. I would like to My working desk is of ``180 cm x 60 cm`` which gives an area of ``0.3 m²``. I would like to
make it a unit of area for my project:: make it a unit of area for my project::
struct desk : named_scaled_unit<desk, "desk", no_prefix, ratio(3, 10), si::square_metre> {}; struct desk : named_scaled_unit<desk, "desk", ratio(3, 10), si::square_metre> {};
With the above I can define a quantity with the area of ``2 desks``:: With the above I can define a quantity with the area of ``2 desks``::
@@ -56,28 +56,22 @@ In case I would like to check how much area ``6 desks`` take in SI units::
Enabling a Unit for Prefixing Enabling a Unit for Prefixing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In case I decide it is reasonable to express my desks with SI prefixes the only thing I have In case I decide it is reasonable to express my desks with SI prefixes, I can define
to change in the above code is to replace `no_prefix` with `isq::si::prefix`:: a new unit named ``kilodesk``::
struct desk : named_scaled_unit<desk, "desk", si::prefix, ratio(3, 10), si::square_metre> {};
Now I can define a new unit named ``kilodesk``::
struct kilodesk : prefixed_unit<kilodesk, si::kilo, desk> {}; struct kilodesk : prefixed_unit<kilodesk, si::kilo, desk> {};
static_assert(3_d * 1000 == si::area<kilodesk>(3)); static_assert(3_d * 1000 == si::area<kilodesk>(3));
But maybe SI prefixes are not good for me. Maybe I always pack ``6`` desks into one package But maybe SI prefixes are not good for me. Maybe I always pack ``6`` desks into one package
for shipment and ``40`` such packages fit into my lorry. To express this with prefixes a new for shipment and ``40`` such packages fit into my lorry. To express this new prefix definitions
prefix family and prefixes are needed:: are needed::
struct shipping_prefix : prefix_family {}; struct package : prefix<package, "pkg", ratio(6)> {};
struct lorry : prefix<lorry, "lorry", ratio(6 * 40)> {};
struct package : prefix<package, shipping_prefix, "pkg", ratio(6)> {};
struct lorry : prefix<lorry, shipping_prefix, "lorry", ratio(6 * 40)> {};
Now we can use it for our unit:: Now we can use it for our unit::
struct desk : named_scaled_unit<desk, "desk", shipping_prefix, ratio(3, 10), si::square_metre> {}; struct desk : named_scaled_unit<desk, "desk", ratio(3, 10), si::square_metre> {};
struct packagedesk : prefixed_unit<packagedesk, package, desk> {}; struct packagedesk : prefixed_unit<packagedesk, package, desk> {};
struct lorrydesk : prefixed_unit<lorrydesk, lorry, desk> {}; struct lorrydesk : prefixed_unit<lorrydesk, lorry, desk> {};
@@ -111,14 +105,14 @@ rate of wood during production I need to define a new derived dimension together
coherent unit:: coherent unit::
// coherent unit must apply to the system rules (in this case SI) // coherent unit must apply to the system rules (in this case SI)
struct square_metre_per_second : unit<square_metre_per_second> {}; struct square_metre_per_second : derived_unit<square_metre_per_second> {};
// new derived dimensions // new derived dimensions
struct dim_desk_rate : derived_dimension<dim_desk_rate, square_metre_per_second, struct dim_desk_rate : derived_dimension<dim_desk_rate, square_metre_per_second,
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {}; exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
// our unit of interest for a new derived dimension // our unit of interest for a new derived dimension
struct desk_per_hour : derived_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {}; struct desk_per_hour : derived_scaled_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {};
// a quantity of our dimension // a quantity of our dimension
template<UnitOf<dim_desk_rate> U, Representation Rep = double> template<UnitOf<dim_desk_rate> U, Representation Rep = double>
@@ -147,7 +141,7 @@ a customer's office I would need a unit called ``person_per_desk`` of a new deri
dimension. However, our library does not know what a ``person`` is. For this I need to dimension. However, our library does not know what a ``person`` is. For this I need to
define a new base dimension, its units, quantity helper, concept, and UDLs:: define a new base dimension, its units, quantity helper, concept, and UDLs::
struct person : named_unit<person, "person", no_prefix> {}; struct person : named_unit<person, "person"> {};
struct dim_people : base_dimension<"people", person> {}; struct dim_people : base_dimension<"people", person> {};
template<UnitOf<dim_people> U, Representation Rep = double> template<UnitOf<dim_people> U, Representation Rep = double>
@@ -162,12 +156,12 @@ define a new base dimension, its units, quantity helper, concept, and UDLs::
With the above we can now define a new derived dimension:: With the above we can now define a new derived dimension::
struct person_per_square_metre : unit<person_per_square_metre> {}; struct person_per_square_metre : derived_unit<person_per_square_metre> {};
struct dim_occupancy_rate : derived_dimension<dim_occupancy_rate, person_per_square_metre, struct dim_occupancy_rate : derived_dimension<dim_occupancy_rate, person_per_square_metre,
exponent<dim_people, 1>, exponent<dim_people, 1>,
exponent<si::dim_area, -1>> {}; exponent<si::dim_area, -1>> {};
struct person_per_desk : derived_unit<person_per_desk, dim_occupancy_rate, person, desk> {}; struct person_per_desk : derived_scaled_unit<person_per_desk, dim_occupancy_rate, person, desk> {};
template<UnitOf<dim_occupancy_rate> U, Representation Rep = double> template<UnitOf<dim_occupancy_rate> U, Representation Rep = double>
using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>; using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>;
@@ -211,8 +205,8 @@ Such units do not share their references with base units of other systems:
namespace fps { namespace fps {
struct foot : named_unit<foot, "ft", no_prefix> {}; struct foot : named_unit<foot, "ft"> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {}; struct yard : named_scaled_unit<yard, "yd", ratio(3), foot> {};
struct dim_length : base_dimension<"L", foot> {}; struct dim_length : base_dimension<"L", foot> {};
@@ -231,7 +225,7 @@ different systems:
namespace si { namespace si {
struct metre : named_unit<metre, "m", units::isq::si::prefix> {}; struct metre : named_unit<metre, "m"> {};
struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {}; struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {};
struct dim_length : base_dimension<"L", metre> {}; struct dim_length : base_dimension<"L", metre> {};
@@ -241,8 +235,8 @@ different systems:
namespace fps { namespace fps {
struct foot : named_scaled_unit<foot, "ft", no_prefix, ratio(3'048, 1'000, -1), metre> {}; struct foot : named_scaled_unit<foot, "ft", ratio(3'048, 1'000, -1), metre> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {}; struct yard : named_scaled_unit<yard, "yd", ratio(3), foot> {};
struct dim_length : base_dimension<"L", foot> {}; struct dim_length : base_dimension<"L", foot> {};
@@ -300,7 +294,7 @@ the library always keeps the ratio relative to the primary reference unit
which in this case is ``si::metre``. This results in much bigger ratios which in this case is ``si::metre``. This results in much bigger ratios
and in case of some units may result with a problem of limited resolution and in case of some units may result with a problem of limited resolution
of ``std::int64_t`` used to store numerator, denominator, and exponent of ``std::int64_t`` used to store numerator, denominator, and exponent
values of ratio. For example the ``si::fps::qubic_foot`` already has the values of ratio. For example the ``si::fps::cubic_foot`` already has the
ratio of ``ratio{55306341, 1953125, -3}``. In case of more complicated ratio of ``ratio{55306341, 1953125, -3}``. In case of more complicated
conversion ratio we can overflow `ratio` and get a compile-time error. conversion ratio we can overflow `ratio` and get a compile-time error.
In such a situation the standalone system may be a better choice here. In such a situation the standalone system may be a better choice here.

View File

@@ -11,7 +11,7 @@ enough to be used with other Linear Algebra libraries existing on the market.
All of the examples provided in this chapter refer to the official proposal of the All of the examples provided in this chapter refer to the official proposal of the
Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_ Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21/tree/master/include>`_ and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21/tree/master/include>`_
or `Conan <https://twonington.jfrog.io/artifactory/api/conan/conan-oss>`_. or `Conan <https://conan.io/center/wg21-linear_algebra>`_.
Also, to simplify the examples all of them assume:: Also, to simplify the examples all of them assume::
using namespace std::math; using namespace std::math;

View File

@@ -22,6 +22,9 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.2)
add_library(example_utils INTERFACE)
target_include_directories(example_utils INTERFACE include)
# #
# add_example(target <depependencies>...) # add_example(target <depependencies>...)
# #

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h> #include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h> #include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -68,7 +69,7 @@ void print_details(std::string_view description, const Ship& ship)
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass)) << STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", << STD_FMT::format("{:20} : {}\n", "speed",
fmt_line<si::fps::speed::knot<>, si::speed::km_per_h<>>(ship.speed)) fmt_line<si::international::speed::kn<>, si::speed::km_per_h<>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power)) << STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns", << STD_FMT::format("{:20} : {}\n", "main guns",
fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns)) fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns))
@@ -101,7 +102,7 @@ int main()
auto iowa = Ship{.length{ft<>(860.)}, auto iowa = Ship{.length{ft<>(860.)},
.draft{ft<>(37.) + in<>(2.)}, .draft{ft<>(37.) + in<>(2.)},
.beam{ft<>(108.) + in<>(2.)}, .beam{ft<>(108.) + in<>(2.)},
.speed{knot<>(33)}, .speed{international::kn<>(33)},
.mass{lton<>(57'540)}, .mass{lton<>(57'540)},
.mainGuns{in<>(16)}, .mainGuns{in<>(16)},
.shellMass{lb<>(2700)}, .shellMass{lb<>(2700)},
@@ -112,7 +113,7 @@ int main()
auto kgv = Ship{.length{ft<>(745.1)}, auto kgv = Ship{.length{ft<>(745.1)},
.draft{ft<>(33.) + in<>(7.5)}, .draft{ft<>(33.) + in<>(7.5)},
.beam{ft<>(103.2) + in<>(2.5)}, .beam{ft<>(103.2) + in<>(2.5)},
.speed{knot<>(28.3)}, .speed{international::kn<>(28.3)},
.mass{lton<>(42'245)}, .mass{lton<>(42'245)},
.mainGuns{in<>(14)}, .mainGuns{in<>(14)},
.shellMass{lb<>(1'590)}, .shellMass{lb<>(1'590)},

View File

@@ -32,8 +32,8 @@ using namespace units;
namespace fps { namespace fps {
struct foot : named_unit<foot, "ft", no_prefix> {}; struct foot : named_unit<foot, "ft"> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, as_magnitude<3>(), foot> {}; struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {}; struct dim_length : base_dimension<"L", foot> {};
@@ -44,7 +44,7 @@ using length = quantity<dim_length, U, Rep>;
namespace si { namespace si {
struct metre : named_unit<metre, "m", units::isq::si::prefix> {}; struct metre : named_unit<metre, "m"> {};
struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {}; struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {};
struct dim_length : base_dimension<"L", metre> {}; struct dim_length : base_dimension<"L", metre> {};
@@ -54,8 +54,8 @@ using length = quantity<dim_length, U, Rep>;
namespace fps { namespace fps {
struct foot : named_scaled_unit<foot, "ft", no_prefix, as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {}; struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, as_magnitude<3>(), foot> {}; struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {}; struct dim_length : base_dimension<"L", foot> {};

View File

@@ -22,6 +22,6 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.2)
add_library(glide_computer STATIC geographic.cpp include/geographic.h glide_computer.cpp include/glide_computer.h) add_library(glide_computer STATIC include/geographic.h glide_computer.cpp include/glide_computer.h)
target_link_libraries(glide_computer PRIVATE mp-units::core-fmt PUBLIC mp-units::si) target_link_libraries(glide_computer PRIVATE mp-units::core-fmt PUBLIC mp-units::si example_utils)
target_include_directories(glide_computer PUBLIC include) target_include_directories(glide_computer PUBLIC include)

View File

@@ -1,64 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "geographic.h"
#include <cmath>
#include <numbers>
#include <type_traits>
namespace {
using namespace units::isq::si;
inline constexpr length<kilometre> earth_radius(6371);
} // namespace
namespace geographic {
distance spherical_distance(position from, position to)
{
using rep = std::common_type_t<latitude::value_type, longitude::value_type>;
constexpr auto p = std::numbers::pi_v<rep> / 180;
const auto lat1 = from.lat.value() * p;
const auto lon1 = from.lon.value() * p;
const auto lat2 = to.lat.value() * p;
const auto lon2 = to.lon.value() * p;
using std::sin, std::cos, std::asin, std::sqrt;
// https://en.wikipedia.org/wiki/Great-circle_distance#Formulae
if constexpr (sizeof(rep) >= 8) {
// spherical law of cosines
const auto central_angle = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1));
// const auto central_angle = 2 * asin(sqrt(0.5 - cos(lat2 - lat1) / 2 + cos(lat1) * cos(lat2) * (1 - cos(lon2 -
// lon1)) / 2));
return distance(earth_radius * central_angle);
} else {
// the haversine formula
const auto sin_lat = sin((lat2 - lat1) / 2);
const auto sin_lon = sin((lon2 - lon1) / 2);
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
return distance(earth_radius * central_angle);
}
}
} // namespace geographic

View File

@@ -22,10 +22,14 @@
#pragma once #pragma once
#include "ranged_representation.h"
#include <units/bits/external/hacks.h>
#include <units/bits/fmt_hacks.h> #include <units/bits/fmt_hacks.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/quantity_kind.h> #include <units/quantity_kind.h>
#include <limits> #include <limits>
#include <numbers>
#include <ostream> #include <ostream>
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
@@ -34,88 +38,95 @@
namespace geographic { namespace geographic {
template<typename Derived, typename Rep> // TODO Change to `angle` dimension in degree unit when the work on magnitudes is done
struct coordinate { template<typename T = double>
using value_type = Rep; using latitude = units::dimensionless<units::one, ranged_representation<T, -90, 90>>;
constexpr explicit coordinate(value_type v) : value_(v) {}
constexpr value_type value() const { return value_; }
auto operator<=>(const coordinate&) const = default;
private:
value_type value_;
};
struct latitude : coordinate<latitude, double> { template<typename T = double>
using coordinate::coordinate; using longitude = units::dimensionless<units::one, ranged_representation<T, -180, 180>>;
};
struct longitude : coordinate<longitude, double> { template<class CharT, class Traits, typename T>
using coordinate::coordinate; std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const latitude<T>& lat)
};
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const latitude& lat)
{ {
if (lat.value() > 0) if (lat.number() > 0)
return os << "N" << lat.value(); return os << "N" << lat.number();
else else
return os << "S" << -lat.value(); return os << "S" << -lat.number();
} }
template<class CharT, class Traits> template<class CharT, class Traits, typename T>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const longitude& lon) std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const longitude<T>& lon)
{ {
if (lon.value() > 0) if (lon.number() > 0)
return os << "E" << lon.value(); return os << "E" << lon.number();
else else
return os << "W" << -lon.value(); return os << "W" << -lon.number();
} }
inline namespace literals { inline namespace literals {
constexpr auto operator"" _N(unsigned long long v) { return latitude(static_cast<latitude::value_type>(v)); } constexpr auto operator"" _N(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
constexpr auto operator"" _N(long double v) { return latitude(static_cast<latitude::value_type>(v)); } constexpr auto operator"" _S(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
constexpr auto operator"" _S(unsigned long long v) { return latitude(-static_cast<latitude::value_type>(v)); } constexpr auto operator"" _E(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
constexpr auto operator"" _S(long double v) { return latitude(-static_cast<latitude::value_type>(v)); } constexpr auto operator"" _W(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
constexpr auto operator"" _E(unsigned long long v) { return longitude(static_cast<longitude::value_type>(v)); } constexpr auto operator"" _N(unsigned long long v)
constexpr auto operator"" _E(long double v) { return longitude(static_cast<longitude::value_type>(v)); } {
constexpr auto operator"" _W(unsigned long long v) { return longitude(-static_cast<longitude::value_type>(v)); } gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
constexpr auto operator"" _W(long double v) { return longitude(-static_cast<longitude::value_type>(v)); } return latitude<std::int64_t>(latitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
}
constexpr auto operator"" _S(unsigned long long v)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
return latitude<std::int64_t>(-latitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
}
constexpr auto operator"" _E(unsigned long long v)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
return longitude<std::int64_t>(longitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
}
constexpr auto operator"" _W(unsigned long long v)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
return longitude<std::int64_t>(-longitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
}
} // namespace literals } // namespace literals
} // namespace geographic } // namespace geographic
template<> template<typename T>
class std::numeric_limits<geographic::latitude> : public numeric_limits<geographic::latitude::value_type> { class std::numeric_limits<geographic::latitude<T>> : public numeric_limits<T> {
static constexpr auto min() noexcept { return geographic::latitude(-90); } static constexpr auto min() noexcept { return geographic::latitude<T>(-90); }
static constexpr auto lowest() noexcept { return geographic::latitude(-90); } static constexpr auto lowest() noexcept { return geographic::latitude<T>(-90); }
static constexpr auto max() noexcept { return geographic::latitude(90); } static constexpr auto max() noexcept { return geographic::latitude<T>(90); }
}; };
template<> template<typename T>
class std::numeric_limits<geographic::longitude> : public numeric_limits<geographic::longitude::value_type> { class std::numeric_limits<geographic::longitude<T>> : public numeric_limits<T> {
static constexpr auto min() noexcept { return geographic::longitude(-180); } static constexpr auto min() noexcept { return geographic::longitude<T>(-180); }
static constexpr auto lowest() noexcept { return geographic::longitude(-180); } static constexpr auto lowest() noexcept { return geographic::longitude<T>(-180); }
static constexpr auto max() noexcept { return geographic::longitude(180); } static constexpr auto max() noexcept { return geographic::longitude<T>(180); }
}; };
template<> template<typename T>
struct STD_FMT::formatter<geographic::latitude> : formatter<geographic::latitude::value_type> { struct STD_FMT::formatter<geographic::latitude<T>> : formatter<T> {
template<typename FormatContext> template<typename FormatContext>
auto format(geographic::latitude lat, FormatContext& ctx) auto format(geographic::latitude<T> lat, FormatContext& ctx)
{ {
STD_FMT::format_to(ctx.out(), "{}", lat.value() > 0 ? 'N' : 'S'); using rep = TYPENAME geographic::latitude<T>::rep;
return formatter<geographic::latitude::value_type>::format(lat.value() > 0 ? lat.value() : -lat.value(), ctx); STD_FMT::format_to(ctx.out(), "{}", lat > rep{0} ? 'N' : 'S');
return formatter<T>::format(lat > rep{0} ? lat.number() : -lat.number(), ctx);
} }
}; };
template<> template<typename T>
struct STD_FMT::formatter<geographic::longitude> : formatter<geographic::longitude::value_type> { struct STD_FMT::formatter<geographic::longitude<T>> : formatter<T> {
template<typename FormatContext> template<typename FormatContext>
auto format(geographic::longitude lon, FormatContext& ctx) auto format(geographic::longitude<T> lon, FormatContext& ctx)
{ {
STD_FMT::format_to(ctx.out(), "{}", lon.value() > 0 ? 'E' : 'W'); using rep = TYPENAME geographic::longitude<T>::rep;
return formatter<geographic::longitude::value_type>::format(lon.value() > 0 ? lon.value() : -lon.value(), ctx); STD_FMT::format_to(ctx.out(), "{}", lon > rep{0} ? 'E' : 'W');
return formatter<T>::format(lon > rep{0} ? lon.number() : -lon.number(), ctx);
} }
}; };
@@ -124,11 +135,41 @@ namespace geographic {
struct horizontal_kind : units::kind<horizontal_kind, units::isq::si::dim_length> {}; struct horizontal_kind : units::kind<horizontal_kind, units::isq::si::dim_length> {};
using distance = units::quantity_kind<horizontal_kind, units::isq::si::kilometre>; using distance = units::quantity_kind<horizontal_kind, units::isq::si::kilometre>;
template<typename T>
struct position { struct position {
latitude lat; latitude<T> lat;
longitude lon; longitude<T> lon;
}; };
distance spherical_distance(position from, position to); template<typename T>
distance spherical_distance(position<T> from, position<T> to)
{
using namespace units::isq::si;
constexpr length<kilometre> earth_radius(6371);
constexpr auto p = std::numbers::pi_v<T> / 180;
const auto lat1_rad = from.lat.number() * p;
const auto lon1_rad = from.lon.number() * p;
const auto lat2_rad = to.lat.number() * p;
const auto lon2_rad = to.lon.number() * p;
using std::sin, std::cos, std::asin, std::acos, std::sqrt;
// https://en.wikipedia.org/wiki/Great-circle_distance#Formulae
if constexpr (sizeof(T) >= 8) {
// spherical law of cosines
const auto central_angle =
acos(sin(lat1_rad) * sin(lat2_rad) + cos(lat1_rad) * cos(lat2_rad) * cos(lon2_rad - lon1_rad));
// const auto central_angle = 2 * asin(sqrt(0.5 - cos(lat2_rad - lat1_rad) / 2 + cos(lat1_rad) * cos(lat2_rad) * (1
// - cos(lon2_rad - lon1_rad)) / 2));
return distance(earth_radius * central_angle);
} else {
// the haversine formula
const auto sin_lat = sin((lat2_rad - lat1_rad) / 2);
const auto sin_lon = sin((lon2_rad - lon1_rad) / 2);
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1_rad) * cos(lat2_rad) * sin_lon * sin_lon));
return distance(earth_radius * central_angle);
}
}
} // namespace geographic } // namespace geographic

View File

@@ -136,7 +136,7 @@ struct weather {
struct waypoint { struct waypoint {
std::string name; std::string name;
geographic::position pos; geographic::position<long double> pos;
altitude alt; altitude alt;
}; };

View File

@@ -0,0 +1,51 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "validated_type.h"
#include <units/bits/external/hacks.h>
#include <algorithm>
#include <type_traits>
template<typename T, auto Min, auto Max>
inline constexpr auto is_in_range = [](const auto& v) { return std::clamp(v, T{Min}, T{Max}) == v; };
template<typename T, auto Min, auto Max>
using is_in_range_t = decltype(is_in_range<T, Min, Max>);
template<typename T, auto Min, auto Max>
class ranged_representation : public validated_type<T, is_in_range_t<T, Min, Max>> {
public:
using validated_type<T, is_in_range_t<T, Min, Max>>::validated_type;
constexpr ranged_representation() : validated_type<T, is_in_range_t<T, Min, Max>>(T{}) {}
[[nodiscard]] constexpr ranged_representation operator-() const { return ranged_representation(-this->value()); }
};
template<typename T, auto Min, auto Max>
struct std::common_type<std::intmax_t, ranged_representation<T, Min, Max>> :
std::type_identity<ranged_representation<std::common_type_t<std::intmax_t, T>, Min, Max>> {};
template<typename T, auto Min, auto Max>
struct std::common_type<ranged_representation<T, Min, Max>, std::intmax_t> :
std::type_identity<ranged_representation<std::common_type_t<T, std::intmax_t>, Min, Max>> {};

View File

@@ -0,0 +1,81 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <gsl/gsl-lite.hpp>
#include <units/bits/external/hacks.h>
#include <utility>
inline constexpr struct validated_tag {
} validated;
template<std::movable T, std::predicate<T> Validator>
class validated_type {
T value_;
public:
using value_type = T;
static constexpr bool validate(const T& value) { return Validator()(value); }
constexpr explicit validated_type(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>)
requires std::copyable<T>
: value_(value)
{
gsl_Expects(validate(value_));
}
constexpr explicit validated_type(T&& value) noexcept(std::is_nothrow_move_constructible_v<T>) :
value_(std::move(value))
{
gsl_Expects(validate(value_));
}
constexpr validated_type(const T& value, validated_tag) noexcept(std::is_nothrow_copy_constructible_v<T>)
requires std::copyable<T>
: value_(value)
{
}
constexpr validated_type(T&& value, validated_tag) noexcept(std::is_nothrow_move_constructible_v<T>) :
value_(std::move(value))
{
}
constexpr explicit(false) operator T() const noexcept(std::is_nothrow_copy_constructible_v<T>)
requires std::copyable<T>
{
return value_;
}
constexpr T& value() & noexcept = delete;
constexpr const T& value() const& noexcept { return value_; }
constexpr T&& value() && noexcept { return std::move(value_); }
constexpr const T&& value() const&& noexcept { return std::move(value_); }
bool operator==(const validated_type&) const
requires std::equality_comparable<T>
= default;
auto operator<=>(const validated_type&) const
requires std::three_way_comparable<T>
= default;
};

View File

@@ -84,7 +84,7 @@ public:
uncertainty_type uncertainty; uncertainty_type uncertainty;
}; };
#if UNITS_COMP_CLANG <= 13 #if UNITS_COMP_CLANG <= 14
template<QuantityOrQuantityPoint QQP, units::Quantity U> template<QuantityOrQuantityPoint QQP, units::Quantity U>
estimation(state<QQP>, U) -> estimation<QQP>; estimation(state<QQP>, U) -> estimation<QQP>;

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232) // TODO Fix when Celsius is properly supported (#232)
namespace units::isq::si { namespace units::isq::si {
struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}, no_prefix> {}; struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}> {};
namespace thermodynamic_temperature_references { namespace thermodynamic_temperature_references {

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232) // TODO Fix when Celsius is properly supported (#232)
namespace units::isq::si { namespace units::isq::si {
struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}, no_prefix> {}; struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}> {};
namespace thermodynamic_temperature_references { namespace thermodynamic_temperature_references {

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232) // TODO Fix when Celsius is properly supported (#232)
namespace units::isq::si { namespace units::isq::si {
struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}, no_prefix> {}; struct degree_celsius : alias_unit<kelvin, basic_symbol_text{"°C", "deg_C"}> {};
namespace thermodynamic_temperature_references { namespace thermodynamic_temperature_references {

View File

@@ -1,113 +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.
#include <units/base_dimension.h>
#include <units/isq/si/prefixes.h>
#include <units/quantity.h>
#include <units/quantity_io.h>
#include <units/unit.h>
#include <iostream>
#include <type_traits>
using namespace units;
namespace fps {
struct foot : named_unit<foot, "ft", no_prefix> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {};
template<UnitOf<dim_length> U, Representation Rep = double>
using length = quantity<dim_length, U, Rep>;
} // namespace fps
namespace si {
struct metre : named_unit<metre, "m", units::isq::si::prefix> {};
struct kilometre : prefixed_unit<kilometre, units::isq::si::kilo, metre> {};
struct dim_length : base_dimension<"L", metre> {};
template<UnitOf<dim_length> U, Representation Rep = double>
using length = quantity<dim_length, U, Rep>;
namespace fps {
struct foot : named_scaled_unit<foot, "ft", no_prefix, as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {};
template<UnitOf<dim_length> U, Representation Rep = double>
using length = quantity<dim_length, U, Rep>;
} // namespace fps
} // namespace si
void conversions()
{
// constexpr auto fps_yard = fps::length<fps::yard>(1.);
// std::cout << quantity_cast<si::kilometre>(fps_yard) << "\n";
constexpr auto si_fps_yard = si::fps::length<si::fps::yard>(1.);
std::cout << quantity_cast<si::kilometre>(si_fps_yard) << "\n";
}
void unknown_dimensions()
{
constexpr auto fps_yard = fps::length<fps::yard>(1.);
constexpr auto fps_area = quantity_cast<unknown_coherent_unit>(fps_yard * fps_yard);
std::cout << fps_yard << "\n";
std::cout << fps_area << "\n";
constexpr auto si_fps_yard = si::fps::length<si::fps::yard>(1.);
constexpr auto si_fps_area = quantity_cast<unknown_coherent_unit>(si_fps_yard * si_fps_yard);
std::cout << si_fps_yard << "\n";
std::cout << si_fps_area << "\n";
}
std::ostream& operator<<(std::ostream& os, const ratio& r)
{
return os << "ratio{" << r.num << ", " << r.den << ", " << r.exp << "}";
}
template<Unit U>
std::ostream& operator<<(std::ostream& os, const U& u)
{
using unit_type = std::remove_cvref_t<decltype(u)>;
return os << as_ratio(unit_type::mag) << " x " << unit_type::reference::symbol.standard();
}
void what_is_your_ratio()
{
std::cout << "fps: " << fps::yard() << "\n";
std::cout << "si::fps: " << si::fps::yard() << "\n";
}
int main()
{
conversions();
unknown_dimensions();
what_is_your_ratio();
}

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h> #include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h> #include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -73,8 +74,9 @@ void print_details(std::string_view description, const Ship& ship)
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "mass", << STD_FMT::format("{:20} : {}\n", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass)) fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", << STD_FMT::format(
fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed)) "{:20} : {}\n", "speed",
fmt_line<si::speed<si::international::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power", << STD_FMT::format("{:20} : {}\n", "power",
fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power)) fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns", << STD_FMT::format("{:20} : {}\n", "main guns",
@@ -108,7 +110,7 @@ int main()
auto iowa = Ship{.length{860._q_ft}, auto iowa = Ship{.length{860._q_ft},
.draft{37._q_ft + 2._q_in}, .draft{37._q_ft + 2._q_in},
.beam{108._q_ft + 2._q_in}, .beam{108._q_ft + 2._q_in},
.speed{33_q_knot}, .speed{si::speed<si::international::knot>{33}},
.mass{57'540_q_lton}, .mass{57'540_q_lton},
.mainGuns{16_q_in}, .mainGuns{16_q_in},
.shellMass{2700_q_lb}, .shellMass{2700_q_lb},
@@ -119,7 +121,7 @@ int main()
auto kgv = Ship{.length{745.1_q_ft}, auto kgv = Ship{.length{745.1_q_ft},
.draft{33._q_ft + 7.5_q_in}, .draft{33._q_ft + 7.5_q_in},
.beam{103.2_q_ft + 2.5_q_in}, .beam{103.2_q_ft + 2.5_q_in},
.speed{28.3_q_knot}, .speed{si::speed<si::international::knot>{28.3}},
.mass{42'245_q_lton}, .mass{42'245_q_lton},
.mainGuns{14_q_in}, .mainGuns{14_q_in},
.shellMass{1'590_q_lb}, .shellMass{1'590_q_lb},

View File

@@ -28,6 +28,7 @@
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/fps/time.h> #include <units/isq/si/fps/time.h>
#include <units/isq/si/fps/volume.h> #include <units/isq/si/fps/volume.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -76,8 +77,9 @@ void print_details(std::string_view description, const Ship& ship)
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "mass", << STD_FMT::format("{:20} : {}\n", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass)) fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", << STD_FMT::format(
fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed)) "{:20} : {}\n", "speed",
fmt_line<si::speed<si::international::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power", << STD_FMT::format("{:20} : {}\n", "power",
fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power)) fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns", << STD_FMT::format("{:20} : {}\n", "main guns",
@@ -112,7 +114,7 @@ int main()
auto iowa = Ship{.length{860. * ft}, auto iowa = Ship{.length{860. * ft},
.draft{37. * ft + 2. * in}, .draft{37. * ft + 2. * in},
.beam{108. * ft + 2. * in}, .beam{108. * ft + 2. * in},
.speed{33 * knot}, .speed{33 * units::isq::si::international::references::kn},
.mass{57'540 * lton}, .mass{57'540 * lton},
.mainGuns{16 * in}, .mainGuns{16 * in},
.shellMass{2700 * lb}, .shellMass{2700 * lb},
@@ -123,7 +125,7 @@ int main()
auto kgv = Ship{.length{745.1 * ft}, auto kgv = Ship{.length{745.1 * ft},
.draft{33. * ft + 7.5 * in}, .draft{33. * ft + 7.5 * in},
.beam{103.2 * ft + 2.5 * in}, .beam{103.2 * ft + 2.5 * in},
.speed{28.3 * knot}, .speed{28.3 * units::isq::si::international::references::kn},
.mass{42'245 * lton}, .mass{42'245 * lton},
.mainGuns{14 * in}, .mainGuns{14 * in},
.shellMass{1'590 * lb}, .shellMass{1'590 * lb},

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
project(mp-units VERSION 0.8.0 LANGUAGES CXX) project(mp-units VERSION 0.8.0 LANGUAGES CXX)
set(projectPrefix UNITS_) set(projectPrefix UNITS_)

View File

@@ -20,14 +20,43 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
function(validate_unparsed module prefix)
if(${prefix}_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}' " "for module '${module}'")
endif()
endfunction()
function(validate_argument_exists module prefix arg)
if(NOT ${prefix}_${arg})
message(FATAL_ERROR "'${arg}' not provided for module '${module}'")
endif()
endfunction()
function(validate_arguments_exists module prefix)
foreach(arg ${ARGN})
validate_argument_exists(${module} ${prefix} ${arg})
endforeach()
endfunction()
# #
# add_units_module(ModuleName <depependencies>...) # add_units_module(ModuleName
# DEPENDENCIES <depependency>...
# HEADERS <header_file>...)
# #
function(add_units_module name) function(add_units_module name)
add_library(mp-units-${name} INTERFACE) # parse arguments
target_link_libraries(mp-units-${name} INTERFACE ${ARGN}) set(multiValues DEPENDENCIES HEADERS)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "${multiValues}")
# validate and process arguments
validate_unparsed(${name} ARG)
validate_arguments_exists(${name} ARG DEPENDENCIES HEADERS)
# define the target for a module
add_library(mp-units-${name} INTERFACE ${ARG_HEADERS})
target_link_libraries(mp-units-${name} INTERFACE ${ARG_DEPENDENCIES})
target_include_directories( target_include_directories(
mp-units-${name} ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> mp-units-${name} ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>

View File

@@ -20,12 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON) option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON)
message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}") message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}")
add_units_module(core-fmt mp-units::core) add_units_module(core-fmt DEPENDENCIES mp-units::core HEADERS include/units/format.h)
target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>) target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>)
if(${projectPrefix}USE_LIBFMT) if(${projectPrefix}USE_LIBFMT)

View File

@@ -20,6 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(core-io mp-units::core) add_units_module(core-io DEPENDENCIES mp-units::core HEADERS include/units/quantity_io.h)

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
# core library options # core library options
set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode") set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode")
@@ -34,7 +34,33 @@ include(CheckLibcxxInUse)
check_libcxx_in_use(${projectPrefix}LIBCXX) check_libcxx_in_use(${projectPrefix}LIBCXX)
# core library definition # core library definition
add_library(mp-units-core INTERFACE) add_library(
mp-units-core
INTERFACE
include/units/base_dimension.h
include/units/chrono.h
include/units/concepts.h
include/units/customization_points.h
include/units/derived_dimension.h
include/units/exponent.h
include/units/generic/angle.h
include/units/generic/dimensionless.h
include/units/kind.h
include/units/magnitude.h
include/units/math.h
include/units/point_origin.h
include/units/prefix.h
include/units/quantity.h
include/units/quantity_cast.h
include/units/quantity_kind.h
include/units/quantity_point.h
include/units/quantity_point_kind.h
include/units/random.h
include/units/ratio.h
include/units/reference.h
include/units/symbol_text.h
include/units/unit.h
)
target_compile_features(mp-units-core INTERFACE cxx_std_20) target_compile_features(mp-units-core INTERFACE cxx_std_20)
target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite) target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
target_include_directories( target_include_directories(

View File

@@ -50,8 +50,7 @@ namespace units {
* @tparam Symbol an unique identifier of the base dimension used to provide dimensional analysis support * @tparam Symbol an unique identifier of the base dimension used to provide dimensional analysis support
* @tparam U a base unit to be used for this base dimension * @tparam U a base unit to be used for this base dimension
*/ */
template<basic_fixed_string Symbol, Unit U> template<basic_fixed_string Symbol, NamedUnit U>
requires U::is_named
struct base_dimension { struct base_dimension {
static constexpr auto symbol = Symbol; ///< Unique base dimension identifier static constexpr auto symbol = Symbol; ///< Unique base dimension identifier
using base_unit = U; ///< Base unit adopted for this dimension using base_unit = U; ///< Base unit adopted for this dimension

View File

@@ -37,25 +37,14 @@
namespace units { namespace units {
// PrefixFamily
struct prefix_family;
/**
* @brief A concept matching a prefix family
*
* Satisfied by all types derived from `prefix_family`
*/
template<typename T>
concept PrefixFamily = std::derived_from<T, prefix_family>;
// Prefix // Prefix
namespace detail { namespace detail {
template<PrefixFamily PF, ratio R> template<ratio R>
struct prefix_base; struct prefix_base;
template<PrefixFamily PF, ratio R> template<ratio R>
void to_prefix_base(const volatile prefix_base<PF, R>*); void to_prefix_base(const volatile prefix_base<R>*);
} // namespace detail } // namespace detail
@@ -87,9 +76,18 @@ void to_base_scaled_unit(const volatile scaled_unit<M, U>*);
template<typename T> template<typename T>
concept Unit = requires(T* t) { detail::to_base_scaled_unit(t); }; concept Unit = requires(T* t) { detail::to_base_scaled_unit(t); };
namespace detail {
template<typename>
inline constexpr bool is_named = false;
}
template<typename T>
concept NamedUnit = Unit<T> && detail::is_named<T>;
// BaseDimension // BaseDimension
template<basic_fixed_string Symbol, Unit U> template<basic_fixed_string Symbol, NamedUnit U>
requires U::is_named
struct base_dimension; struct base_dimension;
namespace detail { namespace detail {

View File

@@ -34,7 +34,7 @@ inline constexpr bool same_scaled_units = false;
template<typename... Es, Unit... Us> template<typename... Es, Unit... Us>
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...); inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
// derived_unit // derived_scaled_unit
template<Unit... Us, typename... Es> template<Unit... Us, typename... Es>
constexpr Magnitude auto derived_mag(exponent_list<Es...>) constexpr Magnitude auto derived_mag(exponent_list<Es...>)
@@ -44,6 +44,6 @@ constexpr Magnitude auto derived_mag(exponent_list<Es...>)
} }
template<DerivedDimension D, Unit... Us> template<DerivedDimension D, Unit... Us>
using derived_unit = scaled_unit<derived_mag<Us...>(typename D::recipe()), typename D::coherent_unit::reference>; using derived_scaled_unit = scaled_unit<derived_mag<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
} // namespace units::detail } // namespace units::detail

View File

@@ -26,6 +26,7 @@
#include <units/bits/external/text_tools.h> #include <units/bits/external/text_tools.h>
#include <units/derived_dimension.h> #include <units/derived_dimension.h>
#include <units/prefix.h> #include <units/prefix.h>
#include <units/unit.h>
namespace units::detail { namespace units::detail {
@@ -57,28 +58,19 @@ constexpr auto ratio_text()
} }
} }
template<ratio R, typename PrefixFamily, std::size_t SymbolLen> template<Unit U, ratio R, std::size_t SymbolLen>
constexpr auto prefix_or_ratio_text() constexpr auto prefix_or_ratio_text()
{ {
if constexpr (R.num == 1 && R.den == 1 && R.exp == 0) { if constexpr (R.num == 1 && R.den == 1 && R.exp == 0) {
// no ratio/prefix // no ratio/prefix
return basic_fixed_string(""); return basic_fixed_string("");
} else { } else {
if constexpr (!is_same_v<PrefixFamily, no_prefix>) { // try to form a prefix
// try to form a prefix using prefix = downcast<detail::prefix_base<R>>;
using prefix = downcast<detail::prefix_base<PrefixFamily, R>>;
if constexpr (!is_same_v<prefix, prefix_base<PrefixFamily, R>>) { if constexpr (can_be_prefixed<U> && !is_same_v<prefix, prefix_base<R>>) {
// print as a prefixed unit // print as a prefixed unit
return prefix::symbol; return prefix::symbol;
} else {
// print as a ratio of the coherent unit
constexpr auto txt = ratio_text<R>();
if constexpr (SymbolLen > 0 && txt.standard().size() > 0)
return txt + basic_fixed_string(" ");
else
return txt;
}
} else { } else {
// print as a ratio of the coherent unit // print as a ratio of the coherent unit
constexpr auto txt = ratio_text<R>(); constexpr auto txt = ratio_text<R>();
@@ -110,7 +102,7 @@ template<Exponent Exp>
constexpr auto exponent_list_with_named_units(Exp) constexpr auto exponent_list_with_named_units(Exp)
{ {
using dim = TYPENAME Exp::dimension; using dim = TYPENAME Exp::dimension;
if constexpr (dimension_unit<dim>::is_named) { if constexpr (NamedUnit<dimension_unit<dim>>) {
return exponent_list<Exp>(); return exponent_list<Exp>();
} else { } else {
using recipe = TYPENAME dim::recipe; using recipe = TYPENAME dim::recipe;
@@ -147,21 +139,16 @@ constexpr auto unit_text()
// print as a prefix or ratio of a coherent unit // print as a prefix or ratio of a coherent unit
using coherent_unit = dimension_unit<Dim>; using coherent_unit = dimension_unit<Dim>;
if constexpr (has_symbol<coherent_unit>) { constexpr auto symbol_text = []() {
// use predefined coherent unit symbol if constexpr (has_symbol<coherent_unit>)
constexpr auto symbol_text = coherent_unit::symbol; return coherent_unit::symbol;
constexpr auto prefix_txt = else
prefix_or_ratio_text<as_ratio(U::mag / coherent_unit::mag), typename U::reference::prefix_family, return derived_dimension_unit_text<Dim>();
symbol_text.standard().size()>(); }();
return prefix_txt + symbol_text;
} else { constexpr auto prefix_txt =
// use derived dimension ingredients to create a unit symbol prefix_or_ratio_text<U, as_ratio(U::mag / coherent_unit::mag), symbol_text.standard().size()>();
constexpr auto symbol_text = derived_dimension_unit_text<Dim>(); return prefix_txt + symbol_text;
constexpr auto prefix_txt =
prefix_or_ratio_text<as_ratio(U::mag / coherent_unit::mag), typename U::reference::prefix_family,
symbol_text.standard().size()>();
return prefix_txt + symbol_text;
}
} }
} }

View File

@@ -32,7 +32,7 @@
namespace units { namespace units {
struct radian : named_unit<radian, "rad", isq::si::prefix> {}; struct radian : named_unit<radian, "rad"> {};
template<Unit U = radian> template<Unit U = radian>
struct dim_angle : base_dimension<"A", U> {}; struct dim_angle : base_dimension<"A", U> {};

View File

@@ -30,8 +30,8 @@
namespace units { namespace units {
struct one : named_unit<one, "", no_prefix> {}; struct one : derived_unit<one> {};
struct percent : named_scaled_unit<percent, "%", no_prefix, as_magnitude<ratio(1, 100)>(), one> {}; struct percent : named_scaled_unit<percent, "%", as_magnitude<ratio(1, 100)>(), one> {};
/** /**
* @brief Dimension one * @brief Dimension one

View File

@@ -32,26 +32,10 @@
namespace units { namespace units {
/**
* @brief The base for all prefix families
*
* Every prefix family should inherit from this type to satisfy PrefixFamily concept.
*/
struct prefix_family {};
/**
* @brief No prefix possible for the unit
*
* This is a special prefix type tag specifying that the unit can not be scaled with any kind
* of the prefix.
*/
struct no_prefix : prefix_family {};
namespace detail { namespace detail {
template<PrefixFamily PF, ratio R> template<ratio R>
struct prefix_base : downcast_base<prefix_base<PF, R>> { struct prefix_base : downcast_base<prefix_base<R>> {
using prefix_family = PF;
static constexpr Magnitude auto mag = as_magnitude<R>(); static constexpr Magnitude auto mag = as_magnitude<R>();
}; };
@@ -64,17 +48,14 @@ struct prefix_base : downcast_base<prefix_base<PF, R>> {
* - when defining a prefixed_unit its ratio is used to scale the reference unit and its * - when defining a prefixed_unit its ratio is used to scale the reference unit and its
* symbol is used to prepend to the symbol of referenced unit * symbol is used to prepend to the symbol of referenced unit
* - when printing the symbol of a scaled unit that was not predefined by the user but its * - when printing the symbol of a scaled unit that was not predefined by the user but its
* factor matches ratio of a prefix from the specified prefix family, its symbol will be * factor matches ratio of a prefix, its symbol will be prepended to the symbol of the unit
* prepended to the symbol of the unit
* *
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @tparam PF a type of prefix family
* @tparam Symbol a text representation of the prefix * @tparam Symbol a text representation of the prefix
* @tparam R factor to be used to scale a unit * @tparam R factor to be used to scale a unit
*/ */
template<typename Child, PrefixFamily PF, basic_symbol_text Symbol, ratio R> template<typename Child, basic_symbol_text Symbol, ratio R>
requires(!std::same_as<PF, no_prefix>) struct prefix : downcast_dispatch<Child, detail::prefix_base<R>, downcast_mode::on> {
struct prefix : downcast_dispatch<Child, detail::prefix_base<PF, R>, downcast_mode::on> {
static constexpr auto symbol = Symbol; static constexpr auto symbol = Symbol;
}; };

View File

@@ -45,6 +45,12 @@ inline constexpr auto make_quantity = [](auto&& v) {
return quantity<typename decltype(R)::dimension, typename decltype(R)::unit, Rep>(std::forward<decltype(v)>(v)); return quantity<typename decltype(R)::dimension, typename decltype(R)::unit, Rep>(std::forward<decltype(v)>(v));
}; };
template<typename T>
concept quantity_one =
Quantity<T> &&
(std::same_as<typename T::dimension, dim_one> || std::same_as<typename T::dimension, unknown_dimension<>>) &&
detail::equivalent_unit<typename T::unit, typename T::dimension, ::units::one, typename T::dimension>::value;
} // namespace detail } // namespace detail
template<typename T> template<typename T>
@@ -133,8 +139,7 @@ public:
template<typename Value> template<typename Value>
requires(safe_convertible_to_<std::remove_cvref_t<Value>, rep>) requires(safe_convertible_to_<std::remove_cvref_t<Value>, rep>)
constexpr explicit(!(std::same_as<dimension, dim_one> && std::same_as<unit, ::units::one>)) quantity(Value&& v) : constexpr explicit(!detail::quantity_one<quantity>) quantity(Value&& v) : number_(std::forward<Value>(v))
number_(std::forward<Value>(v))
{ {
} }
@@ -252,9 +257,9 @@ public:
number_ *= rhs; number_ *= rhs;
return *this; return *this;
} }
template<typename Rep2> template<detail::quantity_one Q>
constexpr quantity& operator*=(const dimensionless<units::one, Rep2>& rhs) constexpr quantity& operator*=(const Q& rhs)
requires requires(rep a, const Rep2 b) { requires requires(rep a, const typename Q::rep b) {
{ {
a *= b a *= b
} -> std::same_as<rep&>; } -> std::same_as<rep&>;
@@ -276,15 +281,15 @@ public:
number_ /= rhs; number_ /= rhs;
return *this; return *this;
} }
template<typename Rep2> template<detail::quantity_one Q>
constexpr quantity& operator/=(const dimensionless<units::one, Rep2>& rhs) constexpr quantity& operator/=(const Q& rhs)
requires requires(rep a, const Rep2 b) { requires requires(rep a, const typename Q::rep b) {
{ {
a /= b a /= b
} -> std::same_as<rep&>; } -> std::same_as<rep&>;
} }
{ {
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero()); gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
number_ /= rhs.number(); number_ /= rhs.number();
return *this; return *this;
} }
@@ -302,15 +307,15 @@ public:
return *this; return *this;
} }
template<typename Rep2> template<detail::quantity_one Q>
constexpr quantity& operator%=(const dimensionless<units::one, Rep2>& rhs) constexpr quantity& operator%=(const Q& rhs)
requires(!floating_point_<rep>) && (!floating_point_<Rep2>) && requires(rep a, const Rep2 b) { requires(!floating_point_<rep>) && (!floating_point_<typename Q::rep>) && requires(rep a, const typename Q::rep b) {
{ {
a %= b a %= b
} -> std::same_as<rep&>; } -> std::same_as<rep&>;
} }
{ {
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero()); gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
number_ %= rhs.number(); number_ %= rhs.number();
return *this; return *this;
} }

View File

@@ -54,6 +54,10 @@ inline constexpr auto downcasted_kind_fn = [](auto q) {
template<QuantityKind QK> template<QuantityKind QK>
inline constexpr auto& downcasted_kind = downcasted_kind_fn<typename QK::kind_type::base_kind>; inline constexpr auto& downcasted_kind = downcasted_kind_fn<typename QK::kind_type::base_kind>;
template<typename T, typename K>
concept quantity_kind_one = QuantityKind<T> && equivalent<typename T::kind_type, downcast_kind<K, dim_one>> &&
detail::quantity_one<typename T::quantity_type>;
} // namespace detail } // namespace detail
/** /**
@@ -198,8 +202,8 @@ public:
q_ *= rhs; q_ *= rhs;
return *this; return *this;
} }
template<typename Rep2> template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator*=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs) constexpr quantity_kind& operator*=(const QK& rhs)
requires requires(quantity_type q) { q *= rhs.common(); } requires requires(quantity_type q) { q *= rhs.common(); }
{ {
q_ *= rhs.common(); q_ *= rhs.common();
@@ -214,8 +218,8 @@ public:
q_ /= rhs; q_ /= rhs;
return *this; return *this;
} }
template<typename Rep2> template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator/=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs) constexpr quantity_kind& operator/=(const QK& rhs)
requires requires(quantity_type q) { q /= rhs.common(); } requires requires(quantity_type q) { q /= rhs.common(); }
{ {
q_ /= rhs.common(); q_ /= rhs.common();
@@ -233,8 +237,7 @@ public:
template<QuantityKind QK> template<QuantityKind QK>
constexpr quantity_kind& operator%=(const QK& rhs) constexpr quantity_kind& operator%=(const QK& rhs)
requires(QuantityKindEquivalentTo<QK, quantity_kind> || requires(QuantityKindEquivalentTo<QK, quantity_kind> || detail::quantity_kind_one<QK, K>) &&
std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
requires(quantity_type q) { q %= rhs.common(); } requires(quantity_type q) { q %= rhs.common(); }
{ {
gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero()); gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero());

View File

@@ -78,16 +78,16 @@ struct basic_symbol_text {
{ {
detail::validate_ascii_string<N>(std.data_); detail::validate_ascii_string<N>(std.data_);
} }
constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&a)[M + 1]) noexcept : constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&ascii)[M + 1]) noexcept :
standard_(std), ascii_(a) standard_(std), ascii_(ascii)
{ {
detail::validate_ascii_string<M>(a); detail::validate_ascii_string<M>(ascii);
} }
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& std, constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& std,
const basic_fixed_string<char, M>& a) noexcept : const basic_fixed_string<char, M>& ascii) noexcept :
standard_(std), ascii_(a) standard_(std), ascii_(ascii)
{ {
detail::validate_ascii_string<M>(a.data_); detail::validate_ascii_string<M>(ascii.data_);
} }
[[nodiscard]] constexpr auto& standard() { return standard_; } [[nodiscard]] constexpr auto& standard() { return standard_; }

View File

@@ -26,7 +26,7 @@
#include <units/bits/external/downcasting.h> #include <units/bits/external/downcasting.h>
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/bits/derived_unit.h> #include <units/bits/derived_scaled_unit.h>
#include <units/bits/external/fixed_string.h> #include <units/bits/external/fixed_string.h>
#include <units/magnitude.h> #include <units/magnitude.h>
#include <units/prefix.h> #include <units/prefix.h>
@@ -36,6 +36,13 @@
namespace units { namespace units {
namespace detail {
template<typename>
inline constexpr bool can_be_prefixed = false;
} // namespace detail
/** /**
* @brief A common point for a hierarchy of units * @brief A common point for a hierarchy of units
* *
@@ -63,58 +70,34 @@ using downcast_unit = downcast<scaled_unit<M, typename dimension_unit<D>::refere
template<Unit U1, Unit U2> template<Unit U1, Unit U2>
struct same_unit_reference : is_same<typename U1::reference, typename U2::reference> {}; struct same_unit_reference : is_same<typename U1::reference, typename U2::reference> {};
/**
* @brief An unnamed unit
*
* Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension
* and it should be passed in this dimension's definition.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
*/
template<typename Child>
struct unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {
static constexpr bool is_named = false;
using prefix_family = no_prefix;
};
/** /**
* @brief A named unit * @brief A named unit
* *
* Defines a named (in most cases coherent) unit that is then passed to a dimension definition. * Defines a named (in most cases coherent) unit that is then passed to a dimension definition.
* A named unit may be used by other units defined with the prefix of the same type, unless * A named unit may be composed with a prefix to create a prefixed_unit.
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
* a prefix unit based on this one).
* *
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @tparam Symbol a short text representation of the unit * @tparam Symbol a short text representation of the unit
* @tparam PF no_prefix or a type of prefix family
*/ */
template<typename Child, basic_symbol_text Symbol, PrefixFamily PF> template<typename Child, basic_symbol_text Symbol>
struct named_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> { struct named_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol; static constexpr auto symbol = Symbol;
using prefix_family = PF;
}; };
/** /**
* @brief A scaled unit * @brief A named scaled unit
* *
* Defines a new named unit that is a scaled version of another unit. Such unit can be used by * Defines a new named unit that is a scaled version of another unit.
* other units defined with the prefix of the same type, unless no_prefix is provided for PF * A named unit may be composed with a prefix to create a prefixed_unit.
* template parameter (in such a case it is impossible to define a prefix unit based on this
* one).
* *
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @tparam Symbol a short text representation of the unit * @tparam Symbol a short text representation of the unit
* @tparam PF no_prefix or a type of prefix family
* @tparam M the Magnitude by which to scale U * @tparam M the Magnitude by which to scale U
* @tparam U a reference unit to scale * @tparam U a reference unit to scale
*/ */
template<typename Child, basic_symbol_text Symbol, PrefixFamily PF, Magnitude auto M, Unit U> template<typename Child, basic_symbol_text Symbol, Magnitude auto M, Unit U>
struct named_scaled_unit : downcast_dispatch<Child, scaled_unit<M * U::mag, typename U::reference>> { struct named_scaled_unit : downcast_dispatch<Child, scaled_unit<M * U::mag, typename U::reference>> {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol; static constexpr auto symbol = Symbol;
using prefix_family = PF;
}; };
/** /**
@@ -128,14 +111,23 @@ struct named_scaled_unit : downcast_dispatch<Child, scaled_unit<M * U::mag, type
* @tparam P prefix to be appied to the reference unit * @tparam P prefix to be appied to the reference unit
* @tparam U reference unit * @tparam U reference unit
*/ */
template<typename Child, Prefix P, Unit U> template<typename Child, Prefix P, NamedUnit U>
requires U::is_named && std::same_as<typename P::prefix_family, typename U::prefix_family> requires detail::can_be_prefixed<U>
struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typename U::reference>> { struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typename U::reference>> {
static constexpr bool is_named = true;
static constexpr auto symbol = P::symbol + U::symbol; static constexpr auto symbol = P::symbol + U::symbol;
using prefix_family = no_prefix;
}; };
/**
* @brief A coherent unit of a derived quantity
*
* Defines a new coherent unit of a derived quantity. It should be passed as a coherent unit
* in the dimension's definition for such a quantity.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
*/
template<typename Child>
struct derived_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {};
/** /**
* @brief A unit with a deduced ratio and symbol * @brief A unit with a deduced ratio and symbol
* *
@@ -149,36 +141,10 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typ
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe * @tparam U the unit of the first composite dimension from provided derived dimension's recipe
* @tparam URest the units for the rest of dimensions from the recipe * @tparam URest the units for the rest of dimensions from the recipe
*/ */
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest> template<typename Child, DerivedDimension Dim, NamedUnit U, NamedUnit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true))
struct derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = false;
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
using prefix_family = no_prefix;
};
/**
* @brief A named unit with a deduced ratio
*
* Defines a new unit with a deduced ratio and the given symbol based on the recipe from the provided
* derived dimension. The number and order of provided units should match the recipe of the
* derived dimension. All of the units provided should also be a named ones so it is possible
* to create a deduced symbol text.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @tparam Dim a derived dimension recipe to use for deduction
* @tparam Symbol a short text representation of the unit
* @tparam PF no_prefix or a type of prefix family
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
* @tparam URest the units for the rest of dimensions from the recipe
*/
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> { struct derived_scaled_unit : downcast_dispatch<Child, detail::derived_scaled_unit<Dim, U, URest...>> {
static constexpr bool is_named = true; static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
static constexpr auto symbol = Symbol;
using prefix_family = PF;
}; };
/** /**
@@ -186,19 +152,14 @@ struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U
* *
* Defines a named alias for another unit. It is useful to assign alternative names and symbols * Defines a named alias for another unit. It is useful to assign alternative names and symbols
* to the already predefined units (i.e. "tonne" for "megagram"). * to the already predefined units (i.e. "tonne" for "megagram").
* An alias unit may be used by other units defined with the prefix of the same type, unless * A alias unit may be composed with a prefix to create a prefixed_alias_unit.
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
* a prefix unit based on this one).
* *
* @tparam U Unit for which an alias is defined * @tparam U Unit for which an alias is defined
* @tparam Symbol a short text representation of the unit * @tparam Symbol a short text representation of the unit
* @tparam PF no_prefix or a type of prefix family
*/ */
template<Unit U, basic_symbol_text Symbol, PrefixFamily PF> template<Unit U, basic_symbol_text Symbol>
struct alias_unit : U { struct alias_unit : U {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol; static constexpr auto symbol = Symbol;
using prefix_family = PF;
}; };
/** /**
@@ -215,20 +176,55 @@ struct alias_unit : U {
// TODO gcc bug: 95015 // TODO gcc bug: 95015
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95015 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95015
// template<Unit U, Prefix P, AliasUnit AU> // template<Unit U, Prefix P, AliasUnit AU>
// requires (!AliasUnit<U>) && std::same_as<typename P::prefix_family, typename AU::prefix_family> // requires (!AliasUnit<U>)
template<Unit U, Prefix P, Unit AU> template<Unit U, Prefix P, NamedUnit AU>
requires AU::is_named && std::same_as<typename P::prefix_family, typename AU::prefix_family> requires detail::can_be_prefixed<AU>
struct prefixed_alias_unit : U { struct prefixed_alias_unit : U {
static constexpr bool is_named = true;
static constexpr auto symbol = P::symbol + AU::symbol; static constexpr auto symbol = P::symbol + AU::symbol;
using prefix_family = no_prefix;
}; };
/** /**
* @brief Unknown unit * @brief Unknown coherent unit
* *
* Used as a coherent unit of an unknown dimension. * Used as a coherent unit of an unknown dimension.
*/ */
struct unknown_coherent_unit : unit<unknown_coherent_unit> {}; struct unknown_coherent_unit : derived_unit<unknown_coherent_unit> {};
namespace detail {
template<typename Child, basic_symbol_text Symbol>
void is_named_impl(const volatile named_unit<Child, Symbol>*);
template<typename Child, basic_symbol_text Symbol, Magnitude auto M, typename U>
void is_named_impl(const volatile named_scaled_unit<Child, Symbol, M, U>*);
template<typename Child, typename P, typename U>
void is_named_impl(const volatile prefixed_unit<Child, P, U>*);
template<typename U, basic_symbol_text Symbol>
void is_named_impl(const volatile alias_unit<U, Symbol>*);
template<typename U, typename P, typename AU>
void is_named_impl(const volatile prefixed_alias_unit<U, P, AU>*);
template<Unit U>
inline constexpr bool is_named<U> = requires(U * u) { is_named_impl(u); };
template<typename Child, basic_symbol_text Symbol>
void can_be_prefixed_impl(const volatile named_unit<Child, Symbol>*);
template<typename Child, basic_symbol_text Symbol, Magnitude auto M, typename U>
void can_be_prefixed_impl(const volatile named_scaled_unit<Child, Symbol, M, U>*);
template<typename U, basic_symbol_text Symbol>
void can_be_prefixed_impl(const volatile alias_unit<U, Symbol>*);
template<Unit U>
inline constexpr bool can_be_prefixed<U> = requires(U * u) { can_be_prefixed_impl(u); };
template<Magnitude auto M, typename U>
inline constexpr bool can_be_prefixed<scaled_unit<M, U>> = can_be_prefixed<typename U::reference>;
} // namespace detail
} // namespace units } // namespace units

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
# systems # systems
add_subdirectory(isq) add_subdirectory(isq)

View File

@@ -20,6 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(isq-iec80000 mp-units::si) add_units_module(
isq-iec80000
DEPENDENCIES mp-units::si
HEADERS include/units/isq/iec80000/binary_prefixes.h include/units/isq/iec80000/iec80000.h
include/units/isq/iec80000/modulation_rate.h include/units/isq/iec80000/storage_capacity.h
include/units/isq/iec80000/traffic_intensity.h include/units/isq/iec80000/transfer_rate.h
)

View File

@@ -26,13 +26,11 @@
namespace units::isq::iec80000 { namespace units::isq::iec80000 {
struct binary_prefix : prefix_family {}; struct kibi : units::prefix<kibi, "Ki", ratio(1'024)> {};
struct mebi : units::prefix<mebi, "Mi", ratio(1'048'576)> {};
struct kibi : units::prefix<kibi, binary_prefix, "Ki", ratio(1'024)> {}; struct gibi : units::prefix<gibi, "Gi", ratio(1'073'741'824)> {};
struct mebi : units::prefix<mebi, binary_prefix, "Mi", ratio(1'048'576)> {}; struct tebi : units::prefix<tebi, "Ti", ratio(1'099'511'627'776)> {};
struct gibi : units::prefix<gibi, binary_prefix, "Gi", ratio(1'073'741'824)> {}; struct pebi : units::prefix<pebi, "Pi", ratio(1'125'899'906'842'624)> {};
struct tebi : units::prefix<tebi, binary_prefix, "Ti", ratio(1'099'511'627'776)> {}; struct exbi : units::prefix<exbi, "Ei", ratio(1'152'921'504'606'846'976)> {};
struct pebi : units::prefix<pebi, binary_prefix, "Pi", ratio(1'125'899'906'842'624)> {};
struct exbi : units::prefix<exbi, binary_prefix, "Ei", ratio(1'152'921'504'606'846'976)> {};
} // namespace units::isq::iec80000 } // namespace units::isq::iec80000

View File

@@ -34,7 +34,7 @@
namespace units::isq::iec80000 { namespace units::isq::iec80000 {
struct baud : alias_unit<si::hertz, "Bd", si::prefix> {}; struct baud : alias_unit<si::hertz, "Bd"> {};
struct kilobaud : prefixed_alias_unit<si::kilohertz, si::kilo, baud> {}; struct kilobaud : prefixed_alias_unit<si::kilohertz, si::kilo, baud> {};
struct megabaud : prefixed_alias_unit<si::megahertz, si::mega, baud> {}; struct megabaud : prefixed_alias_unit<si::megahertz, si::mega, baud> {};
struct gigabaud : prefixed_alias_unit<si::gigahertz, si::giga, baud> {}; struct gigabaud : prefixed_alias_unit<si::gigahertz, si::giga, baud> {};

View File

@@ -35,7 +35,8 @@
namespace units::isq::iec80000 { namespace units::isq::iec80000 {
struct bit : named_unit<bit, "bit", si::prefix> {}; struct bit : named_unit<bit, "bit"> {};
struct kilobit : prefixed_unit<kilobit, si::kilo, bit> {}; struct kilobit : prefixed_unit<kilobit, si::kilo, bit> {};
struct megabit : prefixed_unit<megabit, si::mega, bit> {}; struct megabit : prefixed_unit<megabit, si::mega, bit> {};
struct gigabit : prefixed_unit<gigabit, si::giga, bit> {}; struct gigabit : prefixed_unit<gigabit, si::giga, bit> {};
@@ -45,15 +46,15 @@ struct exabit : prefixed_unit<exabit, si::exa, bit> {};
struct zettabit : prefixed_unit<zettabit, si::zetta, bit> {}; struct zettabit : prefixed_unit<zettabit, si::zetta, bit> {};
struct yottabit : prefixed_unit<yottabit, si::yotta, bit> {}; struct yottabit : prefixed_unit<yottabit, si::yotta, bit> {};
struct binary_prefix_bit : alias_unit<bit, "bit", binary_prefix> {}; struct kibibit : prefixed_unit<kibibit, kibi, bit> {};
struct kibibit : prefixed_unit<kibibit, kibi, binary_prefix_bit> {}; struct mebibit : prefixed_unit<mebibit, mebi, bit> {};
struct mebibit : prefixed_unit<mebibit, mebi, binary_prefix_bit> {}; struct gibibit : prefixed_unit<gibibit, gibi, bit> {};
struct gibibit : prefixed_unit<gibibit, gibi, binary_prefix_bit> {}; struct tebibit : prefixed_unit<tebibit, tebi, bit> {};
struct tebibit : prefixed_unit<tebibit, tebi, binary_prefix_bit> {}; struct pebibit : prefixed_unit<pebibit, pebi, bit> {};
struct pebibit : prefixed_unit<pebibit, pebi, binary_prefix_bit> {}; struct exbibit : prefixed_unit<exbibit, exbi, bit> {};
struct exbibit : prefixed_unit<exbibit, exbi, binary_prefix_bit> {};
struct byte : named_scaled_unit<byte, "B", as_magnitude<8>(), bit> {};
struct byte : named_scaled_unit<byte, "B", si::prefix, as_magnitude<8>(), bit> {};
struct kilobyte : prefixed_unit<kilobyte, si::kilo, byte> {}; struct kilobyte : prefixed_unit<kilobyte, si::kilo, byte> {};
struct megabyte : prefixed_unit<megabyte, si::mega, byte> {}; struct megabyte : prefixed_unit<megabyte, si::mega, byte> {};
struct gigabyte : prefixed_unit<gigabyte, si::giga, byte> {}; struct gigabyte : prefixed_unit<gigabyte, si::giga, byte> {};
@@ -63,13 +64,12 @@ struct exabyte : prefixed_unit<exabyte, si::exa, byte> {};
struct zettabyte : prefixed_unit<zettabyte, si::zetta, byte> {}; struct zettabyte : prefixed_unit<zettabyte, si::zetta, byte> {};
struct yottabyte : prefixed_unit<yottabyte, si::yotta, byte> {}; struct yottabyte : prefixed_unit<yottabyte, si::yotta, byte> {};
struct binary_prefix_byte : alias_unit<byte, "B", binary_prefix> {}; struct kibibyte : prefixed_unit<kibibyte, kibi, byte> {};
struct kibibyte : prefixed_unit<kibibyte, kibi, binary_prefix_byte> {}; struct mebibyte : prefixed_unit<mebibyte, mebi, byte> {};
struct mebibyte : prefixed_unit<mebibyte, mebi, binary_prefix_byte> {}; struct gibibyte : prefixed_unit<gibibyte, gibi, byte> {};
struct gibibyte : prefixed_unit<gibibyte, gibi, binary_prefix_byte> {}; struct tebibyte : prefixed_unit<tebibyte, tebi, byte> {};
struct tebibyte : prefixed_unit<tebibyte, tebi, binary_prefix_byte> {}; struct pebibyte : prefixed_unit<pebibyte, pebi, byte> {};
struct pebibyte : prefixed_unit<pebibyte, pebi, binary_prefix_byte> {}; // struct exbibyte : prefixed_unit<exbibyte, exbi, byte> {};
// struct exbibyte : prefixed_unit<exbibyte, exbi, binary_prefix_byte> {};
struct dim_storage_capacity : base_dimension<"M", byte> {}; struct dim_storage_capacity : base_dimension<"M", byte> {};

View File

@@ -33,7 +33,7 @@
namespace units::isq::iec80000 { namespace units::isq::iec80000 {
struct erlang : named_unit<erlang, "E", no_prefix> {}; struct erlang : named_unit<erlang, "E"> {};
struct dim_traffic_intensity : base_dimension<"A", erlang> {}; struct dim_traffic_intensity : base_dimension<"A", erlang> {};

View File

@@ -34,19 +34,19 @@
namespace units::isq::iec80000 { namespace units::isq::iec80000 {
struct byte_per_second : unit<byte_per_second> {}; struct byte_per_second : derived_unit<byte_per_second> {};
struct dim_transfer_rate : struct dim_transfer_rate :
derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>, derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>,
exponent<si::dim_time, -1>> {}; exponent<si::dim_time, -1>> {};
struct kilobyte_per_second : derived_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {}; struct kilobyte_per_second : derived_scaled_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
struct megabyte_per_second : derived_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {}; struct megabyte_per_second : derived_scaled_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
struct gigabyte_per_second : derived_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {}; struct gigabyte_per_second : derived_scaled_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
struct terabyte_per_second : derived_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {}; struct terabyte_per_second : derived_scaled_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
struct petabyte_per_second : derived_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {}; struct petabyte_per_second : derived_scaled_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
struct exabyte_per_second : derived_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {}; struct exabyte_per_second : derived_scaled_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
struct zettabyte_per_second : derived_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {}; struct zettabyte_per_second : derived_scaled_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
struct yottabyte_per_second : derived_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {}; struct yottabyte_per_second : derived_scaled_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
template<typename T> template<typename T>
concept TransferRate = QuantityOf<T, dim_transfer_rate>; concept TransferRate = QuantityOf<T, dim_transfer_rate>;

View File

@@ -20,6 +20,20 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(isq-natural mp-units::isq) add_units_module(
isq-natural
DEPENDENCIES mp-units::isq
HEADERS include/units/isq/natural/acceleration.h
include/units/isq/natural/constants.h
include/units/isq/natural/energy.h
include/units/isq/natural/force.h
include/units/isq/natural/length.h
include/units/isq/natural/mass.h
include/units/isq/natural/momentum.h
include/units/isq/natural/natural.h
include/units/isq/natural/speed.h
include/units/isq/natural/time.h
include/units/isq/natural/units.h
)

View File

@@ -31,11 +31,10 @@
namespace units::isq::natural { namespace units::isq::natural {
struct electronvolt : named_unit<electronvolt, "eV", si::prefix> {}; struct electronvolt : named_unit<electronvolt, "eV"> {};
struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, si::giga, electronvolt> {}; struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, si::giga, electronvolt> {};
struct inverted_gigaelectronvolt : struct inverted_gigaelectronvolt : named_unit<inverted_gigaelectronvolt, basic_symbol_text{"GeV⁻¹", "GeV^-1"}> {};
named_unit<inverted_gigaelectronvolt, basic_symbol_text{"GeV⁻¹", "GeV^-1"}, no_prefix> {}; struct square_gigaelectronvolt : named_unit<square_gigaelectronvolt, basic_symbol_text{"GeV²", "GeV^2"}> {};
struct square_gigaelectronvolt : named_unit<square_gigaelectronvolt, basic_symbol_text{"GeV²", "GeV^2"}, no_prefix> {};
// NOTE: eV as a base unit with no relation to joule prevents us from going back // NOTE: eV as a base unit with no relation to joule prevents us from going back
// from natural units to SI. Do we need such a support or should we treat // from natural units to SI. Do we need such a support or should we treat

View File

@@ -20,6 +20,54 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(isq mp-units::core) add_units_module(
isq
DEPENDENCIES mp-units::core
HEADERS include/units/isq/dimensions/absorbed_dose.h
include/units/isq/dimensions/acceleration.h
include/units/isq/dimensions/amount_of_substance.h
include/units/isq/dimensions/angular_velocity.h
include/units/isq/dimensions/area.h
include/units/isq/dimensions/capacitance.h
include/units/isq/dimensions/catalytic_activity.h
include/units/isq/dimensions/charge_density.h
include/units/isq/dimensions/concentration.h
include/units/isq/dimensions/conductance.h
include/units/isq/dimensions/current_density.h
include/units/isq/dimensions/density.h
include/units/isq/dimensions/dynamic_viscosity.h
include/units/isq/dimensions/electric_charge.h
include/units/isq/dimensions/electric_current.h
include/units/isq/dimensions/electric_field_strength.h
include/units/isq/dimensions/energy.h
include/units/isq/dimensions/energy_density.h
include/units/isq/dimensions/force.h
include/units/isq/dimensions/frequency.h
include/units/isq/dimensions/heat_capacity.h
include/units/isq/dimensions/inductance.h
include/units/isq/dimensions/length.h
include/units/isq/dimensions/luminance.h
include/units/isq/dimensions/luminous_intensity.h
include/units/isq/dimensions/magnetic_flux.h
include/units/isq/dimensions/magnetic_induction.h
include/units/isq/dimensions/mass.h
include/units/isq/dimensions/molar_energy.h
include/units/isq/dimensions/momentum.h
include/units/isq/dimensions/permeability.h
include/units/isq/dimensions/permittivity.h
include/units/isq/dimensions/power.h
include/units/isq/dimensions/pressure.h
include/units/isq/dimensions/radioactivity.h
include/units/isq/dimensions/resistance.h
include/units/isq/dimensions/speed.h
include/units/isq/dimensions/surface_tension.h
include/units/isq/dimensions/thermal_conductivity.h
include/units/isq/dimensions/thermodynamic_temperature.h
include/units/isq/dimensions/time.h
include/units/isq/dimensions/torque.h
include/units/isq/dimensions/voltage.h
include/units/isq/dimensions/volume.h
include/units/isq/dimensions.h
)

View File

@@ -23,6 +23,7 @@
#pragma once #pragma once
#include <units/concepts.h> #include <units/concepts.h>
#include <units/isq/dimensions/mass.h>
#include <units/isq/dimensions/speed.h> #include <units/isq/dimensions/speed.h>
namespace units::isq { namespace units::isq {

View File

@@ -20,6 +20,20 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-cgs mp-units::si) add_units_module(
si-cgs
DEPENDENCIES mp-units::si
HEADERS include/units/isq/si/cgs/acceleration.h
include/units/isq/si/cgs/area.h
include/units/isq/si/cgs/cgs.h
include/units/isq/si/cgs/energy.h
include/units/isq/si/cgs/force.h
include/units/isq/si/cgs/length.h
include/units/isq/si/cgs/mass.h
include/units/isq/si/cgs/power.h
include/units/isq/si/cgs/pressure.h
include/units/isq/si/cgs/speed.h
include/units/isq/si/cgs/time.h
)

View File

@@ -34,7 +34,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct gal : named_unit<gal, "Gal", si::prefix> {}; struct gal : named_unit<gal, "Gal"> {};
struct dim_acceleration : isq::dim_acceleration<dim_acceleration, gal, dim_length, dim_time> {}; struct dim_acceleration : isq::dim_acceleration<dim_acceleration, gal, dim_length, dim_time> {};
template<UnitOf<dim_acceleration> U, Representation Rep = double> template<UnitOf<dim_acceleration> U, Representation Rep = double>

View File

@@ -35,7 +35,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct erg : named_unit<erg, "erg", si::prefix> {}; struct erg : named_unit<erg, "erg"> {};
struct dim_energy : isq::dim_energy<dim_energy, erg, dim_force, dim_length> {}; struct dim_energy : isq::dim_energy<dim_energy, erg, dim_force, dim_length> {};

View File

@@ -36,7 +36,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct dyne : named_unit<dyne, "dyn", si::prefix> {}; struct dyne : named_unit<dyne, "dyn"> {};
struct dim_force : isq::dim_force<dim_force, dyne, dim_mass, dim_acceleration> {}; struct dim_force : isq::dim_force<dim_force, dyne, dim_mass, dim_acceleration> {};

View File

@@ -34,7 +34,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct erg_per_second : unit<erg_per_second> {}; struct erg_per_second : derived_unit<erg_per_second> {};
struct dim_power : isq::dim_power<dim_power, erg_per_second, dim_energy, dim_time> {}; struct dim_power : isq::dim_power<dim_power, erg_per_second, dim_energy, dim_time> {};

View File

@@ -36,7 +36,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct barye : named_unit<barye, "Ba", si::prefix> {}; struct barye : named_unit<barye, "Ba"> {};
struct dim_pressure : isq::dim_pressure<dim_pressure, barye, dim_force, dim_area> {}; struct dim_pressure : isq::dim_pressure<dim_pressure, barye, dim_force, dim_area> {};

View File

@@ -34,7 +34,7 @@
namespace units::isq::si::cgs { namespace units::isq::si::cgs {
struct centimetre_per_second : unit<centimetre_per_second> {}; struct centimetre_per_second : derived_unit<centimetre_per_second> {};
struct dim_speed : isq::dim_speed<dim_speed, centimetre_per_second, dim_length, dim_time> {}; struct dim_speed : isq::dim_speed<dim_speed, centimetre_per_second, dim_length, dim_time> {};
template<UnitOf<dim_speed> U, Representation Rep = double> template<UnitOf<dim_speed> U, Representation Rep = double>

View File

@@ -20,6 +20,22 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-fps mp-units::si) add_units_module(
si-fps
DEPENDENCIES mp-units::si-international
HEADERS include/units/isq/si/fps/acceleration.h
include/units/isq/si/fps/area.h
include/units/isq/si/fps/density.h
include/units/isq/si/fps/energy.h
include/units/isq/si/fps/force.h
include/units/isq/si/fps/fps.h
include/units/isq/si/fps/length.h
include/units/isq/si/fps/mass.h
include/units/isq/si/fps/power.h
include/units/isq/si/fps/pressure.h
include/units/isq/si/fps/speed.h
include/units/isq/si/fps/time.h
include/units/isq/si/fps/volume.h
)

View File

@@ -33,7 +33,7 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct foot_per_second_sq : unit<foot_per_second_sq> {}; struct foot_per_second_sq : derived_unit<foot_per_second_sq> {};
struct dim_acceleration : isq::dim_acceleration<dim_acceleration, foot_per_second_sq, dim_length, dim_time> {}; struct dim_acceleration : isq::dim_acceleration<dim_acceleration, foot_per_second_sq, dim_length, dim_time> {};
template<UnitOf<dim_acceleration> U, Representation Rep = double> template<UnitOf<dim_acceleration> U, Representation Rep = double>

View File

@@ -34,7 +34,7 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct square_foot : unit<square_foot> {}; struct square_foot : derived_unit<square_foot> {};
struct dim_area : isq::dim_area<dim_area, square_foot, dim_length> {}; struct dim_area : isq::dim_area<dim_area, square_foot, dim_length> {};

View File

@@ -34,7 +34,7 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct pound_per_foot_cub : unit<pound_per_foot_cub> {}; struct pound_per_foot_cub : derived_unit<pound_per_foot_cub> {};
struct dim_density : isq::dim_density<dim_density, pound_per_foot_cub, dim_mass, dim_length> {}; struct dim_density : isq::dim_density<dim_density, pound_per_foot_cub, dim_mass, dim_length> {};

View File

@@ -35,12 +35,12 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
// https://en.wikipedia.org/wiki/Foot-poundal // https://en.wikipedia.org/wiki/Foot-poundal
struct foot_poundal : unit<foot_poundal> {}; struct foot_poundal : derived_unit<foot_poundal> {};
struct dim_energy : isq::dim_energy<dim_energy, foot_poundal, dim_length, dim_force> {}; struct dim_energy : isq::dim_energy<dim_energy, foot_poundal, dim_length, dim_force> {};
// https://en.wikipedia.org/wiki/Foot-pound_(energy) // https://en.wikipedia.org/wiki/Foot-pound_(energy)
struct foot_pound_force : derived_unit<foot_pound_force, dim_energy, foot, pound_force> {}; struct foot_pound_force : derived_scaled_unit<foot_pound_force, dim_energy, foot, pound_force> {};
template<UnitOf<dim_energy> U, Representation Rep = double> template<UnitOf<dim_energy> U, Representation Rep = double>
using energy = quantity<dim_energy, U, Rep>; using energy = quantity<dim_energy, U, Rep>;

View File

@@ -37,16 +37,15 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
// https://en.wikipedia.org/wiki/Poundal // https://en.wikipedia.org/wiki/Poundal
struct poundal : named_unit<poundal, "pdl", no_prefix> {}; struct poundal : named_unit<poundal, "pdl"> {};
// https://en.wikipedia.org/wiki/Pound_(force) // https://en.wikipedia.org/wiki/Pound_(force)
struct pound_force : struct pound_force : named_scaled_unit<pound_force, "lbf", as_magnitude<ratio(32'174'049, 1'000'000)>(), poundal> {};
named_scaled_unit<pound_force, "lbf", si::prefix, as_magnitude<ratio(32'174'049, 1'000'000)>(), poundal> {};
struct kilopound_force : prefixed_unit<kilopound_force, si::kilo, pound_force> {}; struct kilopound_force : prefixed_unit<kilopound_force, si::kilo, pound_force> {};
// https://en.wikipedia.org/wiki/Kip_(unit), // https://en.wikipedia.org/wiki/Kip_(unit),
struct kip : alias_unit<kilopound_force, "klbf", no_prefix> {}; struct kip : alias_unit<kilopound_force, "klbf"> {};
struct dim_force : isq::dim_force<dim_force, poundal, dim_mass, dim_acceleration> {}; struct dim_force : isq::dim_force<dim_force, poundal, dim_mass, dim_acceleration> {};

View File

@@ -29,30 +29,26 @@
#include <units/symbol_text.h> #include <units/symbol_text.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
#include <units/isq/si/length.h> #include <units/isq/si/international/length.h>
#include <units/unit.h> #include <units/unit.h>
namespace units::isq::si::fps { namespace units::isq::si::fps {
// https://en.wikipedia.org/wiki/Foot_(unit) // https://en.wikipedia.org/wiki/Foot_(unit)
struct foot : named_scaled_unit<foot, "ft", no_prefix, as_magnitude<ratio(3'048, 1'000, -1)>(), si::metre> {}; using si::international::fathom;
using si::international::foot;
struct inch : named_scaled_unit<inch, "in", no_prefix, as_magnitude<ratio(1, 12)>(), foot> {}; using si::international::inch;
using si::international::mil;
using si::international::mile;
using si::international::thou;
using si::international::yard;
// thousandth of an inch // thousandth of an inch
struct thousandth : named_scaled_unit<thousandth, "thou", no_prefix, as_magnitude<ratio(1, 1'000)>(), inch> {}; struct thousandth : alias_unit<thou, "thou"> {};
struct thou : alias_unit<thousandth, "thou", no_prefix> {};
struct mil : alias_unit<thousandth, "mil", no_prefix> {};
struct yard : named_scaled_unit<yard, "yd", si::prefix, as_magnitude<3>(), foot> {};
struct fathom : named_scaled_unit<fathom, "ftm", no_prefix, as_magnitude<6>(), foot> {};
struct kiloyard : prefixed_unit<kiloyard, si::kilo, yard> {}; struct kiloyard : prefixed_unit<kiloyard, si::kilo, yard> {};
struct mile : named_scaled_unit<mile, "mile", no_prefix, as_magnitude<5'280>(), foot> {}; struct nautical_mile : named_scaled_unit<nautical_mile, "nmi", as_magnitude<2'000>(), yard> {};
struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", no_prefix, as_magnitude<2'000>(), yard> {};
struct dim_length : isq::dim_length<foot> {}; struct dim_length : isq::dim_length<foot> {};

View File

@@ -35,29 +35,28 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
// https://en.wikipedia.org/wiki/Pound_(mass) // https://en.wikipedia.org/wiki/Pound_(mass)
struct pound : struct pound : named_scaled_unit<pound, "lb", as_magnitude<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
named_scaled_unit<pound, "lb", no_prefix, as_magnitude<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
struct dim_mass : isq::dim_mass<pound> {}; struct dim_mass : isq::dim_mass<pound> {};
template<UnitOf<dim_mass> U, Representation Rep = double> template<UnitOf<dim_mass> U, Representation Rep = double>
using mass = quantity<dim_mass, U, Rep>; using mass = quantity<dim_mass, U, Rep>;
struct grain : named_scaled_unit<grain, "gr", no_prefix, as_magnitude<ratio(1, 7000)>(), pound> {}; struct grain : named_scaled_unit<grain, "gr", as_magnitude<ratio(1, 7000)>(), pound> {};
struct dram : named_scaled_unit<dram, "dr", no_prefix, as_magnitude<ratio(1, 256)>(), pound> {}; struct dram : named_scaled_unit<dram, "dr", as_magnitude<ratio(1, 256)>(), pound> {};
struct ounce : named_scaled_unit<ounce, "oz", no_prefix, as_magnitude<ratio(1, 16)>(), pound> {}; struct ounce : named_scaled_unit<ounce, "oz", as_magnitude<ratio(1, 16)>(), pound> {};
struct stone : named_scaled_unit<stone, "st", no_prefix, as_magnitude<14>(), pound> {}; struct stone : named_scaled_unit<stone, "st", as_magnitude<14>(), pound> {};
struct quarter : named_scaled_unit<quarter, "qr", no_prefix, as_magnitude<28>(), pound> {}; struct quarter : named_scaled_unit<quarter, "qr", as_magnitude<28>(), pound> {};
struct hundredweight : named_scaled_unit<hundredweight, "cwt", no_prefix, as_magnitude<112>(), pound> {}; struct hundredweight : named_scaled_unit<hundredweight, "cwt", as_magnitude<112>(), pound> {};
struct short_ton : named_scaled_unit<short_ton, "ton (short)", no_prefix, as_magnitude<2'000>(), pound> {}; struct short_ton : named_scaled_unit<short_ton, "ton (short)", as_magnitude<2'000>(), pound> {};
struct long_ton : named_scaled_unit<long_ton, "ton (long)", no_prefix, as_magnitude<2'240>(), pound> {}; struct long_ton : named_scaled_unit<long_ton, "ton (long)", as_magnitude<2'240>(), pound> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

View File

@@ -35,14 +35,14 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct foot_poundal_per_second : unit<foot_poundal_per_second> {}; struct foot_poundal_per_second : derived_unit<foot_poundal_per_second> {};
struct dim_power : isq::dim_power<dim_power, foot_poundal_per_second, dim_length, dim_force, dim_time> {}; struct dim_power : isq::dim_power<dim_power, foot_poundal_per_second, dim_length, dim_force, dim_time> {};
struct foot_pound_force_per_second : derived_unit<foot_pound_force_per_second, dim_power, foot, pound_force, second> {}; struct foot_pound_force_per_second :
derived_scaled_unit<foot_pound_force_per_second, dim_power, foot, pound_force, second> {};
struct horse_power : struct horse_power : named_scaled_unit<horse_power, "hp", as_magnitude<550>(), foot_pound_force_per_second> {};
named_scaled_unit<horse_power, "hp", no_prefix, as_magnitude<550>(), foot_pound_force_per_second> {};
template<UnitOf<dim_power> U, Representation Rep = double> template<UnitOf<dim_power> U, Representation Rep = double>
using power = quantity<dim_power, U, Rep>; using power = quantity<dim_power, U, Rep>;

View File

@@ -36,7 +36,7 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct poundal_per_foot_sq : unit<poundal_per_foot_sq> {}; struct poundal_per_foot_sq : derived_unit<poundal_per_foot_sq> {};
struct dim_pressure : isq::dim_pressure<dim_pressure, poundal_per_foot_sq, dim_force, dim_area> {}; struct dim_pressure : isq::dim_pressure<dim_pressure, poundal_per_foot_sq, dim_force, dim_area> {};
@@ -44,12 +44,11 @@ template<UnitOf<dim_pressure> U, Representation Rep = double>
using pressure = quantity<dim_pressure, U, Rep>; using pressure = quantity<dim_pressure, U, Rep>;
struct pound_force_per_foot_sq : struct pound_force_per_foot_sq :
named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", si::prefix, as_magnitude<ratio(32'174'049, 1'000'000)>(), named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", as_magnitude<ratio(32'174'049, 1'000'000)>(),
poundal_per_foot_sq> {}; poundal_per_foot_sq> {};
struct pound_force_per_inch_sq : struct pound_force_per_inch_sq :
named_scaled_unit<pound_force_per_inch_sq, "psi", si::prefix, as_magnitude<ratio(1, 144)>(), named_scaled_unit<pound_force_per_inch_sq, "psi", as_magnitude<ratio(1, 144)>(), pound_force_per_foot_sq> {};
pound_force_per_foot_sq> {};
struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq, si::kilo, pound_force_per_inch_sq> {}; struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq, si::kilo, pound_force_per_inch_sq> {};

View File

@@ -35,15 +35,15 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct foot_per_second : unit<foot_per_second> {}; struct foot_per_second : derived_unit<foot_per_second> {};
struct dim_speed : isq::dim_speed<dim_speed, foot_per_second, dim_length, dim_time> {}; struct dim_speed : isq::dim_speed<dim_speed, foot_per_second, dim_length, dim_time> {};
template<UnitOf<dim_speed> U, Representation Rep = double> template<UnitOf<dim_speed> U, Representation Rep = double>
using speed = quantity<dim_speed, U, Rep>; using speed = quantity<dim_speed, U, Rep>;
struct mile_per_hour : derived_unit<mile_per_hour, dim_speed, mile, hour> {}; struct mile_per_hour : derived_scaled_unit<mile_per_hour, dim_speed, mile, hour> {};
struct nautical_mile_per_hour : derived_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour> {}; struct nautical_mile_per_hour : derived_scaled_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour> {};
struct knot : alias_unit<nautical_mile_per_hour, "knot", no_prefix> {}; struct knot : alias_unit<nautical_mile_per_hour, "kn"> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS
@@ -66,12 +66,12 @@ constexpr auto operator"" _q_mph(unsigned long long l)
constexpr auto operator"" _q_mph(long double l) { return speed<mile_per_hour, long double>(l); } constexpr auto operator"" _q_mph(long double l) { return speed<mile_per_hour, long double>(l); }
// kn // kn
constexpr auto operator"" _q_knot(unsigned long long l) constexpr auto operator"" _q_kn(unsigned long long l)
{ {
gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return speed<knot, std::int64_t>(static_cast<std::int64_t>(l)); return speed<knot, std::int64_t>(static_cast<std::int64_t>(l));
} }
constexpr auto operator"" _q_knot(long double l) { return speed<knot, long double>(l); } constexpr auto operator"" _q_kn(long double l) { return speed<knot, long double>(l); }
} // namespace literals } // namespace literals
@@ -82,7 +82,7 @@ constexpr auto operator"" _q_knot(long double l) { return speed<knot, long doubl
namespace speed_references { namespace speed_references {
inline constexpr auto mph = reference<dim_speed, mile_per_hour>{}; inline constexpr auto mph = reference<dim_speed, mile_per_hour>{};
inline constexpr auto knot = reference<dim_speed, fps::knot>{}; inline constexpr auto kn = reference<dim_speed, fps::knot>{};
} // namespace speed_references } // namespace speed_references
@@ -105,7 +105,7 @@ using ft_per_s = units::isq::si::fps::speed<units::isq::si::fps::foot_per_second
template<Representation Rep = double> template<Representation Rep = double>
using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>; using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>;
template<Representation Rep = double> template<Representation Rep = double>
using knot = units::isq::si::fps::speed<units::isq::si::fps::knot, Rep>; using kn = units::isq::si::fps::speed<units::isq::si::fps::knot, Rep>;
} // namespace units::aliases::isq::si::fps::inline speed } // namespace units::aliases::isq::si::fps::inline speed

View File

@@ -34,10 +34,10 @@
namespace units::isq::si::fps { namespace units::isq::si::fps {
struct cubic_foot : unit<cubic_foot> {}; struct cubic_foot : derived_unit<cubic_foot> {};
struct dim_volume : isq::dim_volume<dim_volume, cubic_foot, dim_length> {}; struct dim_volume : isq::dim_volume<dim_volume, cubic_foot, dim_length> {};
struct cubic_yard : derived_unit<cubic_yard, dim_volume, yard> {}; struct cubic_yard : derived_scaled_unit<cubic_yard, dim_volume, yard> {};
template<UnitOf<dim_volume> U, Representation Rep = double> template<UnitOf<dim_volume> U, Representation Rep = double>
using volume = quantity<dim_volume, U, Rep>; using volume = quantity<dim_volume, U, Rep>;

View File

@@ -20,6 +20,10 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-hep mp-units::si) add_units_module(
si-hep DEPENDENCIES mp-units::si
HEADERS include/units/isq/si/hep/area.h include/units/isq/si/hep/energy.h include/units/isq/si/hep/hep.h
include/units/isq/si/hep/mass.h include/units/isq/si/hep/momentum.h
)

View File

@@ -29,7 +29,7 @@
#include <units/symbol_text.h> #include <units/symbol_text.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
#include <units/isq/si/length.h> #include <units/isq/si/area.h>
#include <units/unit.h> #include <units/unit.h>
namespace units::isq::si::hep { namespace units::isq::si::hep {
@@ -37,7 +37,7 @@ namespace units::isq::si::hep {
// effective cross-sectional area according to EU council directive 80/181/EEC // effective cross-sectional area according to EU council directive 80/181/EEC
// https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:01980L0181-20090527#page=10 // https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:01980L0181-20090527#page=10
// https://www.fedlex.admin.ch/eli/cc/1994/3109_3109_3109/de // https://www.fedlex.admin.ch/eli/cc/1994/3109_3109_3109/de
struct barn : named_scaled_unit<barn, "b", prefix, as_magnitude<ratio(1, 1, -28)>(), square_metre> {}; struct barn : named_scaled_unit<barn, "b", as_magnitude<ratio(1, 1, -28)>(), square_metre> {};
struct yocto_barn : prefixed_unit<yocto_barn, yocto, barn> {}; struct yocto_barn : prefixed_unit<yocto_barn, yocto, barn> {};
struct zepto_barn : prefixed_unit<zepto_barn, zepto, barn> {}; struct zepto_barn : prefixed_unit<zepto_barn, zepto, barn> {};
struct atto_barn : prefixed_unit<atto_barn, atto, barn> {}; struct atto_barn : prefixed_unit<atto_barn, atto, barn> {};

View File

@@ -43,7 +43,7 @@ inline constexpr std::optional<std::intmax_t> units::known_first_factor<225'653'
namespace units::isq::si::hep { namespace units::isq::si::hep {
struct eV_per_c2 : struct eV_per_c2 :
named_scaled_unit<eV_per_c2, basic_symbol_text{"eV/c²", "eV/c^2"}, prefix, named_scaled_unit<eV_per_c2, basic_symbol_text{"eV/c²", "eV/c^2"},
as_magnitude<ratio(17'826'619'216'279, 1'000'000'000'000, -35)>(), kilogram> {}; as_magnitude<ratio(17'826'619'216'279, 1'000'000'000'000, -35)>(), kilogram> {};
struct feV_per_c2 : prefixed_unit<feV_per_c2, femto, eV_per_c2> {}; struct feV_per_c2 : prefixed_unit<feV_per_c2, femto, eV_per_c2> {};
struct peV_per_c2 : prefixed_unit<peV_per_c2, pico, eV_per_c2> {}; struct peV_per_c2 : prefixed_unit<peV_per_c2, pico, eV_per_c2> {};
@@ -60,14 +60,11 @@ struct PeV_per_c2 : prefixed_unit<PeV_per_c2, peta, eV_per_c2> {};
struct EeV_per_c2 : prefixed_unit<EeV_per_c2, exa, eV_per_c2> {}; struct EeV_per_c2 : prefixed_unit<EeV_per_c2, exa, eV_per_c2> {};
struct YeV_per_c2 : prefixed_unit<YeV_per_c2, yotta, eV_per_c2> {}; struct YeV_per_c2 : prefixed_unit<YeV_per_c2, yotta, eV_per_c2> {};
struct electron_mass : struct electron_mass :
named_scaled_unit<eV_per_c2, "m_e", prefix, as_magnitude<ratio(9'109'383'701'528, 1'000'000'000'000, -31)>(), named_scaled_unit<eV_per_c2, "m_e", as_magnitude<ratio(9'109'383'701'528, 1'000'000'000'000, -31)>(), kilogram> {};
kilogram> {};
struct proton_mass : struct proton_mass :
named_scaled_unit<eV_per_c2, "m_p", prefix, as_magnitude<ratio(1'672'621'923'695, 1'000'000'000'000, -27)>(), named_scaled_unit<eV_per_c2, "m_p", as_magnitude<ratio(1'672'621'923'695, 1'000'000'000'000, -27)>(), kilogram> {};
kilogram> {};
struct neutron_mass : struct neutron_mass :
named_scaled_unit<eV_per_c2, "m_n", prefix, as_magnitude<ratio(1'674'927'498'049, 1'000'000'000'000, -27)>(), named_scaled_unit<eV_per_c2, "m_n", as_magnitude<ratio(1'674'927'498'049, 1'000'000'000'000, -27)>(), kilogram> {};
kilogram> {};
struct dim_mass : isq::dim_mass<eV_per_c2> {}; struct dim_mass : isq::dim_mass<eV_per_c2> {};

View File

@@ -24,7 +24,6 @@
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/isq/dimensions/momentum.h> #include <units/isq/dimensions/momentum.h>
#include <units/isq/si/momentum.h>
#include <units/quantity.h> #include <units/quantity.h>
#include <units/symbol_text.h> #include <units/symbol_text.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
@@ -35,9 +34,11 @@
namespace units::isq::si::hep { namespace units::isq::si::hep {
struct kilogram_metre_per_second : derived_unit<kilogram_metre_per_second> {};
struct eV_per_c : struct eV_per_c :
named_scaled_unit<eV_per_c, "eV/c", prefix, as_magnitude<ratio(5'344'285'992'678, 1'000'000'000'000, -35)>(), named_scaled_unit<eV_per_c, "eV/c", as_magnitude<ratio(5'344'285'992'678, 1'000'000'000'000, -35)>(),
::units::isq::si::kilogram_metre_per_second> {}; kilogram_metre_per_second> {};
struct feV_per_c : prefixed_unit<feV_per_c, femto, eV_per_c> {}; struct feV_per_c : prefixed_unit<feV_per_c, femto, eV_per_c> {};
struct peV_per_c : prefixed_unit<peV_per_c, pico, eV_per_c> {}; struct peV_per_c : prefixed_unit<peV_per_c, pico, eV_per_c> {};
struct neV_per_c : prefixed_unit<neV_per_c, nano, eV_per_c> {}; struct neV_per_c : prefixed_unit<neV_per_c, nano, eV_per_c> {};

View File

@@ -20,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-iau mp-units::si) add_units_module(
si-iau DEPENDENCIES mp-units::si HEADERS include/units/isq/si/iau/iau.h include/units/isq/si/iau/length.h
)

View File

@@ -36,13 +36,13 @@
namespace units::isq::si::iau { namespace units::isq::si::iau {
// https://en.wikipedia.org/wiki/Light-year // https://en.wikipedia.org/wiki/Light-year
struct light_year : named_scaled_unit<light_year, "ly", no_prefix, as_magnitude<9460730472580800>(), si::metre> {}; struct light_year : named_scaled_unit<light_year, "ly", as_magnitude<9460730472580800>(), si::metre> {};
// https://en.wikipedia.org/wiki/Parsec // https://en.wikipedia.org/wiki/Parsec
struct parsec : named_scaled_unit<parsec, "pc", si::prefix, as_magnitude<30'856'775'814'913'673>(), si::metre> {}; struct parsec : named_scaled_unit<parsec, "pc", as_magnitude<30'856'775'814'913'673>(), si::metre> {};
// https://en.wikipedia.org/wiki/Angstrom // https://en.wikipedia.org/wiki/Angstrom
struct angstrom : named_scaled_unit<angstrom, "angstrom", no_prefix, as_magnitude<ratio(1, 1, -10)>(), si::metre> {}; struct angstrom : named_scaled_unit<angstrom, "angstrom", as_magnitude<ratio(1, 1, -10)>(), si::metre> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

View File

@@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-imperial mp-units::si) add_units_module(
si-imperial DEPENDENCIES mp-units::si HEADERS include/units/isq/si/imperial/imperial.h
include/units/isq/si/imperial/length.h
)

View File

@@ -35,10 +35,10 @@
namespace units::isq::si::imperial { namespace units::isq::si::imperial {
// https://en.wikipedia.org/wiki/Chain_(unit) // https://en.wikipedia.org/wiki/Chain_(unit)
struct chain : named_scaled_unit<chain, "ch", no_prefix, as_magnitude<22>(), si::international::yard> {}; struct chain : named_scaled_unit<chain, "ch", as_magnitude<22>(), si::international::yard> {};
// https://en.wikipedia.org/wiki/Rod_(unit) // https://en.wikipedia.org/wiki/Rod_(unit)
struct rod : named_scaled_unit<rod, "rd", no_prefix, as_magnitude<ratio(1, 4)>(), chain> {}; struct rod : named_scaled_unit<rod, "rd", as_magnitude<ratio(1, 4)>(), chain> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

View File

@@ -20,6 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-international mp-units::si) add_units_module(
si-international
DEPENDENCIES mp-units::si
HEADERS include/units/isq/si/international/area.h include/units/isq/si/international/international.h
include/units/isq/si/international/length.h include/units/isq/si/international/speed.h
include/units/isq/si/international/volume.h
)

View File

@@ -35,7 +35,7 @@
namespace units::isq::si::international { namespace units::isq::si::international {
struct square_foot : derived_unit<square_foot, si::dim_area, si::international::foot> {}; struct square_foot : derived_scaled_unit<square_foot, si::dim_area, si::international::foot> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

View File

@@ -37,30 +37,30 @@ namespace units::isq::si::international {
// si::international yard // si::international yard
// https://en.wikipedia.org/wiki/International_yard_and_pound // https://en.wikipedia.org/wiki/International_yard_and_pound
struct yard : named_scaled_unit<yard, "yd", no_prefix, as_magnitude<ratio(9'144, 1'000, -1)>(), si::metre> {}; struct yard : named_scaled_unit<yard, "yd", as_magnitude<ratio(9'144, 1'000, -1)>(), si::metre> {};
// si::international foot // si::international foot
// https://en.wikipedia.org/wiki/Foot_(unit)#International_foot // https://en.wikipedia.org/wiki/Foot_(unit)#International_foot
struct foot : named_scaled_unit<foot, "ft", no_prefix, as_magnitude<ratio(1, 3)>(), yard> {}; struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(1, 3)>(), yard> {};
// https://en.wikipedia.org/wiki/Fathom#International_fathom // https://en.wikipedia.org/wiki/Fathom#International_fathom
struct fathom : named_scaled_unit<fathom, "fathom", no_prefix, as_magnitude<2>(), yard> {}; struct fathom : named_scaled_unit<fathom, "fathom", as_magnitude<2>(), yard> {};
// si::international inch // si::international inch
// https://en.wikipedia.org/wiki/Inch#Equivalences // https://en.wikipedia.org/wiki/Inch#Equivalences
struct inch : named_scaled_unit<inch, "in", no_prefix, as_magnitude<ratio(1, 36)>(), yard> {}; struct inch : named_scaled_unit<inch, "in", as_magnitude<ratio(1, 36)>(), yard> {};
// intrnational mile // intrnational mile
// https://en.wikipedia.org/wiki/Mile#International_mile // https://en.wikipedia.org/wiki/Mile#International_mile
struct mile : named_scaled_unit<mile, "mi", no_prefix, as_magnitude<ratio(25'146, 15'625)>(), si::kilometre> {}; struct mile : named_scaled_unit<mile, "mi", as_magnitude<ratio(25'146, 15'625)>(), si::kilometre> {};
// si::international nautical mile // si::international nautical mile
// https://en.wikipedia.org/wiki/Nautical_mile // https://en.wikipedia.org/wiki/Nautical_mile
struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", no_prefix, as_magnitude<1852>(), si::metre> {}; struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", as_magnitude<1852>(), si::metre> {};
// thou // thou
// https://en.wikipedia.org/wiki/Thousandth_of_an_inch // https://en.wikipedia.org/wiki/Thousandth_of_an_inch
struct thou : named_scaled_unit<thou, "thou", no_prefix, as_magnitude<ratio(1, 1000)>(), inch> {}; struct thou : named_scaled_unit<thou, "thou", as_magnitude<ratio(1, 1000)>(), inch> {};
// mil - different name for thou // mil - different name for thou
// https://en.wikipedia.org/wiki/Thousandth_of_an_inch // https://en.wikipedia.org/wiki/Thousandth_of_an_inch

View File

@@ -34,7 +34,10 @@
namespace units::isq::si::international { namespace units::isq::si::international {
struct mile_per_hour : derived_unit<mile_per_hour, si::dim_speed, si::international::mile, si::hour> {}; struct mile_per_hour : derived_scaled_unit<mile_per_hour, si::dim_speed, si::international::mile, si::hour> {};
struct nautical_mile_per_hour :
derived_scaled_unit<nautical_mile_per_hour, si::dim_speed, si::international::nautical_mile, si::hour> {};
struct knot : alias_unit<nautical_mile_per_hour, "kn"> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS
@@ -48,10 +51,42 @@ constexpr auto operator"" _q_mi_per_h(unsigned long long l)
} }
constexpr auto operator"" _q_mi_per_h(long double l) { return si::speed<mile_per_hour, long double>(l); } constexpr auto operator"" _q_mi_per_h(long double l) { return si::speed<mile_per_hour, long double>(l); }
// nmi/h
constexpr auto operator"" _q_nmi_per_h(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return si::speed<nautical_mile_per_hour, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_nmi_per_h(long double l) { return si::speed<nautical_mile_per_hour, long double>(l); }
// kn
constexpr auto operator"" _q_kn(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return si::speed<knot, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_kn(long double l) { return si::speed<knot, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
namespace speed_references {
inline constexpr auto kn = reference<si::dim_speed, knot>{};
} // namespace speed_references
namespace references {
using namespace speed_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::international } // namespace units::isq::si::international
#ifndef UNITS_NO_ALIASES #ifndef UNITS_NO_ALIASES
@@ -61,6 +96,12 @@ namespace units::aliases::isq::si::international::inline speed {
template<Representation Rep = double> template<Representation Rep = double>
using mi_per_h = units::isq::si::speed<units::isq::si::international::mile_per_hour, Rep>; using mi_per_h = units::isq::si::speed<units::isq::si::international::mile_per_hour, Rep>;
template<Representation Rep = double>
using nmi_per_h = units::isq::si::speed<units::isq::si::international::nautical_mile_per_hour, Rep>;
template<Representation Rep = double>
using kn = units::isq::si::speed<units::isq::si::international::knot, Rep>;
} // namespace units::aliases::isq::si::international::inline speed } // namespace units::aliases::isq::si::international::inline speed
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -35,7 +35,7 @@
namespace units::isq::si::international { namespace units::isq::si::international {
struct cubic_foot : derived_unit<cubic_foot, si::dim_volume, si::international::foot> {}; struct cubic_foot : derived_scaled_unit<cubic_foot, si::dim_volume, si::international::foot> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

View File

@@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
add_units_module(si-typographic mp-units::si) add_units_module(
si-typographic DEPENDENCIES mp-units::si HEADERS include/units/isq/si/typographic/length.h
include/units/isq/si/typographic/typographic.h
)

View File

@@ -38,13 +38,11 @@ namespace units::isq::si::typographic {
// TODO Conflicts with (https://en.wikipedia.org/wiki/Pica_(typography)), verify correctness of below conversion factors // TODO Conflicts with (https://en.wikipedia.org/wiki/Pica_(typography)), verify correctness of below conversion factors
// and provide hyperlinks to definitions // and provide hyperlinks to definitions
struct pica_comp : struct pica_comp :
named_scaled_unit<pica_comp, "pica(comp)", no_prefix, as_magnitude<ratio(4233333, 1000000, -3)>(), si::metre> {}; named_scaled_unit<pica_comp, "pica(comp)", as_magnitude<ratio(4233333, 1000000, -3)>(), si::metre> {};
struct pica_prn : struct pica_prn : named_scaled_unit<pica_prn, "pica(prn)", as_magnitude<ratio(2108759, 500000, -3)>(), si::metre> {};
named_scaled_unit<pica_prn, "pica(prn)", no_prefix, as_magnitude<ratio(2108759, 500000, -3)>(), si::metre> {};
struct point_comp : struct point_comp :
named_scaled_unit<point_comp, "point(comp)", no_prefix, as_magnitude<ratio(1763889, 500000, -4)>(), si::metre> {}; named_scaled_unit<point_comp, "point(comp)", as_magnitude<ratio(1763889, 500000, -4)>(), si::metre> {};
struct point_prn : struct point_prn : named_scaled_unit<point_prn, "point(prn)", as_magnitude<ratio(1757299, 500000, -4)>(), si::metre> {};
named_scaled_unit<point_prn, "point(prn)", no_prefix, as_magnitude<ratio(1757299, 500000, -4)>(), si::metre> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS

Some files were not shown because too many files have changed in this diff Show More