Merge branch 'master' into chiphogg/switch-to-mag

This commit is contained in:
Chip Hogg
2022-05-12 16:12:01 +00:00
165 changed files with 2469 additions and 1523 deletions

View File

@@ -4,19 +4,25 @@ parse:
pargs:
nargs: 1
flags:
- ALL
- ALL
kwargs:
BREATHE_PROJECT: 1
CODE_SOURCE_DIR: 1
INSTALL_DIR: 1
CODE_DEPENDS: 1
DOCS_DEPENDS: 1
add_units_module:
pargs:
nargs: 1
kwargs:
DEPENDENCIES: +
HEADERS: +
enable_iwyu:
pargs:
flags:
- NO_FORWARD_DECLARATIONS
- QUOTED_INCLUDES_FIRST
- NO_COMMENTS
- NO_FORWARD_DECLARATIONS
- QUOTED_INCLUDES_FIRST
- NO_COMMENTS
kwargs:
MAPPING_FILE: 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:
push:
paths-ignore:
- 'docs/**'
- "docs/**"
pull_request:
paths-ignore:
- 'docs/**'
- "docs/**"
jobs:
build:
@@ -38,51 +38,108 @@ jobs:
fail-fast: false
matrix:
config:
- {
name: "Windows MSVC 14.2",
os: windows-2019,
compiler: { type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" }
}
- {
name: "Windows MSVC 14.3",
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 },
lib: "libstdc++11"
}
- {
name: "Ubuntu GCC-11",
os: ubuntu-20.04,
compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11", std: 20 },
lib: "libstdc++11"
}
- {
name: "Ubuntu Clang-12 + libstdc++11",
os: ubuntu-20.04,
compiler: { 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: "MacOS Apple Clang 13",
os: macos-11,
compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++", std: 20 }
}
- {
name: "Windows MSVC 14.2",
os: windows-2019,
compiler:
{ type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" },
}
- {
name: "Windows MSVC 14.3",
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,
},
lib: "libstdc++11",
}
- {
name: "Ubuntu GCC-11",
os: ubuntu-20.04,
compiler:
{
type: GCC,
version: 11,
cc: "gcc-11",
cxx: "g++-11",
std: 20,
},
lib: "libstdc++11",
}
- {
name: "Ubuntu Clang-12 + libstdc++11",
os: ubuntu-20.04,
compiler:
{
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
# - {
# name: "Ubuntu GCC 10.2.0",
@@ -90,8 +147,8 @@ jobs:
# compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
# docker_image: conanio/gcc10
# }
build_type: [ "Release", "Debug" ]
downcast_mode: [ "on", "auto" ]
build_type: ["Release", "Debug"]
downcast_mode: ["on", "auto"]
steps:
- uses: actions/checkout@v2
- uses: hendrikmuhs/ccache-action@v1
@@ -141,7 +198,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
python-version: "3.8"
- name: Install Conan Package Tools
run: |
pip install -U conan_package_tools

View File

@@ -25,14 +25,14 @@ name: CMake Test Package CI
on:
push:
paths-ignore:
- 'docs/**'
- 'example/**'
- 'test/**'
- "docs/**"
- "example/**"
- "test/**"
pull_request:
paths-ignore:
- 'docs/**'
- 'example/**'
- 'test/**'
- "docs/**"
- "example/**"
- "test/**"
jobs:
test_package:
@@ -42,46 +42,62 @@ jobs:
fail-fast: false
matrix:
config:
- {
name: "Windows MSVC 2019",
os: windows-latest,
compiler: { type: VISUAL, version: 16, cc: "", cxx: "" }
}
- {
name: "Ubuntu GCC 10.3.0",
os: ubuntu-20.04,
compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
lib: "libstdc++11"
}
- {
name: "Ubuntu GCC 11.1.0",
os: ubuntu-20.04,
compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" },
lib: "libstdc++11"
}
- {
name: "Ubuntu Clang 12.0.0 + libstdc++11",
os: ubuntu-20.04,
compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" },
lib: "libstdc++11"
}
- {
name: "Ubuntu Clang 12.0.0 + libc++",
os: ubuntu-20.04,
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" },
lib: "libc++"
}
- {
name: "MacOS Apple Clang 13",
os: macos-11,
compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++" }
}
- {
name: "Windows MSVC 2019",
os: windows-latest,
compiler: { type: VISUAL, version: 16, cc: "", cxx: "" },
}
- {
name: "Ubuntu GCC 10.3.0",
os: ubuntu-20.04,
compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
lib: "libstdc++11",
}
- {
name: "Ubuntu GCC 11.1.0",
os: ubuntu-20.04,
compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" },
lib: "libstdc++11",
}
- {
name: "Ubuntu Clang 12.0.0 + libstdc++11",
os: ubuntu-20.04,
compiler:
{ type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" },
lib: "libstdc++11",
}
- {
name: "Ubuntu Clang 12.0.0 + libc++",
os: ubuntu-20.04,
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" },
lib: "libc++",
}
- {
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
# - {
# name: "Ubuntu GCC 10.2.0",
@@ -89,7 +105,7 @@ jobs:
# compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" },
# docker_image: conanio/gcc10
# }
build_type: [ "Release", "Debug" ]
build_type: ["Release", "Debug"]
env:
CC: ${{ matrix.config.compiler.cc }}
@@ -151,7 +167,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
python-version: "3.8"
- name: Install Conan
shell: bash
run: |
@@ -185,13 +201,13 @@ jobs:
working-directory: build/${{ matrix.build_type }}
run: |
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
if: matrix.config.compiler.type != 'VISUAL'
shell: bash
working-directory: build/${{ matrix.build_type }}
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
shell: bash
working-directory: build/${{ matrix.build_type }}
@@ -208,14 +224,14 @@ jobs:
working-directory: test_package/build/${{ matrix.build_type }}
run: |
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 .
- name: Build test_package CMake (local build)
if: matrix.config.compiler.type != 'VISUAL'
shell: bash
working-directory: test_package/build/${{ matrix.build_type }}
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 .
- name: Build test_package CMake (installation)
if: matrix.config.compiler.type == 'VISUAL'
@@ -223,14 +239,14 @@ jobs:
working-directory: test_package/build/${{ matrix.build_type }}
run: |
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 .
- name: Build test_package CMake (installation)
if: matrix.config.compiler.type != 'VISUAL'
shell: bash
working-directory: test_package/build/${{ matrix.build_type }}
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 .
- name: Run test_package
shell: bash

3
.gitignore vendored
View File

@@ -40,6 +40,9 @@
/out/
_build/
# CMake
CMakeUserPresets.json
# Conan
*.pyc
/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
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}-13 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
RUN sudo install-packages \
g++-10 \
clang-12 \
clang-13 \
clang-format-15

View File

@@ -84,6 +84,7 @@ tasks:
cp default gcc11
cp default clang12
cp default clang13
cp default clang14
popd
conan profile update settings.compiler.version=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 settings.compiler=clang 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.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
exit
- name: gcc-10
@@ -149,6 +155,18 @@ tasks:
ctest -C Release
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. 🛠️"
- 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
init: |
gp sync-await conan-init

View File

@@ -2,7 +2,7 @@ default_stages: [commit]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v4.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -16,5 +16,19 @@ repos:
- id: cmake-format
additional_dependencies: ["cmakelang[YAML]"]
# - id: cmake-lint
# additional_dependencies: ["cmakelang"]
# exclude: "cmake/.*"
# additional_dependencies: ["cmakelang"]
# 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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
project(mp-units-dev LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -71,3 +71,7 @@ add_subdirectory(docs)
# add unit tests
enable_testing()
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__":
builder = ConanMultiPackager(
# package id
channel = "testing",
stable_branch_pattern = r"v\d+\.\d+\.\d+.*",
channel="testing",
stable_branch_pattern=r"v\d+\.\d+\.\d+.*",
# dependencies
build_policy = ["mp-units", "outdated"],
upload_dependencies = "all",
pip_install = ["sphinx", "recommonmark", "breathe"],
build_policy=["mp-units", "outdated"],
upload_dependencies="all",
pip_install=["sphinx", "recommonmark", "breathe"],
# 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)
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
# SOFTWARE.
from conans import ConanFile, tools
from conans.tools import Version, check_min_cppstd
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
from conans.errors import ConanInvalidConfiguration
import os, re
import os
import re
from conan import ConanFile
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):
name = "mp-units"
homepage = "https://github.com/mpusz/units"
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"
url = "https://github.com/mpusz/units"
settings = "os", "compiler", "build_type", "arch"
requires = (
"gsl-lite/0.38.1"
)
options = {
"downcast_mode": ["off", "on", "auto"],
"build_docs": [True, False]
}
default_options = {
"downcast_mode": "on",
"build_docs": True
}
requires = "gsl-lite/0.40.0"
options = {"downcast_mode": ["off", "on", "auto"], "build_docs": [True, False]}
default_options = {"downcast_mode": "on", "build_docs": True}
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"
@property
def _run_tests(self):
return tools.get_env("CONAN_RUN_TESTS", False)
return get_env("CONAN_RUN_TESTS", False)
@property
def _use_libfmt(self):
compiler = self.settings.compiler
version = Version(self.settings.compiler.version)
std_support = \
(compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23) or \
(compiler == "msvc" and version >= 193 and compiler.cppstd == 23)
std_support = (
compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23
) or (compiler == "msvc" and version >= 193 and compiler.cppstd == 23)
return not std_support
@property
def _use_range_v3(self):
compiler = self.settings.compiler
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
def _msvc_version(self):
compiler = self.settings.compiler
if (compiler.update):
if compiler.update:
return int(f"{compiler.version}{compiler.update}")
else:
return int(f"{compiler.version}0")
def set_version(self):
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(
r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content
).group(1)
self.version = version.strip()
def requirements(self):
@@ -92,12 +113,13 @@ class MPUnitsConan(ConanFile):
def build_requirements(self):
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")
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
version = Version(self.settings.compiler.version)
if compiler == "gcc":
@@ -108,10 +130,14 @@ class MPUnitsConan(ConanFile):
raise ConanInvalidConfiguration("mp-units requires at least clang++-12")
elif compiler == "apple-clang":
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":
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":
if self._msvc_version < 1928:
raise ConanInvalidConfiguration("mp-units requires at least MSVC 19.28")
@@ -146,16 +172,22 @@ class MPUnitsConan(ConanFile):
self.info.header_only()
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.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):
compiler = self.settings.compiler
# core
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
self.cpp_info.components["core"].includedirs = ["include"]
if compiler == "Visual Studio":
self.cpp_info.components["core"].cxxflags = ["/utf-8"]
if self._use_range_v3:
@@ -163,19 +195,60 @@ class MPUnitsConan(ConanFile):
# rest
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"].includedirs = ["include"]
if self._use_libfmt:
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
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"].includedirs = ["include"]
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-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"].includedirs = ["include"]
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"].includedirs = ["include"]
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"].includedirs = ["include"]
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["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**
- (!) 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
- 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: `floor()`, `ceil()`, and `round()` support added (thanks [@hofbi](https://github.com/hofbi))
- feat: `std::format` support for compliant compilers added
- feat: conversion helpers from `mp-units` to `std::chrono` types added
- feat: math functions can now be safely used with user-defined types
- feat: conversion from `quantity_point` to `std::chrono::time_point` added
- feat: `nautical_mile_per_hour` and `knot` added to `si::international` system
- (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock`
- fix: enable any prefixes for most of the named units (beside those that use prefixes already)
- fix: `hectare` definition fixed to be a prefixed version of `are` + other units
- fix: account for different dimensions in `quantity_point_cast`'s constraint
- 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: gsl-lite updated to 0.38.1
- build: catch2 updated to 2.13.7
- build: doxygen updated to 1.9.2
- build: linear algebra switched to wg21-linear_algebra/0.7.2
- build: gsl-lite updated to 0.40.0
- build: catch2 updated to 2.13.9
- build: doxygen updated to 1.9.4
- build: linear_algebra/0.7.0 switched to wg21-linear_algebra/0.7.2
- ci: VS2022, gcc-11, clang-13, clang-14, and AppleClang 13 support added
- ci: pre-commit support added (thanks [@hofbi](https://github.com/hofbi))
- docs: Project documentation updated
- docs: `CITATION.cff` file added
- docs: `CONTRIBUTING.md` updated
- **0.7.0 May 11, 2021**
- (!) refactor: `ScalableNumber` renamed to `Representation`

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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="456px" preserveAspectRatio="none" style="width:591px;height:456px;background:#FCFCFC;" version="1.1" viewBox="0 0 591 456" width="591px" zoomAndPan="magnify">
<defs />
<g>
<!--MD5=[197a77df23d290968e58c76a2239d979]
cluster Unit-->
<g id="cluster_Unit">
<a href="../../framework/units.html" target="_top" title="../../framework/units.html" xlink:actuate="onRequest" xlink:href="../../framework/units.html" xlink:show="new" xlink:title="../../framework/units.html" xlink:type="simple">
<rect height="443" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;fill:none;" width="578" x="7" y="7" />
<path d="M51,7 L51,16.2969 L41,26.2969 L7,26.2969 " fill="none" style="stroke:#181818;stroke-width:1.0;" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="34" x="10" y="20.9951">Unit</text>
</a>
</g> <!--MD5=[124cbcdfdb408a63d08476bd52d3bb38]
class scaled_unit-->
<g id="elem_scaled_unit">
<rect codeLine="12" fill="#F1F1F1" height="26.2969" id="scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="178" x="23" y="225" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="80" x="26" y="242.9951">scaled_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="90" x="114" y="222" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="88" x="115" y="234.1387">UnitRatio, Unit</text>
</g> <!--MD5=[c262fc293e71d96455ecd38c5cba51e9]
class prefixed_alias_unit-->
<a href="../../framework/units.html#aliased-units" target="_top" title="../../framework/units.html#aliased-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#aliased-units" xlink:show="new" xlink:title="../../framework/units.html#aliased-units" xlink:type="simple">
<g id="elem_prefixed_alias_unit">
<rect codeLine="14" fill="#F1F1F1" height="26.2969" id="prefixed_alias_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="269" x="280.5" y="408" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="133" x="283.5" y="425.9951">prefixed_alias_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="128" x="424.5" y="405" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="126" x="425.5" y="417.1387">Unit, Prefix, AliasUnit</text>
</g>
</a> <!--MD5=[80b1f1fe027b66c9bd530ac9502a064a]
class alias_unit-->
<a href="../../framework/units.html#aliased-units" target="_top" title="../../framework/units.html#aliased-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#aliased-units" xlink:show="new" xlink:title="../../framework/units.html#aliased-units" xlink:type="simple">
<g id="elem_alias_unit">
<rect codeLine="15" fill="#F1F1F1" height="26.2969" id="alias_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="155" x="337.5" y="347" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="67" x="340.5" y="364.9951">alias_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="80" x="415.5" y="344" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="78" x="416.5" y="356.1387">Unit, Symbol</text>
</g>
</a> <!--MD5=[26e0af737c6dfe4c6ad8ee7c79493d2e]
class derived_scaled_unit-->
<a href="../../framework/units.html#derived-scaled-units" target="_top" title="../../framework/units.html#derived-scaled-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#derived-scaled-units" xlink:show="new" xlink:title="../../framework/units.html#derived-scaled-units" xlink:type="simple">
<g id="elem_derived_deduced_unit">
<rect codeLine="16" fill="#F1F1F1" height="26.2969" id="derived_scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="308" x="261" y="286" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="157" x="264" y="303.9951">derived_scaled_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="143" x="429" y="283" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="141" x="430" y="295.1387">Dimension, Unit, Unit...</text>
</g>
</a> <!--MD5=[21a38f8b465de3a6a580896bb83abf03]
class derived_unit-->
<a href="../../framework/units.html#derived-unnamed-units" target="_top" title="../../framework/units.html#derived-unnamed-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#derived-unnamed-units" xlink:show="new" xlink:title="../../framework/units.html#derived-unnamed-units" xlink:type="simple">
<g id="elem_derived_unit">
<rect codeLine="17" fill="#F1F1F1" height="26.2969" id="derived_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="94" x="368" y="225" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="88" x="371" y="242.9951">derived_unit</text>
</g>
</a> <!--MD5=[002996a525ad7ee43e1a2ae0bbb7adb6]
class prefixed_unit-->
<a href="../../framework/units.html#prefixed-unit" target="_top" title="../../framework/units.html#prefixed-unit" xlink:actuate="onRequest" xlink:href="../../framework/units.html#prefixed-unit" xlink:show="new" xlink:title="../../framework/units.html#prefixed-unit" xlink:type="simple">
<g id="elem_prefixed_unit">
<rect codeLine="18" fill="#F1F1F1" height="26.2969" id="prefixed_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="169" x="330.5" y="164" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="93" x="333.5" y="181.9951">prefixed_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="68" x="434.5" y="161" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="66" x="435.5" y="173.1387">Prefix, Unit</text>
</g>
</a> <!--MD5=[3a0c8cf47fc662100af5bce8b7f7e204]
class named_scaled_unit-->
<a href="../../framework/units.html#named-scaled-units" target="_top" title="../../framework/units.html#named-scaled-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#named-scaled-units" xlink:show="new" xlink:title="../../framework/units.html#named-scaled-units" xlink:type="simple">
<g id="elem_named_scaled_unit">
<rect codeLine="19" fill="#F1F1F1" height="26.2969" id="named_scaled_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="263" x="283.5" y="103" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="137" x="286.5" y="120.9951">named_scaled_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="118" x="431.5" y="100" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="116" x="432.5" y="112.1387">Symbol, Ratio, Unit</text>
</g>
</a> <!--MD5=[5e57872b30d77ee0da3206dd3d117986]
class named_unit-->
<a href="../../framework/units.html#base-units" target="_top" title="../../framework/units.html#base-units" xlink:actuate="onRequest" xlink:href="../../framework/units.html#base-units" xlink:show="new" xlink:title="../../framework/units.html#base-units" xlink:type="simple">
<g id="elem_named_unit">
<rect codeLine="20" fill="#F1F1F1" height="26.2969" id="named_unit" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="139" x="345.5" y="42" />
<text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="84" x="348.5" y="59.9951">named_unit</text>
<rect fill="#FCFCFC" height="15.9688" style="stroke:#000000;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="47" x="440.5" y="39" />
<text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="45" x="441.5" y="51.1387">Symbol</text>
</g>
</a> <!--MD5=[d10f3427b03caf67d8b4e569e5f4936e]
reverse link scaled_unit to named_unit-->
<g id="link_scaled_unit_named_unit">
<path codeLine="22" d="M133.027,208.194 C158.437,172.883 205.676,115.067 261,85 C286.686,71.041 317.93,63.52 345.471,59.49 " fill="none" id="scaled_unit-backto-named_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="138.679,212.326,121.521,224.76,127.181,204.34,138.679,212.326" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[c4573f7b87c3262f7d3adc92106a39ed]
reverse link scaled_unit to named_scaled_unit-->
<g id="link_scaled_unit_named_scaled_unit">
<path codeLine="23" d="M145.911,212.637 C174.734,191.666 218.536,162.71 261,146 C279.262,138.814 299.451,133.292 319.011,129.068 " fill="none" id="scaled_unit-backto-named_scaled_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="149.884,218.407,129.672,224.769,141.505,207.191,149.884,218.407" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[65b74da07c0359a7bcc888d9c9b6e7d5]
reverse link scaled_unit to prefixed_unit-->
<g id="link_scaled_unit_prefixed_unit">
<path codeLine="24" d="M194.254,220.784 C215.93,216.246 239.344,211.391 261,207 C288.988,201.325 319.892,195.233 346.556,190.03 " fill="none" id="scaled_unit-backto-prefixed_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="195.542,227.667,174.53,224.927,192.664,213.966,195.542,227.667" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[29a2e6b65a8256359df6b41e4d3b7c7c]
reverse link scaled_unit to derived_unit-->
<g id="link_scaled_unit_derived_unit">
<path codeLine="25" d="M221.579,238 C271.79,238 328.764,238 367.604,238 " fill="none" id="scaled_unit-backto-derived_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="221.276,245,201.276,238,221.276,231,221.276,245" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[1916bf928027667941dfca121ed1aff3]
reverse link scaled_unit to derived_scaled_unit-->
<g id="link_scaled_unit_derived_deduced_unit">
<path codeLine="26" d="M197.3,255.089 C218.121,259.31 240.369,263.819 261,268 C290.086,273.894 322.282,280.418 349.606,285.954 " fill="none" id="scaled_unit-backto-derived_scaled_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="195.683,261.904,177.472,251.07,198.464,248.183,195.683,261.904" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[19d99332ae619b76851ceaa34f4e9014]
reverse link scaled_unit to alias_unit-->
<g id="link_scaled_unit_alias_unit">
<path codeLine="27" d="M145.982,263.005 C174.849,283.698 218.676,312.311 261,329 C285.078,338.494 312.484,345.219 337.384,349.919 " fill="none" id="scaled_unit-backto-alias_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="141.677,268.529,129.714,251.039,149.972,257.251,141.677,268.529" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[a61d68e6008f4d1392d92030b50774f1]
reverse link scaled_unit to prefixed_alias_unit-->
<g id="link_scaled_unit_prefixed_alias_unit">
<path codeLine="28" d="M133.104,267.552 C158.592,302.572 205.908,359.952 261,390 C275.157,397.7215 290.998,403.5283 306.976,407.8934 " fill="none" id="scaled_unit-backto-prefixed_alias_unit" style="stroke:#181818;stroke-width:1.0;" />
<polygon fill="none" points="127.332,271.513,121.559,251.125,138.786,263.462,127.332,271.513" style="stroke:#181818;stroke-width:1.0;" />
</g> <!--MD5=[f18d7856f7539404df991684234dc7ed]
@startuml
skinparam monochrome true
skinparam shadowing false
skinparam backgroundColor #fcfcfc
skinparam shadowing false
skinparam backgroundColor #fcfcfc
hide members
hide circle
hide members
hide circle
left to right direction
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]]
package Unit <<Frame>> [[../../framework/units.html]] {
prefix_family <|- - no_prefix
prefix_family <.. prefix
abstract scaled_unit<UnitRatio, Unit>
' prefix_family <.. named_unit
' prefix_family <.. named_scaled_unit
' prefix_family <.. named_derived_unit
' prefix_family <.. alias_unit
abstract prefixed_alias_unit<Unit, Prefix, AliasUnit> [[../../framework/units.html#aliased-units]]
abstract alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract derived_unit [[../../framework/units.html#derived-unnamed-units]]
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
abstract named_scaled_unit<Symbol, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
abstract named_unit<Symbol> [[../../framework/units.html#base-units]]
' prefix <.. prefixed_unit
' prefix <.. prefixed_alias_unit
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
}
scaled_unit <|- - named_unit
scaled_unit <|- - named_scaled_unit
scaled_unit <|- - prefixed_unit
scaled_unit <|- - derived_unit
scaled_unit <|- - derived_scaled_unit
scaled_unit <|- - alias_unit
scaled_unit <|- - prefixed_alias_unit
}
@enduml
@startuml
skinparam monochrome true
skinparam shadowing false
skinparam backgroundColor #fcfcfc
hide members
hide circle
left to right direction
package Unit <<Frame>> [[../../framework/units.html]] {
abstract 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)
PlantUML version 1.2022.5(Sat Apr 30 10:55:52 UTC 2022)
(GPL source distribution)
Java Runtime: Java(TM) SE Runtime Environment
JVM: Java HotSpot(TM) 64-Bit Server VM
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>
-->
</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.
"""
import os
import re
import sphinx_rtd_theme
import subprocess
from pygments.lexer import RegexLexer, include, bygroups, using, \
this, inherit, default, words
from pygments.lexer import (
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.token import Text, Comment, Operator, Keyword, Name, String, \
Number, Punctuation, Error
from sphinx.highlighting import lexers
class MyCFamilyLexer(RegexLexer):
#: optional Comment or Whitespace
_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+'
_ws = r"(?:\s|//.*?\n|/[*].*?[*]/)+"
# The trailing ?, rather than *, avoids a geometric performance drop here.
#: only one /* */ style comment
_ws1 = r'\s*(?:/[*].*?[*]/\s*)?'
_ws1 = r"\s*(?:/[*].*?[*]/\s*)?"
tokens = {
'whitespace': [
"whitespace": [
# preprocessor directives: without whitespace
(r'^#if\s+0', Comment.Preproc, 'if0'),
('^#', Comment.Preproc, 'macro'),
(r"^#if\s+0", Comment.Preproc, "if0"),
("^#", Comment.Preproc, "macro"),
# or with whitespace
('^(' + _ws1 + r')(#if\s+0)',
bygroups(using(this), Comment.Preproc), 'if0'),
('^(' + _ws1 + ')(#)',
bygroups(using(this), Comment.Preproc), 'macro'),
(r'\n', Text),
(r'\s+', Text),
(r'\\\n', Text), # line continuation
(r'//(\n|[\w\W]*?[^\\]\n)', Comment.Single),
(r'/(\\\n)?[*][\w\W]*?[*](\\\n)?/', Comment.Multiline),
(
"^(" + _ws1 + r")(#if\s+0)",
bygroups(using(this), Comment.Preproc),
"if0",
),
("^(" + _ws1 + ")(#)", bygroups(using(this), Comment.Preproc), "macro"),
(r"\n", Text),
(r"\s+", Text),
(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
(r'/(\\\n)?[*][\w\W]*', Comment.Multiline),
(r"/(\\\n)?[*][\w\W]*", Comment.Multiline),
],
'statements': [
(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'\*/', Error),
(r'[~!%^&*+=|?:<>/-]', Operator),
(r'[()\[\],.]', Punctuation),
(words(('asm', 'auto', 'break', 'case', '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),
"statements": [
(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"\*/", Error),
(r"[~!%^&*+=|?:<>/-]", Operator),
(r"[()\[\],.]", Punctuation),
(
words(
(
"asm",
"auto",
"break",
"case",
"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
(r'(__m(128i|128d|128|64))\b', Keyword.Reserved),
(r"(__m(128i|128d|128|64))\b", Keyword.Reserved),
# Microsoft-isms
(words((
'asm', 'int8', 'based', 'except', 'int16', '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),
(
words(
(
"asm",
"int8",
"based",
"except",
"int16",
"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': [
include('whitespace'),
"root": [
include("whitespace"),
# functions
(r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments
r'([a-zA-Z_]\w*)' # method name
r'(\s*\([^;]*?\))' # signature
r'([^;{]*)(\{)',
bygroups(using(this), Name.Function, using(this), using(this),
Punctuation),
'function'),
(
r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments
r"([a-zA-Z_]\w*)" # method name
r"(\s*\([^;]*?\))" # signature
r"([^;{]*)(\{)",
bygroups(
using(this), Name.Function, using(this), using(this), Punctuation
),
"function",
),
# function declarations
(r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments
r'([a-zA-Z_]\w*)' # method name
r'(\s*\([^;]*?\))' # signature
r'([^;]*)(;)',
bygroups(using(this), Name.Function, using(this), using(this),
Punctuation)),
default('statement'),
(
r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments
r"([a-zA-Z_]\w*)" # method name
r"(\s*\([^;]*?\))" # signature
r"([^;]*)(;)",
bygroups(
using(this), Name.Function, using(this), using(this), Punctuation
),
),
default("statement"),
],
'statement': [
include('whitespace'),
include('statements'),
('[{}]', Punctuation),
(';', Punctuation, '#pop'),
"statement": [
include("whitespace"),
include("statements"),
("[{}]", Punctuation),
(";", Punctuation, "#pop"),
],
'function': [
include('whitespace'),
include('statements'),
(';', Punctuation),
(r'\{', Punctuation, '#push'),
(r'\}', Punctuation, '#pop'),
"function": [
include("whitespace"),
include("statements"),
(";", Punctuation),
(r"\{", Punctuation, "#push"),
(r"\}", Punctuation, "#pop"),
],
'string': [
(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),
"string": [
(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'[^\\"\n]+', String), # all other characters
(r'\\\n', String), # line continuation
(r'\\', String), # stray backslash
(r"\\\n", String), # line continuation
(r"\\", String), # stray backslash
],
'macro': [
(r'(include)(' + _ws1 + r')([^\n]+)',
bygroups(Comment.Preproc, Text, Comment.PreprocFile)),
(r'[^/\n]+', Comment.Preproc),
(r'/[*](.|\n)*?[*]/', Comment.Multiline),
(r'//.*?\n', Comment.Single, '#pop'),
(r'/', Comment.Preproc),
(r'(?<=\\)\n', Comment.Preproc),
(r'\n', Comment.Preproc, '#pop'),
"macro": [
(
r"(include)(" + _ws1 + r")([^\n]+)",
bygroups(Comment.Preproc, Text, Comment.PreprocFile),
),
(r"[^/\n]+", Comment.Preproc),
(r"/[*](.|\n)*?[*]/", Comment.Multiline),
(r"//.*?\n", Comment.Single, "#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 = {
'size_t', 'ssize_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'}
"size_t",
"ssize_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 = {
'_Bool', '_Complex', 'int8_t', 'int16_t', 'int32_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'}
"_Bool",
"_Complex",
"int8_t",
"int16_t",
"int32_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 = {
'clockid_t', 'cpu_set_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'}
"clockid_t",
"cpu_set_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):
self.stdlibhighlighting = get_bool_opt(options, 'stdlibhighlighting', True)
self.c99highlighting = get_bool_opt(options, 'c99highlighting', True)
self.platformhighlighting = get_bool_opt(options, 'platformhighlighting', True)
self.stdlibhighlighting = get_bool_opt(options, "stdlibhighlighting", True)
self.c99highlighting = get_bool_opt(options, "c99highlighting", True)
self.platformhighlighting = get_bool_opt(options, "platformhighlighting", True)
RegexLexer.__init__(self, **options)
def get_tokens_unprocessed(self, text):
for index, token, value in \
RegexLexer.get_tokens_unprocessed(self, text):
for index, token, value in RegexLexer.get_tokens_unprocessed(self, text):
if token is Name:
if self.stdlibhighlighting and value in self.stdlib_types:
token = Keyword.Type
@@ -172,65 +332,147 @@ class MyCppLexer(MyCFamilyLexer):
"""
For C++ source code with preprocessor directives.
"""
name = 'My C++'
aliases = ['cpp', 'c++']
filenames = ['*.cpp', '*.hpp', '*.c++', '*.h++',
'*.cc', '*.hh', '*.cxx', '*.hxx',
'*.C', '*.H', '*.cp', '*.CPP']
mimetypes = ['text/x-c++hdr', 'text/x-c++src']
name = "My C++"
aliases = ["cpp", "c++"]
filenames = [
"*.cpp",
"*.hpp",
"*.c++",
"*.h++",
"*.cc",
"*.hh",
"*.cxx",
"*.hxx",
"*.C",
"*.H",
"*.cp",
"*.CPP",
]
mimetypes = ["text/x-c++hdr", "text/x-c++src"]
priority = 0.1
tokens = {
'statements': [
(words((
'catch', 'const_cast', 'delete', 'dynamic_cast', 'explicit',
'export', 'friend', 'mutable', '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'),
"statements": [
(
words(
(
"catch",
"const_cast",
"delete",
"dynamic_cast",
"explicit",
"export",
"friend",
"mutable",
"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
(r'(R)(")([^\\()\s]{,16})(\()((?:.|\n)*?)(\)\3)(")',
bygroups(String.Affix, String, String.Delimiter, String.Delimiter,
String, String.Delimiter, String)),
(
r'(R)(")([^\\()\s]{,16})(\()((?:.|\n)*?)(\)\3)(")',
bygroups(
String.Affix,
String,
String.Delimiter,
String.Delimiter,
String,
String.Delimiter,
String,
),
),
# 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
(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'0x[0-9a-fA-F\']+[LlUu]*', Number.Hex),
(r'0[0-7\']+[LlUu]*', Number.Oct),
(r'\d[\d\']*[LlUu]*', Number.Integer),
(
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"0x[0-9a-fA-F\']+[LlUu]*", Number.Hex),
(r"0[0-7\']+[LlUu]*", Number.Oct),
(r"\d[\d\']*[LlUu]*", Number.Integer),
inherit,
],
'root': [
"root": [
inherit,
# C++ Microsoft-isms
(words(('virtual_inheritance', 'uuidof', 'super', 'single_inheritance',
'multiple_inheritance', 'interface', 'event'),
prefix=r'__', suffix=r'\b'), Keyword.Reserved),
(
words(
(
"virtual_inheritance",
"uuidof",
"super",
"single_inheritance",
"multiple_inheritance",
"interface",
"event",
),
prefix=r"__",
suffix=r"\b",
),
Keyword.Reserved,
),
# Offload C++ extensions, http://offload.codeplay.com/
(r'__(offload|blockingoffload|outer)\b', Keyword.Pseudo),
(r"__(offload|blockingoffload|outer)\b", Keyword.Pseudo),
],
'classname': [
(r'[a-zA-Z_]\w*', Name.Class, '#pop'),
"classname": [
(r"[a-zA-Z_]\w*", Name.Class, "#pop"),
# template specification
(r'\s*(?=>)', Text, '#pop'),
(r"\s*(?=>)", Text, "#pop"),
],
}
def analyse_text(text):
if re.search('#include <[a-z_]+>', text):
if re.search("#include <[a-z_]+>", text):
return 0.2
if re.search('using namespace ', text):
if re.search("using namespace ", text):
return 0.4
lexers['cpp'] = MyCppLexer(startinline=True)
lexers["cpp"] = MyCppLexer(startinline=True)
# 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:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import subprocess, os, re
def get_version():
try:
with open('../src/CMakeLists.txt', 'r') as file:
with open("../src/CMakeLists.txt", "r") as file:
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()
except Exception:
return None
@@ -255,9 +498,9 @@ def get_version():
# -- Project information -----------------------------------------------------
project = 'mp-units'
copyright = '2018-present, Mateusz Pusz'
author = 'Mateusz Pusz'
project = "mp-units"
copyright = "2018-present, Mateusz Pusz"
author = "Mateusz Pusz"
# The major project version, used as the replacement for |version|.
version = get_version()
@@ -270,21 +513,21 @@ release = get_version()
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autosectionlabel',
'sphinx.ext.githubpages',
'sphinx.ext.graphviz',
'sphinx_rtd_theme',
'recommonmark',
'breathe'
"sphinx.ext.autosectionlabel",
"sphinx.ext.githubpages",
"sphinx.ext.graphviz",
"sphinx_rtd_theme",
"recommonmark",
"breathe",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# If true, Sphinx will warn about all references where the target cannot
# 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
# 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.
default_role = 'cpp:any'
default_role = "cpp:any"
# The default language to highlight source code in. The default is 'python3'.
# The value should be a valid Pygments lexer name (https://pygments.org/docs/lexers).
highlight_language = 'cpp'
highlight_language = "cpp"
# 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.
pygments_style = 'default'
pygments_style = "default"
# A list of prefixes that will be ignored when sorting C++ objects in the global
# index. For example ['awesome_lib::'].
cpp_index_common_prefix = ['units::']
cpp_index_common_prefix = ["units::"]
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
# A dictionary of options that influence the look and feel of the selected theme.
# These are theme-specific.
@@ -339,7 +582,7 @@ html_theme_options = {
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# If given, this must be the name of an image file (path relative to the
# configuration directory) that is the logo of the docs. It is placed at the
@@ -349,45 +592,45 @@ html_static_path = ['_static']
# These paths are either relative to html_static_path or fully qualified
# paths (eg. https://...)
html_css_files = [
'css/custom.css'
]
html_css_files = ["css/custom.css"]
# -- Breathe configuration ---------------------------------------------------
def configureDoxyfile(input_dir, output_dir):
with open('Doxyfile.in', 'r') as file:
with open("Doxyfile.in", "r") as file:
filedata = file.read()
filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir)
filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir)
filedata = filedata.replace("@DOXYGEN_INPUT_DIR@", input_dir)
filedata = filedata.replace("@DOXYGEN_OUTPUT_DIR@", output_dir)
with open('Doxyfile', 'w') as file:
with open("Doxyfile", "w") as file:
file.write(filedata)
# 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
# are paths to the folder containing the doxygen output for that project.
breathe_projects = {}
if read_the_docs_build:
input_dir = '../src'
output_dir = 'build'
input_dir = "../src"
output_dir = "build"
configureDoxyfile(input_dir, output_dir)
subprocess.call('doxygen', shell=True)
breathe_projects['mp-units'] = output_dir + '/xml'
subprocess.call("doxygen", shell=True)
breathe_projects["mp-units"] = output_dir + "/xml"
# This should match one of the keys in the breathe_projects dictionary and
# indicates which project should be used when the project is not specified on
# the directive.
breathe_default_project = 'mp-units'
breathe_default_project = "mp-units"
# 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
# take :members:, :private-members: and :undoc-members: options. By default,
# this is set to an empty list, which means no members are displayed.
breathe_default_members = ('members', )
breathe_default_members = ("members",)

View File

@@ -40,38 +40,22 @@ of a `scaled_unit` class template:
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
' 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 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 alias_unit<Unit, Symbol> [[../../framework/units.html#aliased-units]]
abstract derived_scaled_unit<Dimension, Unit, Unit...> [[../../framework/units.html#derived-scaled-units]]
abstract derived_unit [[../../framework/units.html#derived-unnamed-units]]
abstract prefixed_unit<Prefix, Unit> [[../../framework/units.html#prefixed-unit]]
abstract named_scaled_unit<Symbol, 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]]
abstract named_scaled_unit<Symbol, Ratio, Unit> [[../../framework/units.html#named-scaled-units]]
abstract named_unit<Symbol> [[../../framework/units.html#base-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 <|-- derived_scaled_unit
scaled_unit <|-- 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
`named_scaled_unit` class template::
struct minute : named_scaled_unit<minute, "min", no_prefix, ratio(60), second> {};
struct hour : named_scaled_unit<hour, "h", no_prefix, ratio(60), minute> {};
struct day : named_scaled_unit<hour, "d", no_prefix, ratio(24), hour> {};
struct minute : named_scaled_unit<minute, "min", ratio(60), second> {};
struct hour : named_scaled_unit<hour, "h", ratio(60), minute> {};
struct day : named_scaled_unit<day, "d", ratio(24), hour> {};
where `no_prefix` is a special tag type describing that the library should
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
The `ratio` type used in the definition is really similar to ``std::ratio`` but it takes
an additional ``Exponent`` template parameter that defines the exponent of the ratio.
Another important difference is the fact that the objects of that class are used
as class NTTPs rather then a type template parameter kind.
@@ -227,28 +208,26 @@ complete list of all the :term:`SI` prefixes supported by the library::
namespace si {
struct prefix : prefix_family {};
struct yocto : units::prefix<yocto, prefix, "y", ratio(1, 1, -24)> {};
struct zepto : units::prefix<zepto, prefix, "z", ratio(1, 1, -21)> {};
struct atto : units::prefix<atto, prefix, "a", ratio(1, 1, -18)> {};
struct femto : units::prefix<femto, prefix, "f", ratio(1, 1, -15)> {};
struct pico : units::prefix<pico, prefix, "p", ratio(1, 1, -12)> {};
struct nano : units::prefix<nano, prefix, "n", ratio(1, 1, -9)> {};
struct micro : units::prefix<micro, prefix, "µ", ratio(1, 1, -6)> {};
struct milli : units::prefix<milli, prefix, "m", ratio(1, 1, -3)> {};
struct centi : units::prefix<centi, prefix, "c", ratio(1, 1, -2)> {};
struct deci : units::prefix<deci, prefix, "d", ratio(1, 1, -1)> {};
struct deca : units::prefix<deca, prefix, "da", ratio(1, 1, 1)> {};
struct hecto : units::prefix<hecto, prefix, "h", ratio(1, 1, 2)> {};
struct kilo : units::prefix<kilo, prefix, "k", ratio(1, 1, 3)> {};
struct mega : units::prefix<mega, prefix, "M", ratio(1, 1, 6)> {};
struct giga : units::prefix<giga, prefix, "G", ratio(1, 1, 9)> {};
struct tera : units::prefix<tera, prefix, "T", ratio(1, 1, 12)> {};
struct peta : units::prefix<peta, prefix, "P", ratio(1, 1, 15)> {};
struct exa : units::prefix<exa, prefix, "E", ratio(1, 1, 18)> {};
struct zetta : units::prefix<zetta, prefix, "Z", ratio(1, 1, 21)> {};
struct yotta : units::prefix<yotta, prefix, "Y", ratio(1, 1, 24)> {};
struct yocto : units::prefix<yocto, "y", ratio(1, 1, -24)> {};
struct zepto : units::prefix<zepto, "z", ratio(1, 1, -21)> {};
struct atto : units::prefix<atto, "a", ratio(1, 1, -18)> {};
struct femto : units::prefix<femto, "f", ratio(1, 1, -15)> {};
struct pico : units::prefix<pico, "p", ratio(1, 1, -12)> {};
struct nano : units::prefix<nano, "n", ratio(1, 1, -9)> {};
struct micro : units::prefix<micro, ", ratio(1, 1, -6)> {};
struct milli : units::prefix<milli, "m", ratio(1, 1, -3)> {};
struct centi : units::prefix<centi, "c", ratio(1, 1, -2)> {};
struct deci : units::prefix<deci, "d", ratio(1, 1, -1)> {};
struct deca : units::prefix<deca, "da",ratio(1, 1, 1)> {};
struct hecto : units::prefix<hecto, "h", ratio(1, 1, 2)> {};
struct kilo : units::prefix<kilo, "k", ratio(1, 1, 3)> {};
struct mega : units::prefix<mega, "M", ratio(1, 1, 6)> {};
struct giga : units::prefix<giga, "G", ratio(1, 1, 9)> {};
struct tera : units::prefix<tera, "T", ratio(1, 1, 12)> {};
struct peta : units::prefix<peta, "P", ratio(1, 1, 15)> {};
struct exa : units::prefix<exa, "E", ratio(1, 1, 18)> {};
struct zetta : units::prefix<zetta, "Z", ratio(1, 1, 21)> {};
struct yotta : units::prefix<yotta, "Y", ratio(1, 1, 24)> {};
}
@@ -257,14 +236,12 @@ domain::
namespace iec80000 {
struct binary_prefix : prefix_family {};
struct kibi : units::prefix<kibi, binary_prefix, "Ki", ratio( 1'024)> {};
struct mebi : units::prefix<mebi, binary_prefix, "Mi", ratio( 1'048'576)> {};
struct gibi : units::prefix<gibi, binary_prefix, "Gi", ratio( 1'073'741'824)> {};
struct tebi : units::prefix<tebi, binary_prefix, "Ti", ratio( 1'099'511'627'776)> {};
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)> {};
struct kibi : units::prefix<kibi, "Ki", ratio( 1'024)> {};
struct mebi : units::prefix<mebi, "Mi", ratio( 1'048'576)> {};
struct gibi : units::prefix<gibi, "Gi", ratio( 1'073'741'824)> {};
struct tebi : units::prefix<tebi, "Ti", ratio( 1'099'511'627'776)> {};
struct pebi : units::prefix<pebi, "Pi", ratio( 1'125'899'906'842'624)> {};
struct exbi : units::prefix<exbi, "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::
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
``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.
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::
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 {
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
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
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
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
A concept matching only units of a specified dimension. Satisfied by all unit types that

View File

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

View File

@@ -4,9 +4,6 @@ Units
.. doxygenstruct:: units::scaled_unit
:members:
.. doxygenstruct:: units::unit
:members:
.. doxygenstruct:: units::named_unit
:members:
@@ -19,7 +16,7 @@ Units
.. doxygenstruct:: units::derived_unit
:members:
.. doxygenstruct:: units::named_derived_unit
.. doxygenstruct:: units::derived_scaled_unit
:members:
.. 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
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 .
@@ -345,7 +345,7 @@ differences:
mkdir my_project/build && cd my_project/build
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 .
@@ -360,7 +360,7 @@ to find it, it is enough to perform the following steps:
mkdir units/build && cd units/build
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>
@@ -392,7 +392,7 @@ step with the CMake build:
.. code-block:: shell
# ...
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
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
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``::
@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In case I decide it is reasonable to express my desks with SI prefixes the only thing I have
to change in the above code is to replace `no_prefix` with `isq::si::prefix`::
struct desk : named_scaled_unit<desk, "desk", si::prefix, ratio(3, 10), si::square_metre> {};
Now I can define a new unit named ``kilodesk``::
In case I decide it is reasonable to express my desks with SI prefixes, I can define
a new unit named ``kilodesk``::
struct kilodesk : prefixed_unit<kilodesk, si::kilo, desk> {};
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
for shipment and ``40`` such packages fit into my lorry. To express this with prefixes a new
prefix family and prefixes are needed::
for shipment and ``40`` such packages fit into my lorry. To express this new prefix definitions
are needed::
struct shipping_prefix : prefix_family {};
struct package : prefix<package, shipping_prefix, "pkg", ratio(6)> {};
struct lorry : prefix<lorry, shipping_prefix, "lorry", ratio(6 * 40)> {};
struct package : prefix<package, "pkg", ratio(6)> {};
struct lorry : prefix<lorry, "lorry", ratio(6 * 40)> {};
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 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 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
struct dim_desk_rate : derived_dimension<dim_desk_rate, square_metre_per_second,
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
// 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
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
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> {};
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::
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,
exponent<dim_people, 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>
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 {
struct foot : named_unit<foot, "ft", no_prefix> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {};
struct foot : named_unit<foot, "ft"> {};
struct yard : named_scaled_unit<yard, "yd", ratio(3), foot> {};
struct dim_length : base_dimension<"L", foot> {};
@@ -231,7 +225,7 @@ different systems:
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 dim_length : base_dimension<"L", metre> {};
@@ -241,8 +235,8 @@ different systems:
namespace fps {
struct foot : named_scaled_unit<foot, "ft", no_prefix, ratio(3'048, 1'000, -1), metre> {};
struct yard : named_scaled_unit<yard, "yd", no_prefix, ratio(3), foot> {};
struct foot : named_scaled_unit<foot, "ft", ratio(3'048, 1'000, -1), metre> {};
struct yard : named_scaled_unit<yard, "yd", ratio(3), 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
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
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
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.

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
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>`_
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::
using namespace std::math;

View File

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

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h>
#include <units/isq/si/mass.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", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass))
<< 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", "main guns",
fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns))
@@ -101,7 +102,7 @@ int main()
auto iowa = Ship{.length{ft<>(860.)},
.draft{ft<>(37.) + in<>(2.)},
.beam{ft<>(108.) + in<>(2.)},
.speed{knot<>(33)},
.speed{international::kn<>(33)},
.mass{lton<>(57'540)},
.mainGuns{in<>(16)},
.shellMass{lb<>(2700)},
@@ -112,7 +113,7 @@ int main()
auto kgv = Ship{.length{ft<>(745.1)},
.draft{ft<>(33.) + in<>(7.5)},
.beam{ft<>(103.2) + in<>(2.5)},
.speed{knot<>(28.3)},
.speed{international::kn<>(28.3)},
.mass{lton<>(42'245)},
.mainGuns{in<>(14)},
.shellMass{lb<>(1'590)},

View File

@@ -32,8 +32,8 @@ 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 foot : named_unit<foot, "ft"> {};
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {};
@@ -44,7 +44,7 @@ using length = quantity<dim_length, U, Rep>;
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 dim_length : base_dimension<"L", metre> {};
@@ -54,8 +54,8 @@ 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 foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {};
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
struct dim_length : base_dimension<"L", foot> {};

View File

@@ -22,6 +22,6 @@
cmake_minimum_required(VERSION 3.2)
add_library(glide_computer STATIC geographic.cpp include/geographic.h glide_computer.cpp include/glide_computer.h)
target_link_libraries(glide_computer PRIVATE mp-units::core-fmt PUBLIC mp-units::si)
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 example_utils)
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
#include "ranged_representation.h"
#include <units/bits/external/hacks.h>
#include <units/bits/fmt_hacks.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/length.h>
#include <units/quantity_kind.h>
#include <limits>
#include <numbers>
#include <ostream>
// IWYU pragma: begin_exports
@@ -34,88 +38,95 @@
namespace geographic {
template<typename Derived, typename Rep>
struct coordinate {
using value_type = Rep;
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_;
};
// TODO Change to `angle` dimension in degree unit when the work on magnitudes is done
template<typename T = double>
using latitude = units::dimensionless<units::one, ranged_representation<T, -90, 90>>;
struct latitude : coordinate<latitude, double> {
using coordinate::coordinate;
};
template<typename T = double>
using longitude = units::dimensionless<units::one, ranged_representation<T, -180, 180>>;
struct longitude : coordinate<longitude, double> {
using coordinate::coordinate;
};
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const latitude& lat)
template<class CharT, class Traits, typename T>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const latitude<T>& lat)
{
if (lat.value() > 0)
return os << "N" << lat.value();
if (lat.number() > 0)
return os << "N" << lat.number();
else
return os << "S" << -lat.value();
return os << "S" << -lat.number();
}
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const longitude& lon)
template<class CharT, class Traits, typename T>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const longitude<T>& lon)
{
if (lon.value() > 0)
return os << "E" << lon.value();
if (lon.number() > 0)
return os << "E" << lon.number();
else
return os << "W" << -lon.value();
return os << "W" << -lon.number();
}
inline namespace literals {
constexpr auto operator"" _N(unsigned long long v) { return latitude(static_cast<latitude::value_type>(v)); }
constexpr auto operator"" _N(long double v) { return latitude(static_cast<latitude::value_type>(v)); }
constexpr auto operator"" _S(unsigned long long v) { return latitude(-static_cast<latitude::value_type>(v)); }
constexpr auto operator"" _S(long double v) { return latitude(-static_cast<latitude::value_type>(v)); }
constexpr auto operator"" _E(unsigned long long v) { return longitude(static_cast<longitude::value_type>(v)); }
constexpr auto operator"" _E(long double v) { return longitude(static_cast<longitude::value_type>(v)); }
constexpr auto operator"" _W(unsigned long long v) { return longitude(-static_cast<longitude::value_type>(v)); }
constexpr auto operator"" _W(long double v) { return longitude(-static_cast<longitude::value_type>(v)); }
constexpr auto operator"" _N(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
constexpr auto operator"" _S(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
constexpr auto operator"" _E(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
constexpr auto operator"" _W(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
constexpr auto operator"" _N(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"" _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 geographic
template<>
class std::numeric_limits<geographic::latitude> : public numeric_limits<geographic::latitude::value_type> {
static constexpr auto min() noexcept { return geographic::latitude(-90); }
static constexpr auto lowest() noexcept { return geographic::latitude(-90); }
static constexpr auto max() noexcept { return geographic::latitude(90); }
template<typename T>
class std::numeric_limits<geographic::latitude<T>> : public numeric_limits<T> {
static constexpr auto min() noexcept { return geographic::latitude<T>(-90); }
static constexpr auto lowest() noexcept { return geographic::latitude<T>(-90); }
static constexpr auto max() noexcept { return geographic::latitude<T>(90); }
};
template<>
class std::numeric_limits<geographic::longitude> : public numeric_limits<geographic::longitude::value_type> {
static constexpr auto min() noexcept { return geographic::longitude(-180); }
static constexpr auto lowest() noexcept { return geographic::longitude(-180); }
static constexpr auto max() noexcept { return geographic::longitude(180); }
template<typename T>
class std::numeric_limits<geographic::longitude<T>> : public numeric_limits<T> {
static constexpr auto min() noexcept { return geographic::longitude<T>(-180); }
static constexpr auto lowest() noexcept { return geographic::longitude<T>(-180); }
static constexpr auto max() noexcept { return geographic::longitude<T>(180); }
};
template<>
struct STD_FMT::formatter<geographic::latitude> : formatter<geographic::latitude::value_type> {
template<typename T>
struct STD_FMT::formatter<geographic::latitude<T>> : formatter<T> {
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');
return formatter<geographic::latitude::value_type>::format(lat.value() > 0 ? lat.value() : -lat.value(), ctx);
using rep = TYPENAME geographic::latitude<T>::rep;
STD_FMT::format_to(ctx.out(), "{}", lat > rep{0} ? 'N' : 'S');
return formatter<T>::format(lat > rep{0} ? lat.number() : -lat.number(), ctx);
}
};
template<>
struct STD_FMT::formatter<geographic::longitude> : formatter<geographic::longitude::value_type> {
template<typename T>
struct STD_FMT::formatter<geographic::longitude<T>> : formatter<T> {
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');
return formatter<geographic::longitude::value_type>::format(lon.value() > 0 ? lon.value() : -lon.value(), ctx);
using rep = TYPENAME geographic::longitude<T>::rep;
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> {};
using distance = units::quantity_kind<horizontal_kind, units::isq::si::kilometre>;
template<typename T>
struct position {
latitude lat;
longitude lon;
latitude<T> lat;
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

View File

@@ -136,7 +136,7 @@ struct weather {
struct waypoint {
std::string name;
geographic::position pos;
geographic::position<long double> pos;
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;
};
#if UNITS_COMP_CLANG <= 13
#if UNITS_COMP_CLANG <= 14
template<QuantityOrQuantityPoint QQP, units::Quantity U>
estimation(state<QQP>, U) -> estimation<QQP>;

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232)
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 {

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232)
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 {

View File

@@ -32,7 +32,7 @@
// TODO Fix when Celsius is properly supported (#232)
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 {

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/power.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/mass.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))
<< STD_FMT::format("{:20} : {}\n", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed",
fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format(
"{:20} : {}\n", "speed",
fmt_line<si::speed<si::international::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power",
fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns",
@@ -108,7 +110,7 @@ int main()
auto iowa = Ship{.length{860._q_ft},
.draft{37._q_ft + 2._q_in},
.beam{108._q_ft + 2._q_in},
.speed{33_q_knot},
.speed{si::speed<si::international::knot>{33}},
.mass{57'540_q_lton},
.mainGuns{16_q_in},
.shellMass{2700_q_lb},
@@ -119,7 +121,7 @@ int main()
auto kgv = Ship{.length{745.1_q_ft},
.draft{33._q_ft + 7.5_q_in},
.beam{103.2_q_ft + 2.5_q_in},
.speed{28.3_q_knot},
.speed{si::speed<si::international::knot>{28.3}},
.mass{42'245_q_lton},
.mainGuns{14_q_in},
.shellMass{1'590_q_lb},

View File

@@ -28,6 +28,7 @@
#include <units/isq/si/fps/speed.h>
#include <units/isq/si/fps/time.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/mass.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))
<< STD_FMT::format("{:20} : {}\n", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed",
fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format(
"{:20} : {}\n", "speed",
fmt_line<si::speed<si::international::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power",
fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns",
@@ -112,7 +114,7 @@ int main()
auto iowa = Ship{.length{860. * ft},
.draft{37. * ft + 2. * in},
.beam{108. * ft + 2. * in},
.speed{33 * knot},
.speed{33 * units::isq::si::international::references::kn},
.mass{57'540 * lton},
.mainGuns{16 * in},
.shellMass{2700 * lb},
@@ -123,7 +125,7 @@ int main()
auto kgv = Ship{.length{745.1 * ft},
.draft{33. * ft + 7.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},
.mainGuns{14 * in},
.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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
project(mp-units VERSION 0.8.0 LANGUAGES CXX)
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
# 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)
add_library(mp-units-${name} INTERFACE)
target_link_libraries(mp-units-${name} INTERFACE ${ARGN})
# parse arguments
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(
mp-units-${name} ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/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
# 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)
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}>)
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
# 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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
# core library options
set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode")
@@ -34,7 +34,33 @@ include(CheckLibcxxInUse)
check_libcxx_in_use(${projectPrefix}LIBCXX)
# 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_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
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 U a base unit to be used for this base dimension
*/
template<basic_fixed_string Symbol, Unit U>
requires U::is_named
template<basic_fixed_string Symbol, NamedUnit U>
struct base_dimension {
static constexpr auto symbol = Symbol; ///< Unique base dimension identifier
using base_unit = U; ///< Base unit adopted for this dimension

View File

@@ -37,25 +37,14 @@
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
namespace detail {
template<PrefixFamily PF, ratio R>
template<ratio R>
struct prefix_base;
template<PrefixFamily PF, ratio R>
void to_prefix_base(const volatile prefix_base<PF, R>*);
template<ratio R>
void to_prefix_base(const volatile prefix_base<R>*);
} // namespace detail
@@ -87,9 +76,18 @@ void to_base_scaled_unit(const volatile scaled_unit<M, U>*);
template<typename 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
template<basic_fixed_string Symbol, Unit U>
requires U::is_named
template<basic_fixed_string Symbol, NamedUnit U>
struct base_dimension;
namespace detail {

View File

@@ -34,7 +34,7 @@ inline constexpr bool same_scaled_units = false;
template<typename... Es, Unit... Us>
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>
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>
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

View File

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

View File

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

View File

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

View File

@@ -32,26 +32,10 @@
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 {
template<PrefixFamily PF, ratio R>
struct prefix_base : downcast_base<prefix_base<PF, R>> {
using prefix_family = PF;
template<ratio R>
struct prefix_base : downcast_base<prefix_base<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
* symbol is used to prepend to the symbol of referenced unit
* - when printing the symbol of a scaled unit that was not predefined by the user but its
* factor matches ratio of a prefix from the specified prefix family, its symbol will be
* prepended to the symbol of the unit
* factor matches ratio of a prefix, its symbol will be prepended to the symbol of the unit
*
* @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 R factor to be used to scale a unit
*/
template<typename Child, PrefixFamily PF, basic_symbol_text Symbol, ratio R>
requires(!std::same_as<PF, no_prefix>)
struct prefix : downcast_dispatch<Child, detail::prefix_base<PF, R>, downcast_mode::on> {
template<typename Child, basic_symbol_text Symbol, ratio R>
struct prefix : downcast_dispatch<Child, detail::prefix_base<R>, downcast_mode::on> {
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));
};
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
template<typename T>
@@ -133,8 +139,7 @@ public:
template<typename Value>
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) :
number_(std::forward<Value>(v))
constexpr explicit(!detail::quantity_one<quantity>) quantity(Value&& v) : number_(std::forward<Value>(v))
{
}
@@ -252,9 +257,9 @@ public:
number_ *= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity& operator*=(const dimensionless<units::one, Rep2>& rhs)
requires requires(rep a, const Rep2 b) {
template<detail::quantity_one Q>
constexpr quantity& operator*=(const Q& rhs)
requires requires(rep a, const typename Q::rep b) {
{
a *= b
} -> std::same_as<rep&>;
@@ -276,15 +281,15 @@ public:
number_ /= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity& operator/=(const dimensionless<units::one, Rep2>& rhs)
requires requires(rep a, const Rep2 b) {
template<detail::quantity_one Q>
constexpr quantity& operator/=(const Q& rhs)
requires requires(rep a, const typename Q::rep b) {
{
a /= b
} -> 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();
return *this;
}
@@ -302,15 +307,15 @@ public:
return *this;
}
template<typename Rep2>
constexpr quantity& operator%=(const dimensionless<units::one, Rep2>& rhs)
requires(!floating_point_<rep>) && (!floating_point_<Rep2>) && requires(rep a, const Rep2 b) {
{
a %= b
} -> std::same_as<rep&>;
}
template<detail::quantity_one Q>
constexpr quantity& operator%=(const Q& rhs)
requires(!floating_point_<rep>) && (!floating_point_<typename Q::rep>) && requires(rep a, const typename Q::rep b) {
{
a %= b
} -> 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();
return *this;
}

View File

@@ -54,6 +54,10 @@ inline constexpr auto downcasted_kind_fn = [](auto q) {
template<QuantityKind QK>
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
/**
@@ -198,8 +202,8 @@ public:
q_ *= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity_kind& operator*=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator*=(const QK& rhs)
requires requires(quantity_type q) { q *= rhs.common(); }
{
q_ *= rhs.common();
@@ -214,8 +218,8 @@ public:
q_ /= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity_kind& operator/=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator/=(const QK& rhs)
requires requires(quantity_type q) { q /= rhs.common(); }
{
q_ /= rhs.common();
@@ -233,8 +237,7 @@ public:
template<QuantityKind QK>
constexpr quantity_kind& operator%=(const QK& rhs)
requires(QuantityKindEquivalentTo<QK, quantity_kind> ||
std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
requires(QuantityKindEquivalentTo<QK, quantity_kind> || detail::quantity_kind_one<QK, K>) &&
requires(quantity_type q) { q %= rhs.common(); }
{
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_);
}
constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&a)[M + 1]) noexcept :
standard_(std), ascii_(a)
constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&ascii)[M + 1]) noexcept :
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,
const basic_fixed_string<char, M>& a) noexcept :
standard_(std), ascii_(a)
const basic_fixed_string<char, M>& ascii) noexcept :
standard_(std), ascii_(ascii)
{
detail::validate_ascii_string<M>(a.data_);
detail::validate_ascii_string<M>(ascii.data_);
}
[[nodiscard]] constexpr auto& standard() { return standard_; }

View File

@@ -26,7 +26,7 @@
#include <units/bits/external/downcasting.h>
// 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/magnitude.h>
#include <units/prefix.h>
@@ -36,6 +36,13 @@
namespace units {
namespace detail {
template<typename>
inline constexpr bool can_be_prefixed = false;
} // namespace detail
/**
* @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>
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
*
* Defines a named (in most cases coherent) unit that is then passed to a dimension definition.
* A named unit may be used by other units defined with the prefix of the same type, unless
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
* a prefix unit based on this one).
* A named unit may be composed with a prefix to create a prefixed_unit.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @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>> {
static constexpr bool is_named = true;
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
* other units defined with the prefix of the same type, unless no_prefix is provided for PF
* template parameter (in such a case it is impossible to define a prefix unit based on this
* one).
* Defines a new named unit that is a scaled version of another unit.
* A named unit may be composed with a prefix to create a prefixed_unit.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @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 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>> {
static constexpr bool is_named = true;
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 U reference unit
*/
template<typename Child, Prefix P, Unit U>
requires U::is_named && std::same_as<typename P::prefix_family, typename U::prefix_family>
template<typename Child, Prefix P, NamedUnit U>
requires detail::can_be_prefixed<U>
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;
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<ratio(1), Child>> {};
/**
* @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 URest the units for the rest of dimensions from the recipe
*/
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true))
struct 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>
template<typename Child, DerivedDimension Dim, NamedUnit U, NamedUnit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol;
using prefix_family = PF;
struct derived_scaled_unit : downcast_dispatch<Child, detail::derived_scaled_unit<Dim, U, URest...>> {
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
};
/**
@@ -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
* 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
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
* a prefix unit based on this one).
* A alias unit may be composed with a prefix to create a prefixed_alias_unit.
*
* @tparam U Unit for which an alias is defined
* @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 {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol;
using prefix_family = PF;
};
/**
@@ -215,20 +176,55 @@ struct alias_unit : U {
// TODO gcc bug: 95015
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95015
// template<Unit U, Prefix P, AliasUnit AU>
// requires (!AliasUnit<U>) && std::same_as<typename P::prefix_family, typename AU::prefix_family>
template<Unit U, Prefix P, Unit AU>
requires AU::is_named && std::same_as<typename P::prefix_family, typename AU::prefix_family>
// requires (!AliasUnit<U>)
template<Unit U, Prefix P, NamedUnit AU>
requires detail::can_be_prefixed<AU>
struct prefixed_alias_unit : U {
static constexpr bool is_named = true;
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.
*/
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, ratio R, typename U>
void is_named_impl(const volatile named_scaled_unit<Child, Symbol, R, 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, ratio R, typename U>
void can_be_prefixed_impl(const volatile named_scaled_unit<Child, Symbol, R, 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<ratio R, typename U>
inline constexpr bool can_be_prefixed<scaled_unit<R, U>> = can_be_prefixed<typename U::reference>;
} // namespace detail
} // namespace units

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
# systems
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
# 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 {
struct binary_prefix : prefix_family {};
struct kibi : units::prefix<kibi, binary_prefix, "Ki", ratio(1'024)> {};
struct mebi : units::prefix<mebi, binary_prefix, "Mi", ratio(1'048'576)> {};
struct gibi : units::prefix<gibi, binary_prefix, "Gi", ratio(1'073'741'824)> {};
struct tebi : units::prefix<tebi, binary_prefix, "Ti", ratio(1'099'511'627'776)> {};
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)> {};
struct kibi : units::prefix<kibi, "Ki", ratio(1'024)> {};
struct mebi : units::prefix<mebi, "Mi", ratio(1'048'576)> {};
struct gibi : units::prefix<gibi, "Gi", ratio(1'073'741'824)> {};
struct tebi : units::prefix<tebi, "Ti", ratio(1'099'511'627'776)> {};
struct pebi : units::prefix<pebi, "Pi", ratio(1'125'899'906'842'624)> {};
struct exbi : units::prefix<exbi, "Ei", ratio(1'152'921'504'606'846'976)> {};
} // namespace units::isq::iec80000

View File

@@ -34,7 +34,7 @@
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 megabaud : prefixed_alias_unit<si::megahertz, si::mega, baud> {};
struct gigabaud : prefixed_alias_unit<si::gigahertz, si::giga, baud> {};

View File

@@ -35,7 +35,8 @@
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 megabit : prefixed_unit<megabit, si::mega, 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 yottabit : prefixed_unit<yottabit, si::yotta, bit> {};
struct binary_prefix_bit : alias_unit<bit, "bit", binary_prefix> {};
struct kibibit : prefixed_unit<kibibit, kibi, binary_prefix_bit> {};
struct mebibit : prefixed_unit<mebibit, mebi, binary_prefix_bit> {};
struct gibibit : prefixed_unit<gibibit, gibi, binary_prefix_bit> {};
struct tebibit : prefixed_unit<tebibit, tebi, binary_prefix_bit> {};
struct pebibit : prefixed_unit<pebibit, pebi, binary_prefix_bit> {};
struct exbibit : prefixed_unit<exbibit, exbi, binary_prefix_bit> {};
struct kibibit : prefixed_unit<kibibit, kibi, bit> {};
struct mebibit : prefixed_unit<mebibit, mebi, bit> {};
struct gibibit : prefixed_unit<gibibit, gibi, bit> {};
struct tebibit : prefixed_unit<tebibit, tebi, bit> {};
struct pebibit : prefixed_unit<pebibit, pebi, bit> {};
struct exbibit : prefixed_unit<exbibit, exbi, 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 megabyte : prefixed_unit<megabyte, si::mega, 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 yottabyte : prefixed_unit<yottabyte, si::yotta, byte> {};
struct binary_prefix_byte : alias_unit<byte, "B", binary_prefix> {};
struct kibibyte : prefixed_unit<kibibyte, kibi, binary_prefix_byte> {};
struct mebibyte : prefixed_unit<mebibyte, mebi, binary_prefix_byte> {};
struct gibibyte : prefixed_unit<gibibyte, gibi, binary_prefix_byte> {};
struct tebibyte : prefixed_unit<tebibyte, tebi, binary_prefix_byte> {};
struct pebibyte : prefixed_unit<pebibyte, pebi, binary_prefix_byte> {};
// struct exbibyte : prefixed_unit<exbibyte, exbi, binary_prefix_byte> {};
struct kibibyte : prefixed_unit<kibibyte, kibi, byte> {};
struct mebibyte : prefixed_unit<mebibyte, mebi, byte> {};
struct gibibyte : prefixed_unit<gibibyte, gibi, byte> {};
struct tebibyte : prefixed_unit<tebibyte, tebi, byte> {};
struct pebibyte : prefixed_unit<pebibyte, pebi, byte> {};
// struct exbibyte : prefixed_unit<exbibyte, exbi, byte> {};
struct dim_storage_capacity : base_dimension<"M", byte> {};

View File

@@ -33,7 +33,7 @@
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> {};

View File

@@ -34,19 +34,19 @@
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 :
derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>,
exponent<si::dim_time, -1>> {};
struct kilobyte_per_second : derived_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 gigabyte_per_second : derived_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 petabyte_per_second : derived_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 zettabyte_per_second : derived_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 kilobyte_per_second : derived_scaled_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
struct megabyte_per_second : derived_scaled_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
struct gigabyte_per_second : derived_scaled_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
struct terabyte_per_second : derived_scaled_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
struct petabyte_per_second : derived_scaled_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
struct exabyte_per_second : derived_scaled_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
struct zettabyte_per_second : derived_scaled_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
struct yottabyte_per_second : derived_scaled_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
template<typename T>
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
# 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 {
struct electronvolt : named_unit<electronvolt, "eV", si::prefix> {};
struct electronvolt : named_unit<electronvolt, "eV"> {};
struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, si::giga, electronvolt> {};
struct inverted_gigaelectronvolt :
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"}, no_prefix> {};
struct inverted_gigaelectronvolt : named_unit<inverted_gigaelectronvolt, basic_symbol_text{"GeV⁻¹", "GeV^-1"}> {};
struct square_gigaelectronvolt : named_unit<square_gigaelectronvolt, basic_symbol_text{"GeV²", "GeV^2"}> {};
// 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

View File

@@ -20,6 +20,54 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# 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
#include <units/concepts.h>
#include <units/isq/dimensions/mass.h>
#include <units/isq/dimensions/speed.h>
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
# 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 {
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> {};
template<UnitOf<dim_acceleration> U, Representation Rep = double>

View File

@@ -35,7 +35,7 @@
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> {};

View File

@@ -36,7 +36,7 @@
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> {};

View File

@@ -34,7 +34,7 @@
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> {};

View File

@@ -36,7 +36,7 @@
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> {};

View File

@@ -34,7 +34,7 @@
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> {};
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
# 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 {
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> {};
template<UnitOf<dim_acceleration> U, Representation Rep = double>

View File

@@ -34,7 +34,7 @@
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> {};

View File

@@ -34,7 +34,7 @@
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> {};

View File

@@ -35,12 +35,12 @@
namespace units::isq::si::fps {
// 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> {};
// 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>
using energy = quantity<dim_energy, U, Rep>;

View File

@@ -37,16 +37,15 @@
namespace units::isq::si::fps {
// 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)
struct pound_force :
named_scaled_unit<pound_force, "lbf", si::prefix, as_magnitude<ratio(32'174'049, 1'000'000)>(), poundal> {};
struct pound_force : named_scaled_unit<pound_force, "lbf", as_magnitude<ratio(32'174'049, 1'000'000)>(), poundal> {};
struct kilopound_force : prefixed_unit<kilopound_force, si::kilo, pound_force> {};
// 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> {};

View File

@@ -29,30 +29,27 @@
#include <units/symbol_text.h>
// IWYU pragma: end_exports
#include <units/isq/si/length.h>
#include <units/isq/si/international/length.h>
#include <units/unit.h>
namespace units::isq::si::fps {
// 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> {};
struct inch : named_scaled_unit<inch, "in", no_prefix, as_magnitude<ratio(1, 12)>(), foot> {};
using si::international::fathom;
using si::international::foot;
using si::international::inch;
using si::international::mil;
using si::international::thou;
using si::international::yard;
// thousandth of an inch
struct thousandth : named_scaled_unit<thousandth, "thou", no_prefix, as_magnitude<ratio(1, 1'000)>(), inch> {};
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 thousandth : alias_unit<thou, "thou"> {};
struct kiloyard : prefixed_unit<kiloyard, si::kilo, yard> {};
struct mile : named_scaled_unit<mile, "mile", no_prefix, as_magnitude<5'280>(), foot> {};
struct mile : named_scaled_unit<mile, "mile", as_magnitude<5'280>(), foot> {};
struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", no_prefix, as_magnitude<2'000>(), yard> {};
struct nautical_mile : named_scaled_unit<nautical_mile, "nmi", as_magnitude<2'000>(), yard> {};
struct dim_length : isq::dim_length<foot> {};

View File

@@ -35,29 +35,28 @@
namespace units::isq::si::fps {
// https://en.wikipedia.org/wiki/Pound_(mass)
struct pound :
named_scaled_unit<pound, "lb", no_prefix, as_magnitude<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
struct pound : named_scaled_unit<pound, "lb", as_magnitude<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
struct dim_mass : isq::dim_mass<pound> {};
template<UnitOf<dim_mass> U, Representation Rep = double>
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

View File

@@ -35,14 +35,14 @@
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 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 :
named_scaled_unit<horse_power, "hp", no_prefix, as_magnitude<550>(), foot_pound_force_per_second> {};
struct horse_power : named_scaled_unit<horse_power, "hp", as_magnitude<550>(), foot_pound_force_per_second> {};
template<UnitOf<dim_power> U, Representation Rep = double>
using power = quantity<dim_power, U, Rep>;

View File

@@ -36,7 +36,7 @@
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> {};
@@ -44,12 +44,11 @@ template<UnitOf<dim_pressure> U, Representation Rep = double>
using pressure = quantity<dim_pressure, U, Rep>;
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> {};
struct pound_force_per_inch_sq :
named_scaled_unit<pound_force_per_inch_sq, "psi", si::prefix, as_magnitude<ratio(1, 144)>(),
pound_force_per_foot_sq> {};
named_scaled_unit<pound_force_per_inch_sq, "psi", as_magnitude<ratio(1, 144)>(), 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> {};

View File

@@ -35,15 +35,15 @@
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> {};
template<UnitOf<dim_speed> U, Representation Rep = double>
using speed = quantity<dim_speed, U, Rep>;
struct mile_per_hour : derived_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 knot : alias_unit<nautical_mile_per_hour, "knot", no_prefix> {};
struct mile_per_hour : derived_scaled_unit<mile_per_hour, dim_speed, 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, "kn"> {};
#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); }
// 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));
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
@@ -82,7 +82,7 @@ constexpr auto operator"" _q_knot(long double l) { return speed<knot, long doubl
namespace speed_references {
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
@@ -105,7 +105,7 @@ using ft_per_s = units::isq::si::fps::speed<units::isq::si::fps::foot_per_second
template<Representation Rep = double>
using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>;
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

View File

@@ -34,10 +34,10 @@
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 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>
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
# 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>
// IWYU pragma: end_exports
#include <units/isq/si/length.h>
#include <units/isq/si/area.h>
#include <units/unit.h>
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
// 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
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 zepto_barn : prefixed_unit<zepto_barn, zepto, 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 {
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> {};
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> {};
@@ -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 YeV_per_c2 : prefixed_unit<YeV_per_c2, yotta, eV_per_c2> {};
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)>(),
kilogram> {};
named_scaled_unit<eV_per_c2, "m_e", as_magnitude<ratio(9'109'383'701'528, 1'000'000'000'000, -31)>(), kilogram> {};
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)>(),
kilogram> {};
named_scaled_unit<eV_per_c2, "m_p", as_magnitude<ratio(1'672'621'923'695, 1'000'000'000'000, -27)>(), kilogram> {};
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)>(),
kilogram> {};
named_scaled_unit<eV_per_c2, "m_n", as_magnitude<ratio(1'674'927'498'049, 1'000'000'000'000, -27)>(), kilogram> {};
struct dim_mass : isq::dim_mass<eV_per_c2> {};

View File

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

View File

@@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# 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 {
// 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)
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

View File

@@ -20,6 +20,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# 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 {
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

View File

@@ -37,30 +37,30 @@ namespace units::isq::si::international {
// si::international yard
// 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
// 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
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
// 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
// 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
// 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
// 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
// https://en.wikipedia.org/wiki/Thousandth_of_an_inch

View File

@@ -34,7 +34,10 @@
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
@@ -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); }
// 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
#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
#ifndef UNITS_NO_ALIASES
@@ -61,6 +96,12 @@ namespace units::aliases::isq::si::international::inline speed {
template<Representation Rep = double>
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
#endif // UNITS_NO_ALIASES

View File

@@ -35,7 +35,7 @@
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

View File

@@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# 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
// and provide hyperlinks to definitions
struct pica_comp :
named_scaled_unit<pica_comp, "pica(comp)", no_prefix, as_magnitude<ratio(4233333, 1000000, -3)>(), si::metre> {};
struct pica_prn :
named_scaled_unit<pica_prn, "pica(prn)", no_prefix, as_magnitude<ratio(2108759, 500000, -3)>(), si::metre> {};
named_scaled_unit<pica_comp, "pica(comp)", as_magnitude<ratio(4233333, 1000000, -3)>(), si::metre> {};
struct pica_prn : named_scaled_unit<pica_prn, "pica(prn)", as_magnitude<ratio(2108759, 500000, -3)>(), si::metre> {};
struct point_comp :
named_scaled_unit<point_comp, "point(comp)", no_prefix, as_magnitude<ratio(1763889, 500000, -4)>(), si::metre> {};
struct point_prn :
named_scaled_unit<point_prn, "point(prn)", no_prefix, as_magnitude<ratio(1757299, 500000, -4)>(), si::metre> {};
named_scaled_unit<point_comp, "point(comp)", as_magnitude<ratio(1763889, 500000, -4)>(), si::metre> {};
struct point_prn : named_scaled_unit<point_prn, "point(prn)", as_magnitude<ratio(1757299, 500000, -4)>(), si::metre> {};
#ifndef UNITS_NO_LITERALS

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