Merge branch 'master' into downcast_mode_off

This commit is contained in:
Mateusz Pusz
2022-05-09 19:12:02 +02:00
committed by GitHub
175 changed files with 6360 additions and 4102 deletions

47
.cmake-format.yaml Normal file
View File

@@ -0,0 +1,47 @@
parse:
additional_commands:
add_documentation:
pargs:
nargs: 1
flags:
- 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
kwargs:
MAPPING_FILE: 1
MAX_LINE_LENGTH: 1
metabench_add_chart:
pargs:
nargs: 1
kwargs:
TITLE: 1
SUBTITLE: 1
DATASETS: +
format:
line_width: 120
tab_size: 4
max_subgroups_hwrap: 3
max_pargs_hwrap: 6
max_rows_cmdline: 2
dangle_parens: true
min_prefix_chars: 8
max_prefix_chars: 8
max_lines_hwrap: 2
markup:
enable_markup: false

View File

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

3
.gitignore vendored
View File

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

View File

@@ -10,10 +10,11 @@ repos:
# rev: v1.3.5 # rev: v1.3.5
# hooks: # hooks:
# - id: clang-format # - id: clang-format
# - repo: https://github.com/cheshirekow/cmake-format-precommit - repo: https://github.com/cheshirekow/cmake-format-precommit
# rev: v0.6.13 rev: v0.6.13
# hooks: hooks:
# - id: cmake-format - id: cmake-format
# additional_dependencies: ["cmakelang"] additional_dependencies: ["cmakelang[YAML]"]
# - id: cmake-lint # - id: cmake-lint
# additional_dependencies: ["cmakelang"] # additional_dependencies: ["cmakelang"]
# exclude: "cmake/.*"

View File

@@ -20,10 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
project(mp-units-dev project(mp-units-dev LANGUAGES CXX)
LANGUAGES CXX
)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -50,8 +48,7 @@ if(${projectPrefix}IWYU)
include(include-what-you-use) include(include-what-you-use)
enable_iwyu( enable_iwyu(
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp" MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
NO_FORWARD_DECLARATIONS NO_FORWARD_DECLARATIONS QUOTED_INCLUDES_FIRST
QUOTED_INCLUDES_FIRST
MAX_LINE_LENGTH 120 MAX_LINE_LENGTH 120
NO_COMMENTS NO_COMMENTS
) )
@@ -74,3 +71,7 @@ add_subdirectory(docs)
# add unit tests # add unit tests
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
# tests for standalone headers
include(TestPublicHeaders)
add_public_header_test(test_headers mp-units::mp-units)

View File

@@ -1,11 +1,7 @@
# Look for an executable called sphinx-build # Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
# Handle standard arguments to find_package like REQUIRED and QUIET # Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)

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

@@ -134,7 +134,7 @@ function(enable_ccache)
endif() endif()
if("${_ccache_version}" VERSION_LESS 3.3.0) if("${_ccache_version}" VERSION_LESS 3.3.0)
list(APPEND _ccacheEnv CCACHE_CPP2=1) # avoids spurious warnings with some compilers for ccache older than 3.3 list(APPEND _ccacheEnv CCACHE_CPP2=1) # avoids spurious warnings with some compilers for ccache older than 3.3
endif() endif()
if(_enable_ccache_MODE STREQUAL DIRECT_DEPEND) if(_enable_ccache_MODE STREQUAL DIRECT_DEPEND)
@@ -188,25 +188,18 @@ function(enable_ccache)
if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles") if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles")
foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA) foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA)
set(CMAKE_${_lang}_COMPILER_LAUNCHER set(CMAKE_${_lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${_ccacheEnv} ${CCACHE_PATH} PARENT_SCOPE)
${CMAKE_COMMAND} -E env
${_ccacheEnv} ${CCACHE_PATH}
PARENT_SCOPE
)
endforeach() endforeach()
elseif(CMAKE_GENERATOR STREQUAL Xcode) elseif(CMAKE_GENERATOR STREQUAL Xcode)
# Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options. # Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options.
# A separate launch script needs to be written out and the project variables pointed at them. # A separate launch script needs to be written out and the project variables pointed at them.
foreach(_lang IN ITEMS C CXX) foreach(_lang IN ITEMS C CXX)
set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang}) set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang})
file(WRITE ${launch${_lang}} "#!/bin/bash\n\n") file(WRITE ${launch${_lang}} "#!/bin/bash\n\n")
foreach(keyVal IN LISTS _ccacheEnv) foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n") file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach() endforeach()
file(APPEND ${launch${_lang}} file(APPEND ${launch${_lang}} "exec \"${CCACHE_PROGRAM}\" " "\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n")
"exec \"${CCACHE_PROGRAM}\" "
"\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n"
)
execute_process(COMMAND chmod a+rx ${launch${_lang}}) execute_process(COMMAND chmod a+rx ${launch${_lang}})
endforeach() endforeach()
set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE) set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE)

View File

@@ -22,7 +22,8 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
find_package(Doxygen MODULE REQUIRED) # TODO Switch to CONFIG when Conan will start supporting imported executables in CMakeDeps find_package(Doxygen MODULE REQUIRED
)# TODO Switch to CONFIG when Conan will start supporting imported executables in CMakeDeps
find_package(Sphinx REQUIRED) find_package(Sphinx REQUIRED)
# #
@@ -80,16 +81,14 @@ function(add_documentation targetName)
set(_doxygenIndexFile "${DOXYGEN_OUTPUT_DIR}/xml/index.xml") set(_doxygenIndexFile "${DOXYGEN_OUTPUT_DIR}/xml/index.xml")
# Only regenerate Doxygen when the Doxyfile or given dependencies change # Only regenerate Doxygen when the Doxyfile or given dependencies change
add_custom_command(OUTPUT "${_doxygenIndexFile}" add_custom_command(
OUTPUT "${_doxygenIndexFile}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR}
COMMAND Doxygen::doxygen ARGS "${_doxyfile}" COMMAND Doxygen::doxygen ARGS "${_doxyfile}"
MAIN_DEPENDENCY "${_doxyfileIn}" MAIN_DEPENDENCY "${_doxyfileIn}"
DEPENDS DEPENDS "${_doxyfile}" "${_args_CODE_DEPENDS}"
"${_doxyfile}"
"${_args_CODE_DEPENDS}"
COMMENT "Generating doxygen XML metadata" COMMENT "Generating doxygen XML metadata"
USES_TERMINAL USES_TERMINAL VERBATIM
VERBATIM
) )
set(_sphinx_docs_dir "${CMAKE_CURRENT_BINARY_DIR}/sphinx") set(_sphinx_docs_dir "${CMAKE_CURRENT_BINARY_DIR}/sphinx")
@@ -99,16 +98,16 @@ function(add_documentation targetName)
# - Doxygen has rerun # - Doxygen has rerun
# - Our doc files have been updated # - Our doc files have been updated
# - The Sphinx config has been updated # - The Sphinx config has been updated
add_custom_command(OUTPUT "${_sphinx_index_file}" add_custom_command(
COMMAND "${SPHINX_EXECUTABLE}" ARGS -b html -j auto "-Dbreathe_projects.${_args_BREATHE_PROJECT}=${DOXYGEN_OUTPUT_DIR}/xml" "${_args_DOCS_SOURCE_DIR}" "${_sphinx_docs_dir}" OUTPUT "${_sphinx_index_file}"
COMMAND "${SPHINX_EXECUTABLE}" ARGS -b html -j auto
"-Dbreathe_projects.${_args_BREATHE_PROJECT}=${DOXYGEN_OUTPUT_DIR}/xml" "${_args_DOCS_SOURCE_DIR}"
"${_sphinx_docs_dir}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
MAIN_DEPENDENCY "${_args_DOCS_SOURCE_DIR}/conf.py" MAIN_DEPENDENCY "${_args_DOCS_SOURCE_DIR}/conf.py"
DEPENDS DEPENDS "${_doxygenIndexFile}" "${_args_DOCS_DEPENDS}"
"${_doxygenIndexFile}"
"${_args_DOCS_DEPENDS}"
COMMENT "Generating documentation with Sphinx" COMMENT "Generating documentation with Sphinx"
USES_TERMINAL USES_TERMINAL VERBATIM
VERBATIM
) )
# Custom target # Custom target
@@ -118,7 +117,7 @@ function(add_documentation targetName)
add_custom_target(${targetName} ${_all} DEPENDS "${_sphinx_index_file}") add_custom_target(${targetName} ${_all} DEPENDS "${_sphinx_index_file}")
if(_args_INSTALL_DIR) if(_args_INSTALL_DIR)
# Add an install step to install the docs # Add an install step to install the docs
install(DIRECTORY ${_sphinx_docs_dir} TYPE DOC) install(DIRECTORY ${_sphinx_docs_dir} TYPE DOC)
endif() endif()
endfunction() endfunction()

View File

@@ -48,7 +48,17 @@ macro(_enable_iwyu_failed log_postfix)
endmacro() endmacro()
macro(_process_iwyu_arguments offset log_postfix) macro(_process_iwyu_arguments offset log_postfix)
set(_options QUIET REQUIRED NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST) set(_options
QUIET
REQUIRED
NO_DEFAULT_MAPPINGS
PCH_IN_CODE
TRANSITIVE_INCLUDES_ONLY
NO_COMMENTS
NO_FORWARD_DECLARATIONS
CXX17_NAMESPACES
QUOTED_INCLUDES_FIRST
)
set(_one_value_args PROGRAM MAPPING_FILE MAX_LINE_LENGTH) set(_one_value_args PROGRAM MAPPING_FILE MAX_LINE_LENGTH)
set(_multi_value_args KEEP) set(_multi_value_args KEEP)
cmake_parse_arguments(PARSE_ARGV ${offset} _enable_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}") cmake_parse_arguments(PARSE_ARGV ${offset} _enable_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}")
@@ -160,7 +170,5 @@ endfunction()
# #
function(enable_target_iwyu target) function(enable_target_iwyu target)
_process_iwyu_arguments(1 " for '${target}'") _process_iwyu_arguments(1 " for '${target}'")
set_target_properties(${target} PROPERTIES set_target_properties(${target} PROPERTIES CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}")
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
)
endfunction() endfunction()

File diff suppressed because it is too large Load Diff

View File

@@ -23,9 +23,11 @@
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.4)
function(ensure_entry_point) function(ensure_entry_point)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt' is meant to be used only " message(FATAL_ERROR
"as a CMake entry point and should not be included from other CMake files. " "'${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt' is meant to be used only "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead.") "as a CMake entry point and should not be included from other CMake files. "
endif() "Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead."
)
endif()
endfunction() endfunction()

View File

@@ -70,9 +70,7 @@ macro(_set_flags)
-Wformat=2 # warn on security issues around functions that format output (ie printf) -Wformat=2 # warn on security issues around functions that format output (ie printf)
) )
set(CLANG_WARNINGS set(CLANG_WARNINGS ${GCC_COMMON_WARNINGS})
${GCC_COMMON_WARNINGS}
)
set(GCC_WARNINGS set(GCC_WARNINGS
${GCC_COMMON_WARNINGS} ${GCC_COMMON_WARNINGS}

View File

@@ -20,19 +20,33 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
from conans import ConanFile, tools from conan import ConanFile
from conans.tools import Version, check_min_cppstd
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
from conans.errors import ConanInvalidConfiguration from conan.tools.files import copy, load, rmdir
from conan.tools.scm import Version
from conans.tools import get_env, check_min_cppstd # TODO replace with new tools for Conan 2.0
import os, re import os, re
required_conan_version = ">=1.44.0" required_conan_version = ">=1.48.0"
class MPUnitsConan(ConanFile): class MPUnitsConan(ConanFile):
name = "mp-units" name = "mp-units"
homepage = "https://github.com/mpusz/units" homepage = "https://github.com/mpusz/units"
description = "Physical Units library for C++" description = "Physical Units library for C++"
topics = ("units", "dimensions", "quantities", "dimensional-analysis", "physical-quantities", "physical-units", "system-of-units", "cpp23", "cpp20", "library", "quantity-manipulation") topics = (
"units",
"dimensions",
"quantities",
"dimensional-analysis",
"physical-quantities",
"physical-units",
"system-of-units",
"cpp23",
"cpp20",
"library",
"quantity-manipulation",
)
license = "MIT" license = "MIT"
url = "https://github.com/mpusz/units" url = "https://github.com/mpusz/units"
settings = "os", "compiler", "build_type", "arch" settings = "os", "compiler", "build_type", "arch"
@@ -48,12 +62,13 @@ class MPUnitsConan(ConanFile):
"build_docs": True "build_docs": True
} }
exports = ["LICENSE.md"] exports = ["LICENSE.md"]
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"] exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*", "CMakeLists.txt"]
no_copy_source = True
generators = "cmake_paths" generators = "cmake_paths"
@property @property
def _run_tests(self): def _run_tests(self):
return tools.get_env("CONAN_RUN_TESTS", False) return get_env("CONAN_RUN_TESTS", False)
@property @property
def _use_libfmt(self): def _use_libfmt(self):
@@ -68,18 +83,18 @@ class MPUnitsConan(ConanFile):
def _use_range_v3(self): def _use_range_v3(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
return ("clang" in compiler and compiler.libcxx == "libc++" and version < 14) return "clang" in compiler and compiler.libcxx == "libc++" and version < 14
@property @property
def _msvc_version(self): def _msvc_version(self):
compiler = self.settings.compiler compiler = self.settings.compiler
if (compiler.update): if compiler.update:
return int(f"{compiler.version}{compiler.update}") return int(f"{compiler.version}{compiler.update}")
else: else:
return int(f"{compiler.version}0") return int(f"{compiler.version}0")
def set_version(self): def set_version(self):
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt")) content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
self.version = version.strip() self.version = version.strip()
@@ -97,7 +112,8 @@ class MPUnitsConan(ConanFile):
if self.options.build_docs: if self.options.build_docs:
self.tool_requires("doxygen/1.9.2") self.tool_requires("doxygen/1.9.2")
def validate(self): # TODO Replace with `valdate()` for Conan 2.0 (https://github.com/conan-io/conan/issues/10723)
def configure(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
if compiler == "gcc": if compiler == "gcc":
@@ -146,16 +162,17 @@ class MPUnitsConan(ConanFile):
self.info.header_only() self.info.header_only()
def package(self): def package(self):
self.copy("LICENSE.md", dst="licenses") copy(self, "LICENSE.md", self.source_folder, os.path.join(self.package_folder, "licenses"))
cmake = CMake(self) cmake = CMake(self)
cmake.install() cmake.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake")) rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
def package_info(self): def package_info(self):
compiler = self.settings.compiler compiler = self.settings.compiler
# core # core
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"] self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
self.cpp_info.components["core"].includedirs = ["include"]
if compiler == "Visual Studio": if compiler == "Visual Studio":
self.cpp_info.components["core"].cxxflags = ["/utf-8"] self.cpp_info.components["core"].cxxflags = ["/utf-8"]
if self._use_range_v3: if self._use_range_v3:
@@ -163,19 +180,60 @@ class MPUnitsConan(ConanFile):
# rest # rest
self.cpp_info.components["core-io"].requires = ["core"] self.cpp_info.components["core-io"].requires = ["core"]
self.cpp_info.components["core-io"].includedirs = ["include"]
self.cpp_info.components["core-fmt"].requires = ["core"] self.cpp_info.components["core-fmt"].requires = ["core"]
self.cpp_info.components["core-fmt"].includedirs = ["include"]
if self._use_libfmt: if self._use_libfmt:
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt") self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
self.cpp_info.components["isq"].requires = ["core"] self.cpp_info.components["isq"].requires = ["core"]
self.cpp_info.components["isq"].includedirs = ["include"]
self.cpp_info.components["isq-natural"].requires = ["isq"] self.cpp_info.components["isq-natural"].requires = ["isq"]
self.cpp_info.components["isq-natural"].includedirs = ["include"]
self.cpp_info.components["si"].requires = ["isq"] self.cpp_info.components["si"].requires = ["isq"]
self.cpp_info.components["si"].includedirs = ["include"]
self.cpp_info.components["si-cgs"].requires = ["si"] self.cpp_info.components["si-cgs"].requires = ["si"]
self.cpp_info.components["si-cgs"].includedirs = ["include"]
self.cpp_info.components["si-fps"].requires = ["si"] self.cpp_info.components["si-fps"].requires = ["si"]
self.cpp_info.components["si-fps"].includedirs = ["include"]
self.cpp_info.components["si-hep"].requires = ["si"] self.cpp_info.components["si-hep"].requires = ["si"]
self.cpp_info.components["si-hep"].includedirs = ["include"]
self.cpp_info.components["si-iau"].requires = ["si"] self.cpp_info.components["si-iau"].requires = ["si"]
self.cpp_info.components["si-iau"].includedirs = ["include"]
self.cpp_info.components["si-imperial"].requires = ["si"] self.cpp_info.components["si-imperial"].requires = ["si"]
self.cpp_info.components["si-imperial"].includedirs = ["include"]
self.cpp_info.components["si-international"].requires = ["si"] self.cpp_info.components["si-international"].requires = ["si"]
self.cpp_info.components["si-international"].includedirs = ["include"]
self.cpp_info.components["si-typographic"].requires = ["si"] self.cpp_info.components["si-typographic"].requires = ["si"]
self.cpp_info.components["si-typographic"].includedirs = ["include"]
self.cpp_info.components["si-uscs"].requires = ["si"] self.cpp_info.components["si-uscs"].requires = ["si"]
self.cpp_info.components["si-uscs"].includedirs = ["include"]
self.cpp_info.components["isq-iec80000"].requires = ["si"] self.cpp_info.components["isq-iec80000"].requires = ["si"]
self.cpp_info.components["systems"].requires = ["isq", "isq-natural", "si", "si-cgs", "si-fps", "si-hep", "si-iau", "si-imperial", "si-international", "si-typographic", "si-uscs", "isq-iec80000"] self.cpp_info.components["isq-iec80000"].includedirs = ["include"]
self.cpp_info.components["systems"].requires = [
"isq",
"isq-natural",
"si",
"si-cgs",
"si-fps",
"si-hep",
"si-iau",
"si-imperial",
"si-international",
"si-typographic",
"si-uscs",
"isq-iec80000",
]

View File

@@ -44,17 +44,13 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_1.png" "${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_1.png"
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_2.png" "${CMAKE_CURRENT_SOURCE_DIR}/_static/img/downcast_2.png"
"${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg" "${CMAKE_CURRENT_SOURCE_DIR}/_static/img/units.svg"
"${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md" "${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md"
"${CMAKE_CURRENT_SOURCE_DIR}/design.rst" "${CMAKE_CURRENT_SOURCE_DIR}/design.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst" "${CMAKE_CURRENT_SOURCE_DIR}/design/directories.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.rst" "${CMAKE_CURRENT_SOURCE_DIR}/design/downcasting.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity.rst" "${CMAKE_CURRENT_SOURCE_DIR}/design/quantity.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/design/quantity_kind.rst" "${CMAKE_CURRENT_SOURCE_DIR}/design/quantity_kind.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/avg_speed.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/avg_speed.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/box_example.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/box_example.rst"
@@ -66,17 +62,13 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/hello_units.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/hello_units.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/total_energy.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/total_energy.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/unknown_dimension.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/basics/unknown_dimension.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/linear_algebra.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/linear_algebra.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/measurement.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_representation/measurement.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems/custom_systems.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_systems/custom_systems.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities/conversion_factor.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/custom_utilities/conversion_factor.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_1.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_1.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_2.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_2.rst"
@@ -87,9 +79,7 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_7.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_7.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_8.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/example_8.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/kalman.rst" "${CMAKE_CURRENT_SOURCE_DIR}/examples/kalman_filter/kalman.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/faq.rst" "${CMAKE_CURRENT_SOURCE_DIR}/faq.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/framework.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/framework/arithmetics.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/arithmetics.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/basic_concepts.rst"
@@ -101,18 +91,16 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_points.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/quantity_points.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/framework/text_output.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/text_output.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/framework/units.rst" "${CMAKE_CURRENT_SOURCE_DIR}/framework/units.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/genindex.rst" "${CMAKE_CURRENT_SOURCE_DIR}/genindex.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/glossary.rst" "${CMAKE_CURRENT_SOURCE_DIR}/glossary.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/index.rst" "${CMAKE_CURRENT_SOURCE_DIR}/index.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/introduction.rst" "${CMAKE_CURRENT_SOURCE_DIR}/introduction.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/quick_start.rst" "${CMAKE_CURRENT_SOURCE_DIR}/quick_start.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/concepts.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/concepts.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/customization_points.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/customization_points.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/downcasting.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/downcasting.rst"
# "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/functions.rst" # "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/functions.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/metafunctions.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/metafunctions.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/dimensions.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/dimensions.rst"
@@ -128,26 +116,20 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_fixed_string.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_fixed_string.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_symbol_text.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/basic_symbol_text.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/ratio.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/core/types/utilities/ratio.rst"
# "${CMAKE_CURRENT_SOURCE_DIR}/reference/math.rst"
# "${CMAKE_CURRENT_SOURCE_DIR}/reference/math.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/random.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/random.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/angle.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/angle.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/dimensionless.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/dimensionless.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/unknown.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/generic/unknown.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/binary_prefixes.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/binary_prefixes.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/modulation_rate.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/modulation_rate.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/storage_capacity.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/storage_capacity.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/traffic_intensity.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/traffic_intensity.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/transfer_rate.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/iec80000/transfer_rate.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/acceleration.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/acceleration.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/constants.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/constants.rst"
@@ -159,7 +141,6 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/speed.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/speed.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/time.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/time.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/units.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/natural/units.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_cgs.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_cgs.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/acceleration.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/acceleration.rst"
@@ -172,9 +153,7 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/pressure.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/pressure.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/speed.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/speed.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/time.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/cgs/time.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/dimensions_and_concepts.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/dimensions_and_concepts.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_fps.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_fps.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/acceleration.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/acceleration.rst"
@@ -189,19 +168,15 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/speed.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/speed.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/time.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/time.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/volume.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/fps/volume.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_iau.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_iau.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/iau/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/iau/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_imperial.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_imperial.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/imperial/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/imperial/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_international.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_international.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/area.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/area.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/speed.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/speed.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/volume.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/international/volume.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/absorbed_dose.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/absorbed_dose.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/acceleration.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/acceleration.rst"
@@ -245,15 +220,11 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/time.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/time.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/voltage.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/voltage.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/volume.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/volume.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_typographic.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_typographic.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/typographic/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/typographic/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_uscs.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si_uscs.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/uscs/length.rst" "${CMAKE_CURRENT_SOURCE_DIR}/reference/systems/isq/si/uscs/length.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/references.rst" "${CMAKE_CURRENT_SOURCE_DIR}/references.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/custom_representation_types.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases/custom_representation_types.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/extensions.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases/extensions.rst"
@@ -262,14 +233,14 @@ set(unitsSphinxDocs
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/linear_algebra.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases/linear_algebra.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/natural_units.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases/natural_units.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/use_cases/unknown_dimensions.rst" "${CMAKE_CURRENT_SOURCE_DIR}/use_cases/unknown_dimensions.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/usage.rst" "${CMAKE_CURRENT_SOURCE_DIR}/usage.rst"
) )
include(documentation) include(documentation)
include(GNUInstallDirs) include(GNUInstallDirs)
add_documentation(documentation ALL add_documentation(
documentation ALL
BREATHE_PROJECT mp-units BREATHE_PROJECT mp-units
CODE_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src" CODE_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src"
INSTALL_DIR ${CMAKE_INSTALL_DOCDIR} INSTALL_DIR ${CMAKE_INSTALL_DOCDIR}
@@ -277,6 +248,7 @@ add_documentation(documentation ALL
DOCS_DEPENDS ${unitsSphinxDocs} DOCS_DEPENDS ${unitsSphinxDocs}
) )
add_custom_command(TARGET documentation POST_BUILD add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_static/img/*.svg ${CMAKE_CURRENT_BINARY_DIR}/sphinx/_images TARGET documentation POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_static/img/*.svg
${CMAKE_CURRENT_BINARY_DIR}/sphinx/_images
) )

View File

@@ -193,7 +193,7 @@ namely second. Those can be defined easily in the library using
struct minute : named_scaled_unit<minute, "min", no_prefix, ratio(60), second> {}; 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 hour : named_scaled_unit<hour, "h", no_prefix, ratio(60), minute> {};
struct day : named_scaled_unit<hour, "d", no_prefix, ratio(24), hour> {}; struct day : named_scaled_unit<day, "d", no_prefix, ratio(24), hour> {};
where `no_prefix` is a special tag type describing that the library should 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 not allow to define a new prefixed unit that would use this unit as a

View File

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

View File

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

View File

@@ -28,16 +28,23 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-aliases ${target}.cpp) add_executable(${target}-aliases ${target}.cpp)
target_link_libraries(${target}-aliases PRIVATE ${ARGN}) target_link_libraries(${target}-aliases PRIVATE ${ARGN})
target_compile_definitions(${target}-aliases PRIVATE target_compile_definitions(${target}-aliases PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_REFERENCES)
${projectPrefix}NO_LITERALS
${projectPrefix}NO_REFERENCES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
add_example(box_example mp-units::core-fmt mp-units::si) add_example(box_example mp-units::core-fmt mp-units::si)
add_example(capacitor_time_curve mp-units::core-io mp-units::si) add_example(capacitor_time_curve mp-units::core-io mp-units::si)
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-uscs) add_example(
clcpp_response
mp-units::core-fmt
mp-units::core-io
mp-units::si
mp-units::si-iau
mp-units::si-imperial
mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
)
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si) add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps) add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
add_example(measurement mp-units::core-io mp-units::si) add_example(measurement mp-units::core-io mp-units::si)
@@ -46,9 +53,8 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT ${projectPrefix}LIBCXX) if(NOT ${projectPrefix}LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-aliases PRIVATE target_compile_definitions(
${projectPrefix}NO_LITERALS glide_computer_example-aliases PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_REFERENCES
${projectPrefix}NO_REFERENCES
) )
find_package(wg21_linear_algebra CONFIG REQUIRED) find_package(wg21_linear_algebra CONFIG REQUIRED)

View File

@@ -21,12 +21,12 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/cgs/length.h> #include <units/isq/si/cgs/length.h>
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep #include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> // IWYU pragma: keep #include <units/isq/si/international/speed.h> // IWYU pragma: keep
#include <units/isq/si/length.h> // IWYU pragma: keep #include <units/isq/si/length.h> // IWYU pragma: keep
#include <units/isq/si/time.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -35,38 +35,31 @@ namespace {
using namespace units::isq; using namespace units::isq;
constexpr si::speed<si::metre_per_second, int> constexpr si::speed<si::metre_per_second, int> fixed_int_si_avg_speed(si::length<si::metre, int> d,
fixed_int_si_avg_speed(si::length<si::metre, int> d, si::time<si::second, int> t)
si::time<si::second, int> t)
{ {
return d / t; return d / t;
} }
constexpr si::speed<si::metre_per_second> constexpr si::speed<si::metre_per_second> fixed_double_si_avg_speed(si::length<si::metre> d, si::time<si::second> t)
fixed_double_si_avg_speed(si::length<si::metre> d,
si::time<si::second> t)
{ {
return d / t; return d / t;
} }
template<typename U1, typename R1, typename U2, typename R2> template<typename U1, typename R1, typename U2, typename R2>
constexpr Speed auto si_avg_speed(si::length<U1, R1> d, constexpr Speed auto si_avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
si::time<U2, R2> t)
{ {
return d / t; return d / t;
} }
constexpr Speed auto avg_speed(Length auto d, Time auto t) constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
{
return d / t;
}
template<Length D, Time T, Speed V> template<Length D, Time T, Speed V>
void print_result(D distance, T duration, V speed) void print_result(D distance, T duration, V speed)
{ {
const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed); const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed);
std::cout << "Average speed of a car that makes " << distance << " in " std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph
<< duration << " is " << result_in_kmph << ".\n"; << ".\n";
} }
void example() void example()
@@ -94,7 +87,8 @@ void example()
std::cout << "\nSI units with 'double' as representation\n"; std::cout << "\nSI units with 'double' as representation\n";
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration))); print_result(distance, duration,
fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -130,7 +124,9 @@ void example()
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// also it is not possible to make a lossless conversion of miles to meters on an integral type // also it is not possible to make a lossless conversion of miles to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -169,7 +165,9 @@ void example()
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// it is not possible to make a lossless conversion of centimeters to meters on an integral type // it is not possible to make a lossless conversion of centimeters to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
@@ -178,20 +176,17 @@ void example()
print_result(distance, duration, avg_speed(distance, duration)); print_result(distance, duration, avg_speed(distance, duration));
} }
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -29,7 +29,7 @@
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/volume.h> #include <units/isq/si/volume.h>
#include <cassert> #include <cassert>
@@ -40,7 +40,7 @@ namespace {
using namespace units::aliases::isq::si; using namespace units::aliases::isq::si;
inline constexpr auto g = units::isq::si::si2019::standard_gravity<>; inline constexpr auto g = units::isq::si::si2019::standard_gravity<>; // NOLINT(readability-identifier-length)
inline constexpr auto air_density = kg_per_m3<>(1.225); inline constexpr auto air_density = kg_per_m3<>(1.225);
class Box { class Box {
@@ -48,7 +48,10 @@ class Box {
length::m<> height_; length::m<> height_;
density::kg_per_m3<> density_ = air_density; density::kg_per_m3<> density_ = air_density;
public: public:
constexpr Box(const length::m<>& length, const length::m<>& width, length::m<> height): base_(length * width), height_(std::move(height)) {} constexpr Box(const length::m<>& length, const length::m<>& width, length::m<> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr force::N<> filled_weight() const [[nodiscard]] constexpr force::N<> filled_weight() const
{ {
@@ -86,13 +89,13 @@ int main()
auto box = Box(mm<>(1000.0), mm<>(500.0), height); auto box = Box(mm<>(1000.0), mm<>(500.0), height);
box.set_contents_density(kg_per_m3<>(1000.0)); box.set_contents_density(kg_per_m3<>(1000.0));
const auto fill_time = s<>(200.0); // time since starting fill const auto fill_time = s<>(200.0); // time since starting fill
const auto measured_mass = kg<>(20.0); // measured mass at fill_time const auto measured_mass = kg<>(20.0); // measured mass at fill_time
const Length auto fill_level = box.fill_level(measured_mass); const Length auto fill_level = box.fill_level(measured_mass);
const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height); const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height);
const Volume auto spare_capacity = box.spare_capacity(measured_mass); const Volume auto spare_capacity = box.spare_capacity(measured_mass);
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
const Speed auto float_rise_rate = fill_level / fill_time; const Speed auto float_rise_rate = fill_level / fill_time;
const Time auto fill_time_left = (height / fill_level - 1) * fill_time; const Time auto fill_time_left = (height / fill_level - 1) * fill_time;

View File

@@ -25,7 +25,7 @@
#include <units/isq/si/resistance.h> #include <units/isq/si/resistance.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/voltage.h> #include <units/isq/si/voltage.h>
#include <units/math.h> // IWYU pragma: keep #include <units/math.h> // IWYU pragma: keep
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <iostream> #include <iostream>

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h> #include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h> #include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -52,7 +53,7 @@ struct Ship {
}; };
// Print 'a' in its current units and print its value cast to the units in each of Args // Print 'a' in its current units and print its value cast to the units in each of Args
template<class ...Args, units::Quantity Q> template<class... Args, units::Quantity Q>
auto fmt_line(const Q a) auto fmt_line(const Q a)
{ {
return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...); return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...);
@@ -63,16 +64,21 @@ void print_details(std::string_view description, const Ship& ship)
{ {
const auto waterDensity = si::fps::density::lb_per_ft3<>(62.4); const auto waterDensity = si::fps::density::lb_per_ft3<>(62.4);
std::cout << STD_FMT::format("{}\n", description); std::cout << STD_FMT::format("{}\n", description);
std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.length)) std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.length))
<< STD_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.draft)) << STD_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.draft))
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass)) << STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", fmt_line<si::fps::speed::knot<>, si::speed::km_per_h<>>(ship.speed)) << STD_FMT::format("{:20} : {}\n", "speed",
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power)) fmt_line<si::international::speed::kn<>, si::speed::km_per_h<>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns)) << STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing",fmt_line<si::fps::mass::lton<>, si::mass::kg<>>(ship.shellMass)) << STD_FMT::format("{:20} : {}\n", "main guns",
<< STD_FMT::format("{:20} : {}\n", "fire shells at",fmt_line<si::fps::speed::mph<>, si::speed::km_per_h<>>(ship.shellSpeed)) fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns))
<< STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<si::volume::m3<>, si::volume::l<>>(ship.mass / waterDensity)); << STD_FMT::format("{:20} : {}\n", "fire shells weighing",
fmt_line<si::fps::mass::lton<>, si::mass::kg<>>(ship.shellMass))
<< STD_FMT::format("{:20} : {}\n", "fire shells at",
fmt_line<si::fps::speed::mph<>, si::speed::km_per_h<>>(ship.shellSpeed))
<< STD_FMT::format("{:20} : {}\n", "volume underwater",
fmt_line<si::volume::m3<>, si::volume::l<>>(ship.mass / waterDensity));
} }
int main() int main()
@@ -82,13 +88,37 @@ int main()
using units::aliases::isq::si::fps::length::ft; // to disambiguate from si::femptotonne using units::aliases::isq::si::fps::length::ft; // to disambiguate from si::femptotonne
// KMS Bismark, using the units the Germans would use, taken from Wiki // KMS Bismark, using the units the Germans would use, taken from Wiki
auto bismark = Ship{.length{m<>(251.)}, .draft{m<>(9.3)}, .beam{m<>(36)}, .speed{km_per_h<>(56)}, .mass{t<>(50'300)}, .mainGuns{mm<>(380)}, .shellMass{kg<>(800)}, .shellSpeed{m_per_s<>(820.)}, .power{kW<>(110.45)}}; auto bismark = Ship{.length{m<>(251.)},
.draft{m<>(9.3)},
.beam{m<>(36)},
.speed{km_per_h<>(56)},
.mass{t<>(50'300)},
.mainGuns{mm<>(380)},
.shellMass{kg<>(800)},
.shellSpeed{m_per_s<>(820.)},
.power{kW<>(110.45)}};
// USS Iowa, using units from the foot-pound-second system // USS Iowa, using units from the foot-pound-second system
auto iowa = Ship{.length{ft<>(860.)}, .draft{ft<>(37.) + in<>(2.)}, .beam{ft<>(108.) + in<>(2.)}, .speed{knot<>(33)}, .mass{lton<>(57'540)}, .mainGuns{in<>(16)}, .shellMass{lb<>(2700)}, .shellSpeed{ft_per_s<>(2690.)}, .power{hp<>(212'000)}}; auto iowa = Ship{.length{ft<>(860.)},
.draft{ft<>(37.) + in<>(2.)},
.beam{ft<>(108.) + in<>(2.)},
.speed{international::kn<>(33)},
.mass{lton<>(57'540)},
.mainGuns{in<>(16)},
.shellMass{lb<>(2700)},
.shellSpeed{ft_per_s<>(2690.)},
.power{hp<>(212'000)}};
// HMS King George V, using units from the foot-pound-second system // HMS King George V, using units from the foot-pound-second system
auto kgv = Ship{.length{ft<>(745.1)}, .draft{ft<>(33.) + in<>(7.5)}, .beam{ft<>(103.2) + in<>(2.5)}, .speed{knot<>(28.3)}, .mass{lton<>(42'245)}, .mainGuns{in<>(14)}, .shellMass{lb<>(1'590)}, .shellSpeed{ft_per_s<>(2483)}, .power{hp<>(110'000)}}; auto kgv = Ship{.length{ft<>(745.1)},
.draft{ft<>(33.) + in<>(7.5)},
.beam{ft<>(103.2) + in<>(2.5)},
.speed{international::kn<>(28.3)},
.mass{lton<>(42'245)},
.mainGuns{in<>(14)},
.shellMass{lb<>(1'590)},
.shellSpeed{ft_per_s<>(2483)},
.power{hp<>(110'000)}};
print_details("KMS Bismark, defined in appropriate units from the SI system", bismark); print_details("KMS Bismark, defined in appropriate units from the SI system", bismark);
std::cout << "\n\n"; std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace units::aliases::isq::si; using namespace units::aliases::isq::si;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(km_per_h<>(83)), rate_of_climb(m_per_s<>(-0.7389))}}, glider{"SZD-30 Pirat", {velocity(km_per_h<>(83)), rate_of_climb(m_per_s<>(-0.7389))}},
glider{"SZD-51 Junior", {velocity(km_per_h<>(80)), rate_of_climb(m_per_s<>(-0.6349))}}, glider{"SZD-51 Junior", {velocity(km_per_h<>(80)), rate_of_climb(m_per_s<>(-0.6349))}},
glider{"SZD-48 Jantar Std 3", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.77355))}}, glider{"SZD-48 Jantar Std 3", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.77355))}},
glider{"SZD-56 Diana", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.63657))}}}; glider{"SZD-56 Diana", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.63657))}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{ {
using namespace units::aliases::isq::si; using namespace units::aliases::isq::si;
static const std::array weather_conditions = { static const std::array weather_conditions = {
std::pair("Good", weather{height(m<>(1900)), rate_of_climb(m_per_s<>(4.3))}), std::pair("Good", weather{height(m<>(1900)), rate_of_climb(m_per_s<>(4.3))}),
std::pair("Medium", weather{height(m<>(1550)), rate_of_climb(m_per_s<>(2.8))}), std::pair("Medium", weather{height(m<>(1550)), rate_of_climb(m_per_s<>(2.8))}),
std::pair("Bad", weather{height(m<>(850)), rate_of_climb(m_per_s<>(1.8))})}; std::pair("Bad", weather{height(m<>(850)), rate_of_climb(m_per_s<>(1.8))})};
return weather_conditions; return weather_conditions;
} }
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals; using namespace geographic::literals;
using namespace units::aliases::isq::si::international; using namespace units::aliases::isq::si::international;
static const std::array waypoints = { static const std::array waypoints = {
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(ft<>(16))}, // N54°14'51.8" E18°40'28.2" waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(ft<>(16))}, // N54°14'51.8" E18°40'28.2"
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(ft<>(115))} // N53°31'27.9" E18°50'58.1" waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(ft<>(115))} // N53°31'27.9" E18°50'58.1"
}; };
return waypoints; return waypoints;
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

@@ -20,14 +20,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/energy.h> // IWYU pragma: keep #include <units/format.h>
#include <units/isq/si/energy.h> // IWYU pragma: keep
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream> #include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA { namespace STD_LA {
@@ -72,9 +72,9 @@ void vector_of_quantity_add()
{ {
std::cout << "\nvector_of_quantity_add:\n"; std::cout << "\nvector_of_quantity_add:\n";
vector<length::m<>> v = { m<>(1), m<>(2), m<>(3) }; vector<length::m<>> v = {m<>(1), m<>(2), m<>(3)};
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) }; vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
vector<length::km<>> t = { km<>(3), km<>(2), km<>(1) }; vector<length::km<>> t = {km<>(3), km<>(2), km<>(1)};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -89,8 +89,8 @@ void vector_of_quantity_multiply_same()
{ {
std::cout << "\nvector_of_quantity_multiply_same:\n"; std::cout << "\nvector_of_quantity_multiply_same:\n";
vector<length::m<>> v = { m<>(1), m<>(2), m<>(3) }; vector<length::m<>> v = {m<>(1), m<>(2), m<>(3)};
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) }; vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -103,8 +103,8 @@ void vector_of_quantity_multiply_different()
{ {
std::cout << "\nvector_of_quantity_multiply_different:\n"; std::cout << "\nvector_of_quantity_multiply_different:\n";
vector<force::N<>> v = { N<>(1), N<>(2), N<>(3) }; vector<force::N<>> v = {N<>(1), N<>(2), N<>(3)};
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) }; vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -118,7 +118,7 @@ void vector_of_quantity_divide_by_scalar()
{ {
std::cout << "\nvector_of_quantity_divide_by_scalar:\n"; std::cout << "\nvector_of_quantity_divide_by_scalar:\n";
vector<length::m<>> v = { m<>(4), m<>(8), m<>(12) }; vector<length::m<>> v = {m<>(4), m<>(8), m<>(12)};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -139,9 +139,9 @@ void matrix_of_quantity_add()
{ {
std::cout << "\nmatrix_of_quantity_add:\n"; std::cout << "\nmatrix_of_quantity_add:\n";
matrix<length::m<>> v = {{ m<>(1), m<>(2), m<>(3) }, { m<>(4), m<>(5), m<>(6) }, { m<>(7), m<>(8), m<>(9) }}; matrix<length::m<>> v = {{m<>(1), m<>(2), m<>(3)}, {m<>(4), m<>(5), m<>(6)}, {m<>(7), m<>(8), m<>(9)}};
matrix<length::m<>> u = {{ m<>(3), m<>(2), m<>(1) }, { m<>(3), m<>(2), m<>(1) }, { m<>(3), m<>(2), m<>(1) }}; matrix<length::m<>> u = {{m<>(3), m<>(2), m<>(1)}, {m<>(3), m<>(2), m<>(1)}, {m<>(3), m<>(2), m<>(1)}};
matrix<length::mm<>> t = {{ mm<>(3), mm<>(2), mm<>(1) }, { mm<>(3), mm<>(2), mm<>(1) }, { mm<>(3), mm<>(2), mm<>(1) }}; matrix<length::mm<>> t = {{mm<>(3), mm<>(2), mm<>(1)}, {mm<>(3), mm<>(2), mm<>(1)}, {mm<>(3), mm<>(2), mm<>(1)}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -158,8 +158,8 @@ void matrix_of_quantity_multiply_same()
{ {
std::cout << "\nmatrix_of_quantity_multiply_same:\n"; std::cout << "\nmatrix_of_quantity_multiply_same:\n";
matrix<length::m<>> v = {{ m<>(1), m<>(2), m<>(3) }, { m<>(4), m<>(5), m<>(6) }, { m<>(7), m<>(8), m<>(9) }}; matrix<length::m<>> v = {{m<>(1), m<>(2), m<>(3)}, {m<>(4), m<>(5), m<>(6)}, {m<>(7), m<>(8), m<>(9)}};
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) }; vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -172,8 +172,8 @@ void matrix_of_quantity_multiply_different()
{ {
std::cout << "\nmatrix_of_quantity_multiply_different:\n"; std::cout << "\nmatrix_of_quantity_multiply_different:\n";
vector<force::N<>> v = { N<>(1), N<>(2), N<>(3) }; vector<force::N<>> v = {N<>(1), N<>(2), N<>(3)};
matrix<length::m<>> u = {{ m<>(1), m<>(2), m<>(3) }, { m<>(4), m<>(5), m<>(6) }, { m<>(7), m<>(8), m<>(9) }}; matrix<length::m<>> u = {{m<>(1), m<>(2), m<>(3)}, {m<>(4), m<>(5), m<>(6)}, {m<>(7), m<>(8), m<>(9)}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -187,7 +187,7 @@ void matrix_of_quantity_divide_by_scalar()
{ {
std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n"; std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n";
matrix<length::m<>> v = {{ m<>(2), m<>(4), m<>(6) }, { m<>(4), m<>(6), m<>(8) }, { m<>(8), m<>(4), m<>(2) }}; matrix<length::m<>> v = {{m<>(2), m<>(4), m<>(6)}, {m<>(4), m<>(6), m<>(8)}, {m<>(8), m<>(4), m<>(2)}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
@@ -216,9 +216,9 @@ void quantity_of_vector_add()
{ {
std::cout << "\nquantity_of_vector_add:\n"; std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{ 3, 2, 1 }); length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -233,8 +233,8 @@ void quantity_of_vector_multiply_same()
{ {
std::cout << "\nquantity_of_vector_multiply_same:\n"; std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -247,8 +247,8 @@ void quantity_of_vector_multiply_different()
{ {
std::cout << "\nquantity_of_vector_multiply_different:\n"; std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -262,7 +262,7 @@ void quantity_of_vector_divide_by_scalar()
{ {
std::cout << "\nquantity_of_vector_divide_by_scalar:\n"; std::cout << "\nquantity_of_vector_divide_by_scalar:\n";
length_v<> v(vector<>{ 4, 8, 12 }); length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -286,9 +286,9 @@ void quantity_of_matrix_add()
{ {
std::cout << "\nquantity_of_matrix_add:\n"; std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -305,8 +305,8 @@ void quantity_of_matrix_multiply_same()
{ {
std::cout << "\nquantity_of_matrix_multiply_same:\n"; std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -319,8 +319,8 @@ void quantity_of_matrix_multiply_different()
{ {
std::cout << "\nquantity_of_matrix_multiply_different:\n"; std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -334,7 +334,7 @@ void quantity_of_matrix_divide_by_scalar()
{ {
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n"; std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }}); length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";

View File

@@ -38,8 +38,7 @@ public:
measurement() = default; measurement() = default;
constexpr explicit measurement(const value_type& val, const value_type& err = {}) : constexpr explicit measurement(const value_type& val, const value_type& err = {}) : value_(val)
value_(val)
{ {
// it sucks that using declaration cannot be provided for a constructor initializer list // it sucks that using declaration cannot be provided for a constructor initializer list
using namespace std; using namespace std;

View File

@@ -21,11 +21,11 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/natural/natural.h> #include <units/isq/natural/natural.h>
#include <units/isq/si/constants.h>
#include <units/isq/si/energy.h> #include <units/isq/si/energy.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/momentum.h> #include <units/isq/si/momentum.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/constants.h>
#include <units/math.h> #include <units/math.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -85,18 +85,16 @@ void natural_example()
<< "E = " << E << "\n"; << "E = " << E << "\n";
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
si_example(); si_example();
natural_example(); natural_example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -21,7 +21,7 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -44,8 +44,9 @@ void example()
Time auto t1 = s<>(10); Time auto t1 = s<>(10);
Speed auto v1 = avg_speed(d1, t1); Speed auto v1 = avg_speed(d1, t1);
auto temp1 = v1 * m<>(50); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit' auto temp1 =
Speed auto v2 = temp1 / m<>(100); // back to known dimensions again v1 * m<>(50); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
Speed auto v2 = temp1 / m<>(100); // back to known dimensions again
Length auto d2 = v2 * s<>(60); Length auto d2 = v2 * s<>(60);
std::cout << "d1 = " << d1 << '\n'; std::cout << "d1 = " << d1 << '\n';
@@ -56,17 +57,15 @@ void example()
std::cout << "d2 = " << d2 << '\n'; std::cout << "d2 = " << d2 << '\n';
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -54,7 +54,8 @@ int main()
std::cout << STD_FMT::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB); std::cout << STD_FMT::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB);
std::cout << STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n", lengthA, lengthB) std::cout << STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n", lengthA,
lengthB)
<< STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n", << STD_FMT::format("lengthB.number( {} ) == lengthA.number( {} ) * conversion_factor( {} )\n",
lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA)); lengthB.number(), lengthA.number(), conversion_factor(lengthB, lengthA));
} }

View File

@@ -66,10 +66,7 @@ using length = quantity<dim_length, U, Rep>;
} // namespace si } // namespace si
template<typename Q, typename U> template<typename Q, typename U>
concept castable_to = Quantity<Q> && Unit<U> && concept castable_to = Quantity<Q> && Unit<U> && requires(Q q) { quantity_cast<U>(q); };
requires (Q q) {
quantity_cast<U>(q);
};
void conversions() void conversions()
{ {

View File

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

View File

@@ -1,63 +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

@@ -34,7 +34,8 @@ task::legs task::make_legs(const waypoints& wpts)
task::legs res; task::legs res;
res.reserve(wpts.size() - 1); res.reserve(wpts.size() - 1);
auto to_leg = [](const waypoint& w1, const waypoint& w2) { return task::leg(w1, w2); }; auto to_leg = [](const waypoint& w1, const waypoint& w2) { return task::leg(w1, w2); };
std::ranges::transform(wpts.cbegin(), prev(wpts.cend()), next(wpts.cbegin()), wpts.cend(), std::back_inserter(res), to_leg); std::ranges::transform(wpts.cbegin(), prev(wpts.cend()), next(wpts.cbegin()), wpts.cend(), std::back_inserter(res),
to_leg);
return res; return res;
} }
@@ -64,24 +65,23 @@ distance glide_distance(const flight_point& pos, const glider& g, const task& t,
((ground_alt - t.get_finish().alt) / dist_to_finish - 1 / glide_ratio(g.polar[0]))); ((ground_alt - t.get_finish().alt) / dist_to_finish - 1 / glide_ratio(g.polar[0])));
} }
} } // namespace glide_computer
namespace { namespace {
using namespace glide_computer; using namespace glide_computer;
void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point, const glide_computer::flight_point& new_point) void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point,
const glide_computer::flight_point& new_point)
{ {
std::cout << STD_FMT::format( std::cout << STD_FMT::format(
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) |\n", "| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) "
phase_name, quantity_cast<si::minute>(new_point.ts - point.ts), quantity_cast<si::minute>(new_point.ts - start_ts), "|\n",
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt); phase_name, quantity_cast<si::minute>(new_point.ts - point.ts), quantity_cast<si::minute>(new_point.ts - start_ts),
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt);
} }
flight_point takeoff(timestamp start_ts, const task& t) flight_point takeoff(timestamp start_ts, const task& t) { return {start_ts, t.get_start().alt}; }
{
return {start_ts, t.get_start().alt};
}
flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow& at) flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow& at)
{ {
@@ -92,7 +92,8 @@ flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow
return new_pos; return new_pos;
} }
flight_point circle(timestamp start_ts, const flight_point& pos, const glider& g, const weather& w, const task& t, height& height_to_gain) flight_point circle(timestamp start_ts, const flight_point& pos, const glider& g, const weather& w, const task& t,
height& height_to_gain)
{ {
const height h_agl = agl(pos.alt, terrain_level_alt(t, pos)); const height h_agl = agl(pos.alt, terrain_level_alt(t, pos));
const height circling_height = std::min(w.cloud_base - h_agl, height_to_gain); const height circling_height = std::min(w.cloud_base - h_agl, height_to_gain);
@@ -114,7 +115,8 @@ flight_point glide(timestamp start_ts, const flight_point& pos, const glider& g,
const auto alt = ground_alt + s.min_agl_height; const auto alt = ground_alt + s.min_agl_height;
const auto l3d = length_3d(dist, pos.alt - alt); const auto l3d = length_3d(dist, pos.alt - alt);
const duration d = l3d / g.polar[0].v.common(); const duration d = l3d / g.polar[0].v.common();
const flight_point new_pos{pos.ts + d, terrain_level_alt(t, pos) + s.min_agl_height, t.get_leg_index(new_distance), new_distance}; const flight_point new_pos{pos.ts + d, terrain_level_alt(t, pos) + s.min_agl_height, t.get_leg_index(new_distance),
new_distance};
print("Glide", start_ts, pos, new_pos); print("Glide", start_ts, pos, new_pos);
return new_pos; return new_pos;
@@ -135,9 +137,11 @@ flight_point final_glide(timestamp start_ts, const flight_point& pos, const glid
namespace glide_computer { namespace glide_computer {
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s, const aircraft_tow& at) void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s,
const aircraft_tow& at)
{ {
std::cout << STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance", "Height"); std::cout << STD_FMT::format("| {:<12} | {:^28} | {:^26} | {:^21} |\n", "Flight phase", "Duration", "Distance",
"Height");
std::cout << STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", ""); std::cout << STD_FMT::format("|{0:-^14}|{0:-^30}|{0:-^28}|{0:-^23}|\n", "");
// ready to takeoff // ready to takeoff

View File

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

View File

@@ -32,14 +32,14 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/format.h> #include <units/format.h>
#include <units/math.h> // IWYU pragma: keep #include <units/math.h> // IWYU pragma: keep
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <ostream> #include <ostream>
#include <ranges> #include <ranges>
#include <string> // IWYU pragma: keep #include <string> // IWYU pragma: keep
#include <vector> #include <vector>
// An example of a really simplified tactical glide computer // An example of a really simplified tactical glide computer
@@ -69,7 +69,7 @@ namespace glide_computer {
template<units::QuantityKind QK1, units::QuantityKind QK2> template<units::QuantityKind QK1, units::QuantityKind QK2>
constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs) constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
requires(!units::QuantityKindRelatedTo<QK1, QK2>) && requires { lhs.common() / rhs.common();} requires(!units::QuantityKindRelatedTo<QK1, QK2>) && requires { lhs.common() / rhs.common(); }
{ {
return lhs.common() / rhs.common(); return lhs.common() / rhs.common();
} }
@@ -136,7 +136,7 @@ struct weather {
struct waypoint { struct waypoint {
std::string name; std::string name;
geographic::position pos; geographic::position<long double> pos;
altitude alt; altitude alt;
}; };
@@ -149,7 +149,7 @@ public:
const waypoint* end_; const waypoint* end_;
distance length_ = geographic::spherical_distance(begin().pos, end().pos); distance length_ = geographic::spherical_distance(begin().pos, end().pos);
public: public:
leg(const waypoint& b, const waypoint& e) noexcept: begin_(&b), end_(&e) {} leg(const waypoint& b, const waypoint& e) noexcept : begin_(&b), end_(&e) {}
constexpr const waypoint& begin() const { return *begin_; }; constexpr const waypoint& begin() const { return *begin_; };
constexpr const waypoint& end() const { return *end_; } constexpr const waypoint& end() const { return *end_; }
constexpr const distance get_length() const { return length_; } constexpr const distance get_length() const { return length_; }
@@ -157,8 +157,11 @@ public:
using legs = std::vector<leg>; using legs = std::vector<leg>;
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires std::same_as<std::ranges::range_value_t<R>,
explicit task(const R& r) : waypoints_(std::ranges::begin(r), std::ranges::end(r)) {} waypoint> explicit task(const R& r) :
waypoints_(std::ranges::begin(r), std::ranges::end(r))
{
}
task(std::initializer_list<waypoint> wpts) : waypoints_(wpts) {} task(std::initializer_list<waypoint> wpts) : waypoints_(wpts) {}
@@ -170,10 +173,14 @@ public:
distance get_length() const { return length_; } distance get_length() const { return length_; }
distance get_leg_dist_offset(std::size_t leg_index) const { return leg_index == 0 ? distance{} : leg_total_distances_[leg_index - 1]; } distance get_leg_dist_offset(std::size_t leg_index) const
{
return leg_index == 0 ? distance{} : leg_total_distances_[leg_index - 1];
}
std::size_t get_leg_index(distance dist) const std::size_t get_leg_index(distance dist) const
{ {
return static_cast<std::size_t>(std::ranges::distance(leg_total_distances_.cbegin(), std::ranges::lower_bound(leg_total_distances_, dist))); return static_cast<std::size_t>(
std::ranges::distance(leg_total_distances_.cbegin(), std::ranges::lower_bound(leg_total_distances_, dist)));
} }
private: private:
@@ -214,6 +221,7 @@ inline units::isq::si::length<units::isq::si::kilometre> length_3d(distance dist
distance glide_distance(const flight_point& pos, const glider& g, const task& t, const safety& s, altitude ground_alt); distance glide_distance(const flight_point& pos, const glider& g, const task& t, const safety& s, altitude ground_alt);
void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s, const aircraft_tow& at); void estimate(timestamp start_ts, const glider& g, const weather& w, const task& t, const safety& s,
const aircraft_tow& at);
} // namespace glide_computer } // namespace glide_computer

View File

@@ -22,19 +22,16 @@
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> // IWYU pragma: keep #include <units/isq/si/international/speed.h> // IWYU pragma: keep
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <iostream> #include <iostream>
using namespace units::isq; using namespace units::isq;
constexpr Speed auto avg_speed(Length auto d, Time auto t) constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
{
return d / t;
}
int main() int main()
{ {
@@ -55,11 +52,11 @@ int main()
#endif #endif
constexpr Speed auto v7 = quantity_cast<int>(v6); constexpr Speed auto v7 = quantity_cast<int>(v6);
std::cout << v1 << '\n'; // 110 km/h std::cout << v1 << '\n'; // 110 km/h
std::cout << v2 << '\n'; // 70 mi/h std::cout << v2 << '\n'; // 70 mi/h
std::cout << STD_FMT::format("{}", v3) << '\n'; // 110 km/h std::cout << STD_FMT::format("{}", v3) << '\n'; // 110 km/h
std::cout << STD_FMT::format("{:*^14}", v4) << '\n'; // ***70 mi/h**** std::cout << STD_FMT::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
std::cout << STD_FMT::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s std::cout << STD_FMT::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
std::cout << STD_FMT::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s std::cout << STD_FMT::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
std::cout << STD_FMT::format("{:%Q}", v7) << '\n'; // 31 std::cout << STD_FMT::format("{:%Q}", v7) << '\n'; // 31
} }

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

@@ -28,10 +28,7 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target} ${target}.cpp) add_executable(${target} ${target}.cpp)
target_link_libraries(${target} PRIVATE ${ARGN}) target_link_libraries(${target} PRIVATE ${ARGN})
target_compile_definitions(${target} PRIVATE target_compile_definitions(${target} PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_ALIASES)
${projectPrefix}NO_LITERALS
${projectPrefix}NO_ALIASES
)
endfunction() endfunction()
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si) add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)

View File

@@ -34,7 +34,8 @@
namespace kalman { namespace kalman {
template<typename T> template<typename T>
concept QuantityOrQuantityPoint = units::Quantity<T> || units::QuantityPoint<T>; // TODO Should it also account for `kinds`? concept QuantityOrQuantityPoint =
units::Quantity<T> || units::QuantityPoint<T>; // TODO Should it also account for `kinds`?
template<typename... Qs> template<typename... Qs>
inline constexpr bool are_derivatives = false; inline constexpr bool are_derivatives = false;
@@ -44,34 +45,42 @@ inline constexpr bool are_derivatives<Q> = true;
template<typename Q1, typename Q2, typename... Qs> template<typename Q1, typename Q2, typename... Qs>
inline constexpr bool are_derivatives<Q1, Q2, Qs...> = inline constexpr bool are_derivatives<Q1, Q2, Qs...> =
units::DimensionOfT<typename decltype(Q1::reference / Q2::reference)::dimension, units::isq::dim_time> && // TODO Think on how to simplify this units::DimensionOfT<typename decltype(Q1::reference / Q2::reference)::dimension,
units::isq::dim_time> && // TODO Think on how to simplify this
are_derivatives<Q2, Qs...>; are_derivatives<Q2, Qs...>;
// state // state
template<QuantityOrQuantityPoint... QQPs> template<QuantityOrQuantityPoint... QQPs>
requires (sizeof...(QQPs) > 0) && (sizeof...(QQPs) <= 3) && are_derivatives<QQPs...> requires(sizeof...(QQPs) > 0) && (sizeof...(QQPs) <= 3) && are_derivatives<QQPs...>
struct state { struct state {
std::tuple<QQPs...> variables_; std::tuple<QQPs...> variables_;
constexpr state(QQPs... qqps): variables_(std::move(qqps)...) {} constexpr state(QQPs... qqps) : variables_(std::move(qqps)...) {}
}; };
template<typename T> template<typename T>
concept State = units::is_specialization_of<T, state>; concept State = units::is_specialization_of<T, state>;
template<std::size_t Idx, typename... Qs> template<std::size_t Idx, typename... Qs>
constexpr auto& get(state<Qs...>& s) { return get<Idx>(s.variables_); } constexpr auto& get(state<Qs...>& s)
{
return get<Idx>(s.variables_);
}
template<std::size_t Idx, typename... Qs> template<std::size_t Idx, typename... Qs>
constexpr const auto& get(const state<Qs...>& s) { return get<Idx>(s.variables_); } constexpr const auto& get(const state<Qs...>& s)
{
return get<Idx>(s.variables_);
}
// estimation // estimation
template<QuantityOrQuantityPoint QQP, QuantityOrQuantityPoint... QQPs> template<QuantityOrQuantityPoint QQP, QuantityOrQuantityPoint... QQPs>
struct estimation { struct estimation {
private: private:
using uncertainty_ref = decltype(QQP::reference * QQP::reference); using uncertainty_ref = decltype(QQP::reference * QQP::reference);
using uncertainty_type = units::quantity<typename uncertainty_ref::dimension, typename uncertainty_ref::unit, typename QQP::rep>; using uncertainty_type =
units::quantity<typename uncertainty_ref::dimension, typename uncertainty_ref::unit, typename QQP::rep>;
public: public:
kalman::state<QQP, QQPs...> state; // TODO extend kalman functions to work with this variadic patermater list kalman::state<QQP, QQPs...> state; // TODO extend kalman functions to work with this variadic patermater list
uncertainty_type uncertainty; uncertainty_type uncertainty;
}; };
@@ -94,7 +103,7 @@ template<typename Q, QuantityOrQuantityPoint QM, units::Dimensionless K>
requires units::equivalent<typename Q::dimension, typename QM::dimension> requires units::equivalent<typename Q::dimension, typename QM::dimension>
constexpr state<Q> state_update(const state<Q>& predicted, QM measured, K gain) constexpr state<Q> state_update(const state<Q>& predicted, QM measured, K gain)
{ {
return { get<0>(predicted) + gain * (measured - get<0>(predicted)) }; return {get<0>(predicted) + gain * (measured - get<0>(predicted))};
} }
template<typename Q1, typename Q2, QuantityOrQuantityPoint QM, units::Dimensionless K, units::isq::Time T> template<typename Q1, typename Q2, QuantityOrQuantityPoint QM, units::Dimensionless K, units::isq::Time T>
@@ -103,17 +112,18 @@ constexpr state<Q1, Q2> state_update(const state<Q1, Q2>& predicted, QM measured
{ {
const auto q1 = get<0>(predicted) + get<0>(gain) * (measured - get<0>(predicted)); const auto q1 = get<0>(predicted) + get<0>(gain) * (measured - get<0>(predicted));
const auto q2 = get<1>(predicted) + get<1>(gain) * (measured - get<0>(predicted)) / interval; const auto q2 = get<1>(predicted) + get<1>(gain) * (measured - get<0>(predicted)) / interval;
return { q1, q2 }; return {q1, q2};
} }
template<typename Q1, typename Q2, typename Q3, QuantityOrQuantityPoint QM, units::Dimensionless K, units::isq::Time T> template<typename Q1, typename Q2, typename Q3, QuantityOrQuantityPoint QM, units::Dimensionless K, units::isq::Time T>
requires units::equivalent<typename Q1::dimension, typename QM::dimension> requires units::equivalent<typename Q1::dimension, typename QM::dimension>
constexpr state<Q1, Q2, Q3> state_update(const state<Q1, Q2, Q3>& predicted, QM measured, std::array<K, 3> gain, T interval) constexpr state<Q1, Q2, Q3> state_update(const state<Q1, Q2, Q3>& predicted, QM measured, std::array<K, 3> gain,
T interval)
{ {
const auto q1 = get<0>(predicted) + get<0>(gain) * (measured - get<0>(predicted)); const auto q1 = get<0>(predicted) + get<0>(gain) * (measured - get<0>(predicted));
const auto q2 = get<1>(predicted) + get<1>(gain) * (measured - get<0>(predicted)) / interval; const auto q2 = get<1>(predicted) + get<1>(gain) * (measured - get<0>(predicted)) / interval;
const auto q3 = get<2>(predicted) + get<2>(gain) * (measured - get<0>(predicted)) / (interval * interval / 2); const auto q3 = get<2>(predicted) + get<2>(gain) * (measured - get<0>(predicted)) / (interval * interval / 2);
return { q1, q2, q3 }; return {q1, q2, q3};
} }
// covariance update // covariance update
@@ -129,7 +139,7 @@ constexpr state<Q1, Q2> state_extrapolation(const state<Q1, Q2>& estimated, T in
{ {
const auto q1 = get<0>(estimated) + get<1>(estimated) * interval; const auto q1 = get<0>(estimated) + get<1>(estimated) * interval;
const auto q2 = get<1>(estimated); const auto q2 = get<1>(estimated);
return { q1, q2 }; return {q1, q2};
} }
template<typename Q1, typename Q2, typename Q3, units::isq::Time T> template<typename Q1, typename Q2, typename Q3, units::isq::Time T>
@@ -138,7 +148,7 @@ constexpr state<Q1, Q2, Q3> state_extrapolation(const state<Q1, Q2, Q3>& estimat
const auto q1 = get<0>(estimated) + get<1>(estimated) * interval + get<2>(estimated) * pow<2>(interval) / 2; const auto q1 = get<0>(estimated) + get<1>(estimated) * interval + get<2>(estimated) * pow<2>(interval) / 2;
const auto q2 = get<1>(estimated) + get<2>(estimated) * interval; const auto q2 = get<1>(estimated) + get<2>(estimated) * interval;
const auto q3 = get<2>(estimated); const auto q3 = get<2>(estimated);
return { q1, q2, q3 }; return {q1, q2, q3};
} }
// covariance extrapolation // covariance extrapolation
@@ -164,24 +174,26 @@ struct STD_FMT::formatter<kalman::state<Qs...>> {
std::string value_buffer; std::string value_buffer;
auto to_value_buffer = std::back_inserter(value_buffer); auto to_value_buffer = std::back_inserter(value_buffer);
if (specs.precision != -1) { if (specs.precision != -1) {
if constexpr(sizeof...(Qs) == 1) if constexpr (sizeof...(Qs) == 1)
STD_FMT::format_to(to_value_buffer, "{1:%.{0}Q %q}", specs.precision, kalman::get<0>(s)); STD_FMT::format_to(to_value_buffer, "{1:%.{0}Q %q}", specs.precision, kalman::get<0>(s));
else if constexpr(sizeof...(Qs) == 2) else if constexpr (sizeof...(Qs) == 2)
STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q} }}", specs.precision, kalman::get<0>(s), kalman::get<1>(s)); STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q} }}", specs.precision, kalman::get<0>(s),
kalman::get<1>(s));
else else
STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q}, {3:%.{0}Q %q} }}", specs.precision, kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s)); STD_FMT::format_to(to_value_buffer, "{{ {1:%.{0}Q %q}, {2:%.{0}Q %q}, {3:%.{0}Q %q} }}", specs.precision,
} kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s));
else { } else {
if constexpr(sizeof...(Qs) == 1) if constexpr (sizeof...(Qs) == 1)
STD_FMT::format_to(to_value_buffer, "{}", kalman::get<0>(s)); STD_FMT::format_to(to_value_buffer, "{}", kalman::get<0>(s));
else if constexpr(sizeof...(Qs) == 2) else if constexpr (sizeof...(Qs) == 2)
STD_FMT::format_to(to_value_buffer, "{{ {}, {} }}", kalman::get<0>(s), kalman::get<1>(s)); STD_FMT::format_to(to_value_buffer, "{{ {}, {} }}", kalman::get<0>(s), kalman::get<1>(s));
else else
STD_FMT::format_to(to_value_buffer, "{{ {}, {}, {} }}", kalman::get<0>(s), kalman::get<1>(s), kalman::get<2>(s)); STD_FMT::format_to(to_value_buffer, "{{ {}, {}, {} }}", kalman::get<0>(s), kalman::get<1>(s),
kalman::get<2>(s));
} }
std::string global_format_buffer; std::string global_format_buffer;
units::detail::quantity_global_format_specs<char> global_specs = { specs.fill, specs.align, specs.width }; units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs); units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs);
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer)); return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer));
@@ -202,7 +214,7 @@ struct STD_FMT::formatter<kalman::estimation<Q>> {
auto format(kalman::estimation<Q> e, FormatContext& ctx) auto format(kalman::estimation<Q> e, FormatContext& ctx)
{ {
units::Quantity auto q = [](const Q& t) { units::Quantity auto q = [](const Q& t) {
if constexpr(units::Quantity<Q>) if constexpr (units::Quantity<Q>)
return t; return t;
else else
return t.relative(); return t.relative();
@@ -212,13 +224,12 @@ struct STD_FMT::formatter<kalman::estimation<Q>> {
auto to_value_buffer = std::back_inserter(value_buffer); auto to_value_buffer = std::back_inserter(value_buffer);
if (specs.precision != -1) { if (specs.precision != -1) {
STD_FMT::format_to(to_value_buffer, "{0:%.{2}Q} ± {1:%.{2}Q} {0:%q}", q, sqrt(e.uncertainty), specs.precision); STD_FMT::format_to(to_value_buffer, "{0:%.{2}Q} ± {1:%.{2}Q} {0:%q}", q, sqrt(e.uncertainty), specs.precision);
} } else {
else {
STD_FMT::format_to(to_value_buffer, "{0:%Q} ± {1:%Q} {0:%q}", q, sqrt(e.uncertainty)); STD_FMT::format_to(to_value_buffer, "{0:%Q} ± {1:%Q} {0:%q}", q, sqrt(e.uncertainty));
} }
std::string global_format_buffer; std::string global_format_buffer;
units::detail::quantity_global_format_specs<char> global_specs = { specs.fill, specs.align, specs.width }; units::detail::quantity_global_format_specs<char> global_specs = {specs.fill, specs.align, specs.width};
units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs); units::detail::format_global_buffer(std::back_inserter(global_format_buffer), global_specs);
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer)); return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer));

View File

@@ -21,9 +21,9 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/isq/si/mass.h>
#include <units/format.h> #include <units/format.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/mass.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
@@ -34,10 +34,12 @@ using namespace units;
void print_header(const kalman::State auto& initial) void print_header(const kalman::State auto& initial)
{ {
std::cout << STD_FMT::format("Initial: {}\n", initial); std::cout << STD_FMT::format("Initial: {}\n", initial);
std::cout << STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured", "Curr. Estimate", "Next Estimate"); std::cout << STD_FMT::format("{:>2} | {:>9} | {:>8} | {:>14} | {:>14}\n", "N", "Gain", "Measured", "Curr. Estimate",
"Next Estimate");
} }
void print(auto iteration, Dimensionless auto gain, Quantity auto measured, const kalman::State auto& current, const kalman::State auto& next) void print(auto iteration, Dimensionless auto gain, Quantity auto measured, const kalman::State auto& current,
const kalman::State auto& next)
{ {
std::cout << STD_FMT::format("{:2} | {:9} | {:8} | {:14} | {:14}\n", iteration, gain, measured, current, next); std::cout << STD_FMT::format("{:2} | {:9} | {:8} | {:14} | {:14}\n", iteration, gain, measured, current, next);
} }
@@ -48,13 +50,13 @@ int main()
using namespace units::isq::si::references; using namespace units::isq::si::references;
using state = kalman::state<si::mass<si::gram>>; using state = kalman::state<si::mass<si::gram>>;
const state initial = { 1 * kg }; const state initial = {1 * kg};
const std::array measurements = { 1030 * g, 989 * g, 1017 * g, 1009 * g, 1013 * g, const std::array measurements = {1030 * g, 989 * g, 1017 * g, 1009 * g, 1013 * g,
979 * g, 1008 * g, 1042 * g, 1012 * g, 1011 * g }; 979 * g, 1008 * g, 1042 * g, 1012 * g, 1011 * g};
print_header(initial); print_header(initial);
state next = initial; state next = initial;
for(int index = 1; const auto& m : measurements) { for (int index = 1; const auto& m : measurements) {
const auto& previous = next; const auto& previous = next;
const dimensionless<one> gain = 1. / index; const dimensionless<one> gain = 1. / index;
const auto current = state_update(previous, m, gain); const auto current = state_update(previous, m, gain);

View File

@@ -21,11 +21,11 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
@@ -51,14 +51,14 @@ int main()
using state = kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>>; using state = kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>>;
const auto interval = 5 * s; const auto interval = 5 * s;
const state initial = { 30 * km, 40 * (m / s) }; const state initial = {30 * km, 40 * (m / s)};
const std::array measurements = { 30110 * m, 30265 * m, 30740 * m, 30750 * m, 31135 * m, const std::array measurements = {30110 * m, 30265 * m, 30740 * m, 30750 * m, 31135 * m,
31015 * m, 31180 * m, 31610 * m, 31960 * m, 31865 * m }; 31015 * m, 31180 * m, 31610 * m, 31960 * m, 31865 * m};
std::array gain = {dimensionless<one>(0.2), dimensionless<one>(0.1)}; std::array gain = {dimensionless<one>(0.2), dimensionless<one>(0.1)};
print_header(initial); print_header(initial);
state next = state_extrapolation(initial, interval); state next = state_extrapolation(initial, interval);
for(int index = 1; const auto& measured : measurements) { for (int index = 1; const auto& measured : measurements) {
const auto& previous = next; const auto& previous = next;
const auto current = state_update(previous, measured, gain, interval); const auto current = state_update(previous, measured, gain, interval);
next = state_extrapolation(current, interval); next = state_extrapolation(current, interval);

View File

@@ -21,11 +21,11 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
@@ -51,14 +51,14 @@ int main()
using state = kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>>; using state = kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>>;
const auto interval = 5 * s; const auto interval = 5 * s;
const state initial = { 30 * km, 50 * (m / s) }; const state initial = {30 * km, 50 * (m / s)};
const std::array measurements = { 30160 * m, 30365 * m, 30890 * m, 31050 * m, 31785 * m, const std::array measurements = {30160 * m, 30365 * m, 30890 * m, 31050 * m, 31785 * m,
32215 * m, 33130 * m, 34510 * m, 36010 * m, 37265 * m }; 32215 * m, 33130 * m, 34510 * m, 36010 * m, 37265 * m};
std::array gain = {dimensionless<one>(0.2), dimensionless<one>(0.1)}; std::array gain = {dimensionless<one>(0.2), dimensionless<one>(0.1)};
print_header(initial); print_header(initial);
state next = state_extrapolation(initial, interval); state next = state_extrapolation(initial, interval);
for(int index = 1; const auto& measured : measurements) { for (int index = 1; const auto& measured : measurements) {
const auto& previous = next; const auto& previous = next;
const auto current = state_update(previous, measured, gain, interval); const auto current = state_update(previous, measured, gain, interval);
next = state_extrapolation(current, interval); next = state_extrapolation(current, interval);

View File

@@ -21,12 +21,12 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/acceleration.h> #include <units/isq/si/acceleration.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
@@ -49,19 +49,20 @@ int main()
{ {
using namespace units::isq; using namespace units::isq;
using namespace units::isq::si::references; using namespace units::isq::si::references;
using state = kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>, si::acceleration<si::metre_per_second_sq>>; using state =
kalman::state<si::length<si::metre>, si::speed<si::metre_per_second>, si::acceleration<si::metre_per_second_sq>>;
constexpr auto mps = m / s; constexpr auto mps = m / s;
constexpr auto mps2 = mps / s; constexpr auto mps2 = mps / s;
const auto interval = 5. * s; const auto interval = 5. * s;
const state initial = { 30 * km, 50 * mps, 0 * mps2 }; const state initial = {30 * km, 50 * mps, 0 * mps2};
const std::array measurements = { 30160 * m, 30365 * m, 30890 * m, 31050 * m, 31785 * m, const std::array measurements = {30160 * m, 30365 * m, 30890 * m, 31050 * m, 31785 * m,
32215 * m, 33130 * m, 34510 * m, 36010 * m, 37265 * m }; 32215 * m, 33130 * m, 34510 * m, 36010 * m, 37265 * m};
std::array gain = {dimensionless<one>(0.5), dimensionless<one>(0.4), dimensionless<one>(0.1)}; std::array gain = {dimensionless<one>(0.5), dimensionless<one>(0.4), dimensionless<one>(0.1)};
print_header(initial); print_header(initial);
state next = state_extrapolation(initial, interval); state next = state_extrapolation(initial, interval);
for(int index = 1; const auto& measured : measurements) { for (int index = 1; const auto& measured : measurements) {
const auto& previous = next; const auto& previous = next;
const auto current = state_update(previous, measured, gain, interval); const auto current = state_update(previous, measured, gain, interval);
next = state_extrapolation(current, interval); next = state_extrapolation(current, interval);

View File

@@ -21,8 +21,8 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/isq/si/length.h>
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/length.h>
#include <units/math.h> #include <units/math.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
@@ -35,13 +35,15 @@ template<Quantity Q>
void print_header(kalman::estimation<Q> initial) void print_header(kalman::estimation<Q> initial)
{ {
std::cout << STD_FMT::format("Initial: {}\n", initial); std::cout << STD_FMT::format("Initial: {}\n", initial);
std::cout << STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate", "Next Estimate"); std::cout << STD_FMT::format("{:>2} | {:>5} | {:>8} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
"Next Estimate");
} }
template<Quantity Q, Dimensionless K> template<Quantity Q, Dimensionless K>
void print(auto iteration, K gain, Q measured, kalman::estimation<Q> current, kalman::estimation<Q> next) void print(auto iteration, K gain, Q measured, kalman::estimation<Q> current, kalman::estimation<Q> next)
{ {
std::cout << STD_FMT::format("{:2} | {:5%.2Q} | {:8} | {:>16.2} | {:>16.2}\n", iteration, gain, measured, current, next); std::cout << STD_FMT::format("{:2} | {:5%.2Q} | {:8} | {:>16.2} | {:>16.2}\n", iteration, gain, measured, current,
next);
} }
int main() int main()
@@ -50,20 +52,20 @@ int main()
using namespace units::isq; using namespace units::isq;
using namespace units::isq::si::references; using namespace units::isq::si::references;
const estimation initial = { state{ 60. * m }, pow<2>(15. * m) }; const estimation initial = {state{60. * m}, pow<2>(15. * m)};
const std::array measurements = { 48.54 * m, 47.11 * m, 55.01 * m, 55.15 * m, 49.89 * m, const std::array measurements = {48.54 * m, 47.11 * m, 55.01 * m, 55.15 * m, 49.89 * m,
40.85 * m, 46.72 * m, 50.05 * m, 51.27 * m, 49.95 * m }; 40.85 * m, 46.72 * m, 50.05 * m, 51.27 * m, 49.95 * m};
const auto measurement_uncertainty = pow<2>(5. * m); const auto measurement_uncertainty = pow<2>(5. * m);
auto update = [=]<Quantity Q>(const estimation<Q>& previous, const Q& meassurement, Dimensionless auto gain) { auto update = [=]<Quantity Q>(const estimation<Q>& previous, const Q& meassurement, Dimensionless auto gain) {
return estimation{ state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain) }; return estimation{state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain)};
}; };
auto predict = []<Quantity Q>(const estimation<Q>& current) { return current; }; auto predict = []<Quantity Q>(const estimation<Q>& current) { return current; };
print_header(initial); print_header(initial);
estimation next = predict(initial); estimation next = predict(initial);
for(int index = 1; const auto& measured : measurements) { for (int index = 1; const auto& measured : measurements) {
const auto& previous = next; const auto& previous = next;
const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty); const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, measured, gain); const estimation current = update(previous, measured, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h> #include <units/math.h>
#include <units/quantity_point.h> #include <units/quantity_point.h>
#include <units/unit.h> #include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> initial) void print_header(kalman::estimation<QP> initial)
{ {
std::cout << STD_FMT::format("Initial: {}\n", initial); std::cout << STD_FMT::format("Initial: {}\n", initial);
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate", "Next Estimate"); std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
"Next Estimate");
} }
template<QuantityPoint QP, Dimensionless K> template<QuantityPoint QP, Dimensionless K>
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next) void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
{ {
std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain, measured.relative(), current, next); std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
measured.relative(), current, next);
} }
int main() int main()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references; using namespace units::isq::si::references;
const auto process_noise_variance = 0.0001 * (deg_C * deg_C); const auto process_noise_variance = 0.0001 * (deg_C * deg_C);
const estimation initial = { state{ quantity_point(10. * deg_C) }, pow<2>(100. * deg_C) }; const estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = { const std::array measurements = {quantity_point(49.95 * deg_C), quantity_point(49.967 * deg_C),
quantity_point(49.95 * deg_C), quantity_point(50.1 * deg_C), quantity_point(50.106 * deg_C),
quantity_point(49.967 * deg_C), quantity_point(49.992 * deg_C), quantity_point(49.819 * deg_C),
quantity_point(50.1 * deg_C), quantity_point(49.933 * deg_C), quantity_point(50.007 * deg_C),
quantity_point(50.106 * deg_C), quantity_point(50.023 * deg_C), quantity_point(49.99 * deg_C)};
quantity_point(49.992 * deg_C),
quantity_point(49.819 * deg_C),
quantity_point(49.933 * deg_C),
quantity_point(50.007 * deg_C),
quantity_point(50.023 * deg_C),
quantity_point(49.99 * deg_C)
};
const auto measurement_uncertainty = pow<2>(0.1 * deg_C); const auto measurement_uncertainty = pow<2>(0.1 * deg_C);
auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) { auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) {
return estimation{ state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain) }; return estimation{state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain)};
}; };
auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) { auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) {
return estimation{ current.state, covariance_extrapolation(current.uncertainty, process_noise_variance) }; return estimation{current.state, covariance_extrapolation(current.uncertainty, process_noise_variance)};
}; };
print_header(initial); print_header(initial);
estimation next = predict(initial); estimation next = predict(initial);
for(int index = 1; const auto& m : measurements) { for (int index = 1; const auto& m : measurements) {
const auto& previous = next; const auto& previous = next;
const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty); const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain); const estimation current = update(previous, m, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h> #include <units/math.h>
#include <units/quantity_point.h> #include <units/quantity_point.h>
#include <units/unit.h> #include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> initial) void print_header(kalman::estimation<QP> initial)
{ {
std::cout << STD_FMT::format("Initial: {}\n", initial); std::cout << STD_FMT::format("Initial: {}\n", initial);
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate", "Next Estimate"); std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>18} | {:>18}\n", "N", "Gain", "Measured", "Curr. Estimate",
"Next Estimate");
} }
template<QuantityPoint QP, Dimensionless K> template<QuantityPoint QP, Dimensionless K>
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next) void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
{ {
std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain, measured.relative(), current, next); std::cout << STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
measured.relative(), current, next);
} }
int main() int main()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references; using namespace units::isq::si::references;
const auto process_noise_variance = 0.0001 * (deg_C * deg_C); const auto process_noise_variance = 0.0001 * (deg_C * deg_C);
const estimation initial = { state{ quantity_point(10. * deg_C) }, pow<2>(100. * deg_C) }; const estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = { const std::array measurements = {quantity_point(50.45 * deg_C), quantity_point(50.967 * deg_C),
quantity_point(50.45 * deg_C), quantity_point(51.6 * deg_C), quantity_point(52.106 * deg_C),
quantity_point(50.967 * deg_C), quantity_point(52.492 * deg_C), quantity_point(52.819 * deg_C),
quantity_point(51.6 * deg_C), quantity_point(53.433 * deg_C), quantity_point(54.007 * deg_C),
quantity_point(52.106 * deg_C), quantity_point(54.523 * deg_C), quantity_point(54.99 * deg_C)};
quantity_point(52.492 * deg_C),
quantity_point(52.819 * deg_C),
quantity_point(53.433 * deg_C),
quantity_point(54.007 * deg_C),
quantity_point(54.523 * deg_C),
quantity_point(54.99 * deg_C)
};
const auto measurement_uncertainty = pow<2>(0.1 * deg_C); const auto measurement_uncertainty = pow<2>(0.1 * deg_C);
auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) { auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) {
return estimation{ state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain) }; return estimation{state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain)};
}; };
auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) { auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) {
return estimation{ current.state, covariance_extrapolation(current.uncertainty, process_noise_variance) }; return estimation{current.state, covariance_extrapolation(current.uncertainty, process_noise_variance)};
}; };
print_header(initial); print_header(initial);
estimation next = predict(initial); estimation next = predict(initial);
for(int index = 1; const auto& m : measurements) { for (int index = 1; const auto& m : measurements) {
const auto& previous = next; const auto& previous = next;
const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty); const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain); const estimation current = update(previous, m, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE. // SOFTWARE.
#include "kalman.h" #include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h> #include <units/math.h>
#include <units/quantity_point.h> #include <units/quantity_point.h>
#include <units/unit.h> #include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> initial) void print_header(kalman::estimation<QP> initial)
{ {
std::cout << STD_FMT::format("Initial: {}\n", initial); std::cout << STD_FMT::format("Initial: {}\n", initial);
std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate", "Next Estimate"); std::cout << STD_FMT::format("{:>2} | {:>7} | {:>10} | {:>16} | {:>16}\n", "N", "Gain", "Measured", "Curr. Estimate",
"Next Estimate");
} }
template<QuantityPoint QP, Dimensionless K> template<QuantityPoint QP, Dimensionless K>
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next) void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
{ {
std::cout << STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain, measured.relative(), current, next); std::cout << STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
measured.relative(), current, next);
} }
int main() int main()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references; using namespace units::isq::si::references;
const auto process_noise_variance = 0.15 * (deg_C * deg_C); const auto process_noise_variance = 0.15 * (deg_C * deg_C);
const estimation initial = { state{ quantity_point(10. * deg_C) }, pow<2>(100. * deg_C) }; const estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = { const std::array measurements = {quantity_point(50.45 * deg_C), quantity_point(50.967 * deg_C),
quantity_point(50.45 * deg_C), quantity_point(51.6 * deg_C), quantity_point(52.106 * deg_C),
quantity_point(50.967 * deg_C), quantity_point(52.492 * deg_C), quantity_point(52.819 * deg_C),
quantity_point(51.6 * deg_C), quantity_point(53.433 * deg_C), quantity_point(54.007 * deg_C),
quantity_point(52.106 * deg_C), quantity_point(54.523 * deg_C), quantity_point(54.99 * deg_C)};
quantity_point(52.492 * deg_C),
quantity_point(52.819 * deg_C),
quantity_point(53.433 * deg_C),
quantity_point(54.007 * deg_C),
quantity_point(54.523 * deg_C),
quantity_point(54.99 * deg_C)
};
const auto measurement_uncertainty = pow<2>(0.1 * deg_C); const auto measurement_uncertainty = pow<2>(0.1 * deg_C);
auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) { auto update = [=]<QuantityPoint QP>(const estimation<QP>& previous, const QP& meassurement, Dimensionless auto gain) {
return estimation{ state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain) }; return estimation{state_update(previous.state, meassurement, gain), covariance_update(previous.uncertainty, gain)};
}; };
auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) { auto predict = [=]<QuantityPoint QP>(const estimation<QP>& current) {
return estimation{ current.state, covariance_extrapolation(current.uncertainty, process_noise_variance) }; return estimation{current.state, covariance_extrapolation(current.uncertainty, process_noise_variance)};
}; };
print_header(initial); print_header(initial);
estimation next = predict(initial); estimation next = predict(initial);
for(int index = 1; const auto& m : measurements) { for (int index = 1; const auto& m : measurements) {
const auto& previous = next; const auto& previous = next;
const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty); const auto gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain); const estimation current = update(previous, m, gain);

View File

@@ -28,16 +28,23 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-literals ${target}.cpp) add_executable(${target}-literals ${target}.cpp)
target_link_libraries(${target}-literals PRIVATE ${ARGN}) target_link_libraries(${target}-literals PRIVATE ${ARGN})
target_compile_definitions(${target}-literals PRIVATE target_compile_definitions(${target}-literals PRIVATE ${projectPrefix}NO_REFERENCES ${projectPrefix}NO_ALIASES)
${projectPrefix}NO_REFERENCES
${projectPrefix}NO_ALIASES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
add_example(box_example mp-units::core-fmt mp-units::si) add_example(box_example mp-units::core-fmt mp-units::si)
add_example(capacitor_time_curve mp-units::core-io mp-units::si) add_example(capacitor_time_curve mp-units::core-io mp-units::si)
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-uscs) add_example(
clcpp_response
mp-units::core-fmt
mp-units::core-io
mp-units::si
mp-units::si-iau
mp-units::si-imperial
mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
)
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si) add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps) add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural) add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural)
@@ -45,9 +52,8 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT ${projectPrefix}LIBCXX) if(NOT ${projectPrefix}LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-literals PRIVATE target_compile_definitions(
${projectPrefix}NO_REFERENCES glide_computer_example-literals PRIVATE ${projectPrefix}NO_REFERENCES ${projectPrefix}NO_ALIASES
${projectPrefix}NO_ALIASES
) )
find_package(wg21_linear_algebra CONFIG REQUIRED) find_package(wg21_linear_algebra CONFIG REQUIRED)

View File

@@ -21,12 +21,12 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/cgs/length.h> #include <units/isq/si/cgs/length.h>
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep #include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> // IWYU pragma: keep #include <units/isq/si/international/speed.h> // IWYU pragma: keep
#include <units/isq/si/length.h> // IWYU pragma: keep #include <units/isq/si/length.h> // IWYU pragma: keep
#include <units/isq/si/time.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -35,38 +35,31 @@ namespace {
using namespace units::isq; using namespace units::isq;
constexpr si::speed<si::metre_per_second, int> constexpr si::speed<si::metre_per_second, int> fixed_int_si_avg_speed(si::length<si::metre, int> d,
fixed_int_si_avg_speed(si::length<si::metre, int> d, si::time<si::second, int> t)
si::time<si::second, int> t)
{ {
return d / t; return d / t;
} }
constexpr si::speed<si::metre_per_second> constexpr si::speed<si::metre_per_second> fixed_double_si_avg_speed(si::length<si::metre> d, si::time<si::second> t)
fixed_double_si_avg_speed(si::length<si::metre> d,
si::time<si::second> t)
{ {
return d / t; return d / t;
} }
template<typename U1, typename R1, typename U2, typename R2> template<typename U1, typename R1, typename U2, typename R2>
constexpr Speed auto si_avg_speed(si::length<U1, R1> d, constexpr Speed auto si_avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
si::time<U2, R2> t)
{ {
return d / t; return d / t;
} }
constexpr Speed auto avg_speed(Length auto d, Time auto t) constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
{
return d / t;
}
template<Length D, Time T, Speed V> template<Length D, Time T, Speed V>
void print_result(D distance, T duration, V speed) void print_result(D distance, T duration, V speed)
{ {
const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed); const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed);
std::cout << "Average speed of a car that makes " << distance << " in " std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph
<< duration << " is " << result_in_kmph << ".\n"; << ".\n";
} }
void example() void example()
@@ -94,7 +87,8 @@ void example()
std::cout << "\nSI units with 'double' as representation\n"; std::cout << "\nSI units with 'double' as representation\n";
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration))); print_result(distance, duration,
fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -130,7 +124,9 @@ void example()
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// also it is not possible to make a lossless conversion of miles to meters on an integral type // also it is not possible to make a lossless conversion of miles to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -141,7 +137,7 @@ void example()
{ {
using namespace units::isq::si::cgs::literals; using namespace units::isq::si::cgs::literals;
constexpr auto distance = 22'000'000_q_cm; constexpr auto distance = 22'000'000_q_cm;
constexpr si::cgs::time<si::hour, int> duration(2); // cannot use an SI literal here constexpr si::cgs::time<si::hour, int> duration(2); // cannot use an SI literal here
std::cout << "\nCGS units with 'int' as representation\n"; std::cout << "\nCGS units with 'int' as representation\n";
@@ -160,14 +156,16 @@ void example()
{ {
using namespace units::isq::si::cgs::literals; using namespace units::isq::si::cgs::literals;
constexpr auto distance = 22'000'000._q_cm; constexpr auto distance = 22'000'000._q_cm;
constexpr si::cgs::time<si::hour, double> duration(2); // cannot use an SI literal here constexpr si::cgs::time<si::hour, double> duration(2); // cannot use an SI literal here
std::cout << "\nCGS units with 'double' as representation\n"; std::cout << "\nCGS units with 'double' as representation\n";
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// it is not possible to make a lossless conversion of centimeters to meters on an integral type // it is not possible to make a lossless conversion of centimeters to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
@@ -176,20 +174,17 @@ void example()
print_result(distance, duration, avg_speed(distance, duration)); print_result(distance, duration, avg_speed(distance, duration));
} }
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -29,7 +29,7 @@
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/volume.h> #include <units/isq/si/volume.h>
#include <cassert> #include <cassert>
@@ -56,7 +56,10 @@ class Box {
si::length<m> height_; si::length<m> height_;
si::density<kgpm3> density_ = air_density; si::density<kgpm3> density_ = air_density;
public: public:
constexpr Box(const si::length<m>& length, const si::length<m>& width, si::length<m> height) : base_(length * width), height_(std::move(height)) {} constexpr Box(const si::length<m>& length, const si::length<m>& width, si::length<m> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr si::force<N> filled_weight() const [[nodiscard]] constexpr si::force<N> filled_weight() const
{ {
@@ -94,13 +97,13 @@ int main()
auto box = Box(1000.0_q_mm, 500.0_q_mm, height); auto box = Box(1000.0_q_mm, 500.0_q_mm, height);
box.set_contents_density(1000.0_q_kg_per_m3); box.set_contents_density(1000.0_q_kg_per_m3);
const auto fill_time = 200.0_q_s; // time since starting fill const auto fill_time = 200.0_q_s; // time since starting fill
const auto measured_mass = 20.0_q_kg; // measured mass at fill_time const auto measured_mass = 20.0_q_kg; // measured mass at fill_time
const Length auto fill_level = box.fill_level(measured_mass); const Length auto fill_level = box.fill_level(measured_mass);
const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height); const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height);
const Volume auto spare_capacity = box.spare_capacity(measured_mass); const Volume auto spare_capacity = box.spare_capacity(measured_mass);
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
const Speed auto float_rise_rate = fill_level / fill_time; const Speed auto float_rise_rate = fill_level / fill_time;
const Time auto fill_time_left = (height / fill_level - 1) * fill_time; const Time auto fill_time_left = (height / fill_level - 1) * fill_time;

View File

@@ -26,7 +26,7 @@
#include <units/isq/si/resistance.h> #include <units/isq/si/resistance.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/voltage.h> #include <units/isq/si/voltage.h>
#include <units/math.h> // IWYU pragma: keep #include <units/math.h> // IWYU pragma: keep
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <iostream> #include <iostream>

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h> #include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h> #include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -53,7 +54,7 @@ struct Ship {
}; };
// Print 'a' in its current units and print its value cast to the units in each of Args // Print 'a' in its current units and print its value cast to the units in each of Args
template<class ...Args, units::Quantity Q> template<class... Args, units::Quantity Q>
auto fmt_line(const Q a) auto fmt_line(const Q a)
{ {
return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...); return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...);
@@ -65,16 +66,28 @@ void print_details(std::string_view description, const Ship& ship)
using namespace units::isq::si::fps::literals; using namespace units::isq::si::fps::literals;
const auto waterDensity = 62.4_q_lb_per_ft3; const auto waterDensity = 62.4_q_lb_per_ft3;
std::cout << STD_FMT::format("{}\n", description); std::cout << STD_FMT::format("{}\n", description);
std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length)) std::cout << STD_FMT::format("{:20} : {}\n", "length",
<< STD_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length))
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "draft",
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "beam",
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<si::fps::length<si::fps::inch>, si::length<si::millimetre>>(ship.mainGuns)) << STD_FMT::format("{:20} : {}\n", "mass",
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing",fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::kilogram>>(ship.shellMass)) fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "fire shells at",fmt_line<si::fps::speed<si::fps::mile_per_hour>, si::speed<si::kilometre_per_hour>>(ship.shellSpeed)) << STD_FMT::format(
<< STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<si::volume<si::cubic_metre>, si::volume<si::litre>>(ship.mass / waterDensity)); "{: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",
fmt_line<si::fps::length<si::fps::inch>, si::length<si::millimetre>>(ship.mainGuns))
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::kilogram>>(ship.shellMass))
<< STD_FMT::format(
"{:20} : {}\n", "fire shells at",
fmt_line<si::fps::speed<si::fps::mile_per_hour>, si::speed<si::kilometre_per_hour>>(ship.shellSpeed))
<< STD_FMT::format("{:20} : {}\n", "volume underwater",
fmt_line<si::volume<si::cubic_metre>, si::volume<si::litre>>(ship.mass / waterDensity));
} }
int main() int main()
@@ -83,13 +96,37 @@ int main()
using namespace units::isq::si::fps::literals; using namespace units::isq::si::fps::literals;
// KMS Bismark, using the units the Germans would use, taken from Wiki // KMS Bismark, using the units the Germans would use, taken from Wiki
auto bismark = Ship{.length{251._q_m}, .draft{9.3_q_m}, .beam{36_q_m}, .speed{56_q_km_per_h}, .mass{50'300_q_t}, .mainGuns{380_q_mm}, .shellMass{800_q_kg}, .shellSpeed{820._q_m_per_s}, .power{110.45_q_kW}}; auto bismark = Ship{.length{251._q_m},
.draft{9.3_q_m},
.beam{36_q_m},
.speed{56_q_km_per_h},
.mass{50'300_q_t},
.mainGuns{380_q_mm},
.shellMass{800_q_kg},
.shellSpeed{820._q_m_per_s},
.power{110.45_q_kW}};
// USS Iowa, using units from the foot-pound-second system // USS Iowa, using units from the foot-pound-second system
auto iowa = Ship{.length{860._q_ft}, .draft{37._q_ft + 2._q_in}, .beam{108._q_ft + 2._q_in}, .speed{33_q_knot}, .mass{57'540_q_lton}, .mainGuns{16_q_in}, .shellMass{2700_q_lb}, .shellSpeed{2690._q_ft_per_s}, .power{212'000_q_hp}}; auto iowa = Ship{.length{860._q_ft},
.draft{37._q_ft + 2._q_in},
.beam{108._q_ft + 2._q_in},
.speed{si::speed<si::international::knot>{33}},
.mass{57'540_q_lton},
.mainGuns{16_q_in},
.shellMass{2700_q_lb},
.shellSpeed{2690._q_ft_per_s},
.power{212'000_q_hp}};
// HMS King George V, using units from the foot-pound-second system // HMS King George V, using units from the foot-pound-second system
auto kgv = Ship{.length{745.1_q_ft}, .draft{33._q_ft + 7.5_q_in}, .beam{103.2_q_ft + 2.5_q_in}, .speed{28.3_q_knot}, .mass{42'245_q_lton}, .mainGuns{14_q_in}, .shellMass{1'590_q_lb}, .shellSpeed{2483._q_ft_per_s}, .power{110'000_q_hp}}; 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{si::speed<si::international::knot>{28.3}},
.mass{42'245_q_lton},
.mainGuns{14_q_in},
.shellMass{1'590_q_lb},
.shellSpeed{2483._q_ft_per_s},
.power{110'000_q_hp}};
print_details("KMS Bismark, defined in appropriate units from the SI system", bismark); print_details("KMS Bismark, defined in appropriate units from the SI system", bismark);
std::cout << "\n\n"; std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace si::literals; using namespace si::literals;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}}, glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}},
glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}}, glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}},
glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}}, glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}},
glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}}; glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{ {
using namespace si::literals; using namespace si::literals;
static const std::array weather_conditions = { static const std::array weather_conditions = {
std::pair("Good", weather{height(1900_q_m), rate_of_climb(4.3_q_m_per_s)}), std::pair("Good", weather{height(1900_q_m), rate_of_climb(4.3_q_m_per_s)}),
std::pair("Medium", weather{height(1550_q_m), rate_of_climb(2.8_q_m_per_s)}), std::pair("Medium", weather{height(1550_q_m), rate_of_climb(2.8_q_m_per_s)}),
std::pair("Bad", weather{height(850_q_m), rate_of_climb(1.8_q_m_per_s)})}; std::pair("Bad", weather{height(850_q_m), rate_of_climb(1.8_q_m_per_s)})};
return weather_conditions; return weather_conditions;
} }
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals; using namespace geographic::literals;
using namespace units::isq::si::international::literals; using namespace units::isq::si::international::literals;
static const std::array waypoints = { static const std::array waypoints = {
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16_q_ft)}, // N54°14'51.8" E18°40'28.2" waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16_q_ft)}, // N54°14'51.8" E18°40'28.2"
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115_q_ft)} // N53°31'27.9" E18°50'58.1" waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115_q_ft)} // N53°31'27.9" E18°50'58.1"
}; };
return waypoints; return waypoints;
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

@@ -20,14 +20,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/energy.h> // IWYU pragma: keep #include <units/format.h>
#include <units/isq/si/energy.h> // IWYU pragma: keep
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream> #include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA { namespace STD_LA {
@@ -73,9 +73,9 @@ void vector_of_quantity_add()
{ {
std::cout << "\nvector_of_quantity_add:\n"; std::cout << "\nvector_of_quantity_add:\n";
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m }; vector<si::length<si::metre>> v = {1_q_m, 2_q_m, 3_q_m};
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m }; vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
vector<si::length<si::kilometre>> t = { 3_q_km, 2_q_km, 1_q_km }; vector<si::length<si::kilometre>> t = {3_q_km, 2_q_km, 1_q_km};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -90,8 +90,8 @@ void vector_of_quantity_multiply_same()
{ {
std::cout << "\nvector_of_quantity_multiply_same:\n"; std::cout << "\nvector_of_quantity_multiply_same:\n";
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m }; vector<si::length<si::metre>> v = {1_q_m, 2_q_m, 3_q_m};
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m }; vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -104,8 +104,8 @@ void vector_of_quantity_multiply_different()
{ {
std::cout << "\nvector_of_quantity_multiply_different:\n"; std::cout << "\nvector_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N }; vector<si::force<si::newton>> v = {1_q_N, 2_q_N, 3_q_N};
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m }; vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -119,7 +119,7 @@ void vector_of_quantity_divide_by_scalar()
{ {
std::cout << "\nvector_of_quantity_divide_by_scalar:\n"; std::cout << "\nvector_of_quantity_divide_by_scalar:\n";
vector<si::length<si::metre>> v = { 4_q_m, 8_q_m, 12_q_m }; vector<si::length<si::metre>> v = {4_q_m, 8_q_m, 12_q_m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -140,9 +140,9 @@ void matrix_of_quantity_add()
{ {
std::cout << "\nmatrix_of_quantity_add:\n"; std::cout << "\nmatrix_of_quantity_add:\n";
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }}; matrix<si::length<si::metre>> v = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
matrix<si::length<si::metre>> u = {{ 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }}; matrix<si::length<si::metre>> u = {{3_q_m, 2_q_m, 1_q_m}, {3_q_m, 2_q_m, 1_q_m}, {3_q_m, 2_q_m, 1_q_m}};
matrix<si::length<si::millimetre>> t = {{ 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }}; matrix<si::length<si::millimetre>> t = {{3_q_mm, 2_q_mm, 1_q_mm}, {3_q_mm, 2_q_mm, 1_q_mm}, {3_q_mm, 2_q_mm, 1_q_mm}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -159,8 +159,8 @@ void matrix_of_quantity_multiply_same()
{ {
std::cout << "\nmatrix_of_quantity_multiply_same:\n"; std::cout << "\nmatrix_of_quantity_multiply_same:\n";
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }}; matrix<si::length<si::metre>> v = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m }; vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -173,8 +173,8 @@ void matrix_of_quantity_multiply_different()
{ {
std::cout << "\nmatrix_of_quantity_multiply_different:\n"; std::cout << "\nmatrix_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N }; vector<si::force<si::newton>> v = {1_q_N, 2_q_N, 3_q_N};
matrix<si::length<si::metre>> u = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }}; matrix<si::length<si::metre>> u = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -188,7 +188,7 @@ void matrix_of_quantity_divide_by_scalar()
{ {
std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n"; std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n";
matrix<si::length<si::metre>> v = {{ 2_q_m, 4_q_m, 6_q_m }, { 4_q_m, 6_q_m, 8_q_m }, { 8_q_m, 4_q_m, 2_q_m }}; matrix<si::length<si::metre>> v = {{2_q_m, 4_q_m, 6_q_m}, {4_q_m, 6_q_m, 8_q_m}, {8_q_m, 4_q_m, 2_q_m}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
@@ -215,9 +215,9 @@ void quantity_of_vector_add()
{ {
std::cout << "\nquantity_of_vector_add:\n"; std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{ 3, 2, 1 }); length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -232,8 +232,8 @@ void quantity_of_vector_multiply_same()
{ {
std::cout << "\nquantity_of_vector_multiply_same:\n"; std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -246,8 +246,8 @@ void quantity_of_vector_multiply_different()
{ {
std::cout << "\nquantity_of_vector_multiply_different:\n"; std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -261,7 +261,7 @@ void quantity_of_vector_divide_by_scalar()
{ {
std::cout << "\nquantity_of_vector_divide_by_scalar:\n"; std::cout << "\nquantity_of_vector_divide_by_scalar:\n";
length_v<> v(vector<>{ 4, 8, 12 }); length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -285,9 +285,9 @@ void quantity_of_matrix_add()
{ {
std::cout << "\nquantity_of_matrix_add:\n"; std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -304,8 +304,8 @@ void quantity_of_matrix_multiply_same()
{ {
std::cout << "\nquantity_of_matrix_multiply_same:\n"; std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -318,8 +318,8 @@ void quantity_of_matrix_multiply_different()
{ {
std::cout << "\nquantity_of_matrix_multiply_different:\n"; std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -333,7 +333,7 @@ void quantity_of_matrix_divide_by_scalar()
{ {
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n"; std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }}); length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";

View File

@@ -21,11 +21,11 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/natural/natural.h> #include <units/isq/natural/natural.h>
#include <units/isq/si/constants.h>
#include <units/isq/si/energy.h> #include <units/isq/si/energy.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/momentum.h> #include <units/isq/si/momentum.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/constants.h>
#include <units/math.h> #include <units/math.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -88,18 +88,16 @@ void natural_example()
<< "E = " << E << "\n"; << "E = " << E << "\n";
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
si_example(); si_example();
natural_example(); natural_example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -21,7 +21,7 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -44,8 +44,9 @@ void example()
Time auto t1 = 10_q_s; Time auto t1 = 10_q_s;
Speed auto v1 = avg_speed(d1, t1); Speed auto v1 = avg_speed(d1, t1);
auto temp1 = v1 * 50_q_m; // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit' auto temp1 =
Speed auto v2 = temp1 / 100_q_m; // back to known dimensions again v1 * 50_q_m; // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
Speed auto v2 = temp1 / 100_q_m; // back to known dimensions again
Length auto d2 = v2 * 60_q_s; Length auto d2 = v2 * 60_q_s;
std::cout << "d1 = " << d1 << '\n'; std::cout << "d1 = " << d1 << '\n';
@@ -56,17 +57,15 @@ void example()
std::cout << "d2 = " << d2 << '\n'; std::cout << "d2 = " << d2 << '\n';
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -38,8 +38,7 @@ public:
measurement() = default; measurement() = default;
constexpr explicit measurement(const value_type& val, const value_type& err = {}) : constexpr explicit measurement(const value_type& val, const value_type& err = {}) : value_(val)
value_(val)
{ {
// it sucks that using declaration cannot be provided for a constructor initializer list // it sucks that using declaration cannot be provided for a constructor initializer list
using namespace std; using namespace std;
@@ -133,7 +132,8 @@ void example()
const Speed auto v1 = a * t; const Speed auto v1 = a * t;
#if UNITS_DOWNCAST_MODE == 0 #if UNITS_DOWNCAST_MODE == 0
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::dim_speed, si::kilometre_per_hour>(v1) << '\n'; std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::dim_speed, si::kilometre_per_hour>(v1)
<< '\n';
#else #else
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n'; std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
#endif #endif

View File

@@ -28,16 +28,23 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-references ${target}.cpp) add_executable(${target}-references ${target}.cpp)
target_link_libraries(${target}-references PRIVATE ${ARGN}) target_link_libraries(${target}-references PRIVATE ${ARGN})
target_compile_definitions(${target}-references PRIVATE target_compile_definitions(${target}-references PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_ALIASES)
${projectPrefix}NO_LITERALS
${projectPrefix}NO_ALIASES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
add_example(box_example mp-units::core-fmt mp-units::si) add_example(box_example mp-units::core-fmt mp-units::si)
add_example(capacitor_time_curve mp-units::core-io mp-units::si) add_example(capacitor_time_curve mp-units::core-io mp-units::si)
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-uscs) add_example(
clcpp_response
mp-units::core-fmt
mp-units::core-io
mp-units::si
mp-units::si-iau
mp-units::si-imperial
mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
)
add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si) add_example(experimental_angle mp-units::core-fmt mp-units::core-io mp-units::si)
add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps) add_example(foot_pound_second mp-units::core-fmt mp-units::si-fps)
add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural) add_example(total_energy mp-units::core-io mp-units::si mp-units::isq-natural)
@@ -45,9 +52,8 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT ${projectPrefix}LIBCXX) if(NOT ${projectPrefix}LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-references PRIVATE target_compile_definitions(
${projectPrefix}NO_LITERALS glide_computer_example-references PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_ALIASES
${projectPrefix}NO_ALIASES
) )
find_package(wg21_linear_algebra CONFIG REQUIRED) find_package(wg21_linear_algebra CONFIG REQUIRED)

View File

@@ -21,12 +21,12 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/cgs/length.h> #include <units/isq/si/cgs/length.h>
#include <units/isq/si/cgs/speed.h> // IWYU pragma: keep #include <units/isq/si/cgs/speed.h> // IWYU pragma: keep
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> // IWYU pragma: keep #include <units/isq/si/international/speed.h> // IWYU pragma: keep
#include <units/isq/si/length.h> // IWYU pragma: keep #include <units/isq/si/length.h> // IWYU pragma: keep
#include <units/isq/si/time.h>
#include <units/isq/si/speed.h> #include <units/isq/si/speed.h>
#include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -35,38 +35,31 @@ namespace {
using namespace units::isq; using namespace units::isq;
constexpr si::speed<si::metre_per_second, int> constexpr si::speed<si::metre_per_second, int> fixed_int_si_avg_speed(si::length<si::metre, int> d,
fixed_int_si_avg_speed(si::length<si::metre, int> d, si::time<si::second, int> t)
si::time<si::second, int> t)
{ {
return d / t; return d / t;
} }
constexpr si::speed<si::metre_per_second> constexpr si::speed<si::metre_per_second> fixed_double_si_avg_speed(si::length<si::metre> d, si::time<si::second> t)
fixed_double_si_avg_speed(si::length<si::metre> d,
si::time<si::second> t)
{ {
return d / t; return d / t;
} }
template<typename U1, typename R1, typename U2, typename R2> template<typename U1, typename R1, typename U2, typename R2>
constexpr Speed auto si_avg_speed(si::length<U1, R1> d, constexpr Speed auto si_avg_speed(si::length<U1, R1> d, si::time<U2, R2> t)
si::time<U2, R2> t)
{ {
return d / t; return d / t;
} }
constexpr Speed auto avg_speed(Length auto d, Time auto t) constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
{
return d / t;
}
template<Length D, Time T, Speed V> template<Length D, Time T, Speed V>
void print_result(D distance, T duration, V speed) void print_result(D distance, T duration, V speed)
{ {
const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed); const auto result_in_kmph = units::quantity_cast<si::speed<si::kilometre_per_hour>>(speed);
std::cout << "Average speed of a car that makes " << distance << " in " std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph
<< duration << " is " << result_in_kmph << ".\n"; << ".\n";
} }
void example() void example()
@@ -94,7 +87,8 @@ void example()
std::cout << "\nSI units with 'double' as representation\n"; std::cout << "\nSI units with 'double' as representation\n";
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration))); print_result(distance, duration,
fixed_int_si_avg_speed(quantity_cast<int>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -130,7 +124,9 @@ void example()
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// also it is not possible to make a lossless conversion of miles to meters on an integral type // also it is not possible to make a lossless conversion of miles to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, si_avg_speed(distance, duration));
@@ -169,7 +165,9 @@ void example()
// conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed
// it is not possible to make a lossless conversion of centimeters to meters on an integral type // it is not possible to make a lossless conversion of centimeters to meters on an integral type
// (explicit cast needed) // (explicit cast needed)
print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration))); print_result(
distance, duration,
fixed_int_si_avg_speed(quantity_cast<si::length<si::metre, int>>(distance), quantity_cast<int>(duration)));
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
@@ -178,20 +176,17 @@ void example()
print_result(distance, duration, avg_speed(distance, duration)); print_result(distance, duration, avg_speed(distance, duration));
} }
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -29,7 +29,7 @@
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/volume.h> #include <units/isq/si/volume.h>
#include <cassert> #include <cassert>
@@ -50,7 +50,10 @@ class Box {
si::length<si::metre> height_; si::length<si::metre> height_;
si::density<si::kilogram_per_metre_cub> density_ = air_density; si::density<si::kilogram_per_metre_cub> density_ = air_density;
public: public:
constexpr Box(const si::length<si::metre>& length, const si::length<si::metre>& width, si::length<si::metre> height) : base_(length * width), height_(std::move(height)) {} constexpr Box(const si::length<si::metre>& length, const si::length<si::metre>& width, si::length<si::metre> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr si::force<si::newton> filled_weight() const [[nodiscard]] constexpr si::force<si::newton> filled_weight() const
{ {
@@ -90,13 +93,13 @@ int main()
auto box = Box(1000.0 * mm, 500.0 * mm, height); auto box = Box(1000.0 * mm, 500.0 * mm, height);
box.set_contents_density(1000.0 * (kg / m3)); box.set_contents_density(1000.0 * (kg / m3));
const auto fill_time = 200.0 * s; // time since starting fill const auto fill_time = 200.0 * s; // time since starting fill
const auto measured_mass = 20.0 * kg; // measured mass at fill_time const auto measured_mass = 20.0 * kg; // measured mass at fill_time
const Length auto fill_level = box.fill_level(measured_mass); const Length auto fill_level = box.fill_level(measured_mass);
const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height); const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height);
const Volume auto spare_capacity = box.spare_capacity(measured_mass); const Volume auto spare_capacity = box.spare_capacity(measured_mass);
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
const Speed auto float_rise_rate = fill_level / fill_time; const Speed auto float_rise_rate = fill_level / fill_time;
const Time auto fill_time_left = (height / fill_level - 1) * fill_time; const Time auto fill_time_left = (height / fill_level - 1) * fill_time;

View File

@@ -26,7 +26,7 @@
#include <units/isq/si/resistance.h> #include <units/isq/si/resistance.h>
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/isq/si/voltage.h> #include <units/isq/si/voltage.h>
#include <units/math.h> // IWYU pragma: keep #include <units/math.h> // IWYU pragma: keep
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <iostream> #include <iostream>

View File

@@ -39,15 +39,15 @@ void simple_quantities()
using distance = si::length<si::metre>; using distance = si::length<si::metre>;
using duration = si::time<si::second>; using duration = si::time<si::second>;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW UNITS_DIAGNOSTIC_IGNORE_SHADOW
constexpr distance km = 1.0 * references::km; constexpr distance km = 1.0 * references::km;
constexpr distance miles = 1.0 * mi; constexpr distance miles = 1.0 * mi;
constexpr duration sec = 1 * s; constexpr duration sec = 1 * s;
constexpr duration min = 1 * references::min; constexpr duration min = 1 * references::min;
constexpr duration hr = 1 * h; constexpr duration hr = 1 * h;
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
std::cout << "A physical quantities library can choose the simple\n"; std::cout << "A physical quantities library can choose the simple\n";
std::cout << "option to provide output using a single type for each base unit:\n\n"; std::cout << "option to provide output using a single type for each base unit:\n\n";
@@ -66,8 +66,8 @@ void quantities_with_typed_units()
using namespace units::isq::si::international; using namespace units::isq::si::international;
using namespace units::isq::si::international::references; using namespace units::isq::si::international::references;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW UNITS_DIAGNOSTIC_IGNORE_SHADOW
constexpr length<kilometre> km = 1.0 * si::references::km; constexpr length<kilometre> km = 1.0 * si::references::km;
constexpr length<mile> miles = 1.0 * mi; constexpr length<mile> miles = 1.0 * mi;
@@ -76,7 +76,7 @@ UNITS_DIAGNOSTIC_IGNORE_SHADOW
constexpr si::time<second> sec = 1 * s; constexpr si::time<second> sec = 1 * s;
constexpr si::time<minute> min = 1 * si::references::min; constexpr si::time<minute> min = 1 * si::references::min;
constexpr si::time<hour> hr = 1 * h; constexpr si::time<hour> hr = 1 * h;
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
std::cout << "A more flexible option is to provide separate types for each unit,\n\n"; std::cout << "A more flexible option is to provide separate types for each unit,\n\n";
std::cout << km << '\n'; std::cout << km << '\n';

View File

@@ -20,17 +20,17 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <units/bits/external/hacks.h> // IWYU pragma: keep #include <units/bits/external/hacks.h> // IWYU pragma: keep
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW UNITS_DIAGNOSTIC_IGNORE_SHADOW
#include <units/isq/si/force.h> // 'N' (Newton) shadows a template parameter traditionally used as a size of the array #include <units/isq/si/force.h> // 'N' (Newton) shadows a template parameter traditionally used as a size of the array
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
#include <units/generic/angle.h> #include <units/generic/angle.h>
#include <units/isq/si/energy.h> #include <units/isq/si/energy.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/torque.h> // IWYU pragma: keep #include <units/isq/si/torque.h> // IWYU pragma: keep
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <iostream> #include <iostream>

View File

@@ -21,13 +21,14 @@
// SOFTWARE. // SOFTWARE.
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/fps/density.h> // IWYU pragma: keep #include <units/isq/si/fps/density.h> // IWYU pragma: keep
#include <units/isq/si/fps/length.h> #include <units/isq/si/fps/length.h>
#include <units/isq/si/fps/mass.h> #include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h> #include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/fps/time.h> #include <units/isq/si/fps/time.h>
#include <units/isq/si/fps/volume.h> #include <units/isq/si/fps/volume.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/power.h> #include <units/isq/si/power.h>
@@ -56,7 +57,7 @@ struct Ship {
}; };
// Print 'a' in its current units and print its value cast to the units in each of Args // Print 'a' in its current units and print its value cast to the units in each of Args
template<class ...Args, units::Quantity Q> template<class... Args, units::Quantity Q>
auto fmt_line(const Q a) auto fmt_line(const Q a)
{ {
return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...); return STD_FMT::format("{:22}", a) + (STD_FMT::format(",{:20}", units::quantity_cast<Args>(a)) + ...);
@@ -68,16 +69,28 @@ void print_details(std::string_view description, const Ship& ship)
using namespace units::isq::si::fps::references; using namespace units::isq::si::fps::references;
const auto waterDensity = 62.4 * (lb / ft3); const auto waterDensity = 62.4 * (lb / ft3);
std::cout << STD_FMT::format("{}\n", description); std::cout << STD_FMT::format("{}\n", description);
std::cout << STD_FMT::format("{:20} : {}\n", "length", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length)) std::cout << STD_FMT::format("{:20} : {}\n", "length",
<< STD_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length))
<< STD_FMT::format("{:20} : {}\n", "beam", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "draft",
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "beam",
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power<si::fps::horse_power>, si::power<si::kilowatt>>(ship.power)) fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<si::fps::length<si::fps::inch>, si::length<si::millimetre>>(ship.mainGuns)) << STD_FMT::format("{:20} : {}\n", "mass",
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::kilogram>>(ship.shellMass)) fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "fire shells at", fmt_line<si::fps::speed<si::fps::mile_per_hour>, si::speed<si::kilometre_per_hour>>(ship.shellSpeed)) << STD_FMT::format(
<< STD_FMT::format("{:20} : {}\n", "volume underwater", fmt_line<si::volume<si::cubic_metre>, si::volume<si::litre>>(ship.mass / waterDensity)); "{: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",
fmt_line<si::fps::length<si::fps::inch>, si::length<si::millimetre>>(ship.mainGuns))
<< STD_FMT::format("{:20} : {}\n", "fire shells weighing",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::kilogram>>(ship.shellMass))
<< STD_FMT::format(
"{:20} : {}\n", "fire shells at",
fmt_line<si::fps::speed<si::fps::mile_per_hour>, si::speed<si::kilometre_per_hour>>(ship.shellSpeed))
<< STD_FMT::format("{:20} : {}\n", "volume underwater",
fmt_line<si::volume<si::cubic_metre>, si::volume<si::litre>>(ship.mass / waterDensity));
} }
int main() int main()
@@ -87,13 +100,37 @@ int main()
using units::isq::si::fps::references::ft; // collides with si::femtotonne (alias unit of mass) using units::isq::si::fps::references::ft; // collides with si::femtotonne (alias unit of mass)
// KMS Bismark, using the units the Germans would use, taken from Wiki // KMS Bismark, using the units the Germans would use, taken from Wiki
auto bismark = Ship{.length{251. * m}, .draft{9.3 * m}, .beam{36 * m}, .speed{56 * (km / h)}, .mass{50'300 * t}, .mainGuns{380 * mm}, .shellMass{800 * kg}, .shellSpeed{820. * (m / s)}, .power{110.45 * kW}}; auto bismark = Ship{.length{251. * m},
.draft{9.3 * m},
.beam{36 * m},
.speed{56 * (km / h)},
.mass{50'300 * t},
.mainGuns{380 * mm},
.shellMass{800 * kg},
.shellSpeed{820. * (m / s)},
.power{110.45 * kW}};
// USS Iowa, using units from the foot-pound-second system // USS Iowa, using units from the foot-pound-second system
auto iowa = Ship{.length{860. * ft}, .draft{37. * ft + 2. * in}, .beam{108. * ft + 2. * in}, .speed{33 * knot}, .mass{57'540 * lton}, .mainGuns{16 * in}, .shellMass{2700 * lb}, .shellSpeed{2690. * (ft / s)}, .power{212'000 * hp}}; auto iowa = Ship{.length{860. * ft},
.draft{37. * ft + 2. * in},
.beam{108. * ft + 2. * in},
.speed{33 * units::isq::si::international::references::kn},
.mass{57'540 * lton},
.mainGuns{16 * in},
.shellMass{2700 * lb},
.shellSpeed{2690. * (ft / s)},
.power{212'000 * hp}};
// HMS King George V, using units from the foot-pound-second system // HMS King George V, using units from the foot-pound-second system
auto kgv = Ship{.length{745.1 * ft}, .draft{33. * ft + 7.5 * in}, .beam{103.2 * ft + 2.5 * in}, .speed{28.3 * knot}, .mass{42'245 * lton}, .mainGuns{14 * in}, .shellMass{1'590 * lb}, .shellSpeed{2483. * (ft / s)}, .power{110'000 * hp}}; auto kgv = Ship{.length{745.1 * ft},
.draft{33. * ft + 7.5 * in},
.beam{103.2 * ft + 2.5 * in},
.speed{28.3 * units::isq::si::international::references::kn},
.mass{42'245 * lton},
.mainGuns{14 * in},
.shellMass{1'590 * lb},
.shellSpeed{2483. * (ft / s)},
.power{110'000 * hp}};
print_details("KMS Bismark, defined in appropriate units from the SI system", bismark); print_details("KMS Bismark, defined in appropriate units from the SI system", bismark);
std::cout << "\n\n"; std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace si::references; using namespace si::references;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(83 * (km / h)), rate_of_climb(-0.7389 * (m / s))}}, glider{"SZD-30 Pirat", {velocity(83 * (km / h)), rate_of_climb(-0.7389 * (m / s))}},
glider{"SZD-51 Junior", {velocity(80 * (km / h)), rate_of_climb(-0.6349 * (m / s))}}, glider{"SZD-51 Junior", {velocity(80 * (km / h)), rate_of_climb(-0.6349 * (m / s))}},
glider{"SZD-48 Jantar Std 3", {velocity(110 * (km / h)), rate_of_climb(-0.77355 * (m / s))}}, glider{"SZD-48 Jantar Std 3", {velocity(110 * (km / h)), rate_of_climb(-0.77355 * (m / s))}},
glider{"SZD-56 Diana", {velocity(110 * (km / h)), rate_of_climb(-0.63657 * (m / s))}}}; glider{"SZD-56 Diana", {velocity(110 * (km / h)), rate_of_climb(-0.63657 * (m / s))}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{ {
using namespace si::references; using namespace si::references;
static const std::array weather_conditions = { static const std::array weather_conditions = {
std::pair("Good", weather{height(1900 * m), rate_of_climb(4.3 * (m / s))}), std::pair("Good", weather{height(1900 * m), rate_of_climb(4.3 * (m / s))}),
std::pair("Medium", weather{height(1550 * m), rate_of_climb(2.8 * (m / s))}), std::pair("Medium", weather{height(1550 * m), rate_of_climb(2.8 * (m / s))}),
std::pair("Bad", weather{height(850 * m), rate_of_climb(1.8 * (m / s))})}; std::pair("Bad", weather{height(850 * m), rate_of_climb(1.8 * (m / s))})};
return weather_conditions; return weather_conditions;
} }
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals; using namespace geographic::literals;
using namespace units::isq::si::international::references; using namespace units::isq::si::international::references;
static const std::array waypoints = { static const std::array waypoints = {
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16 * ft)}, // N54°14'51.8" E18°40'28.2" waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16 * ft)}, // N54°14'51.8" E18°40'28.2"
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115 * ft)} // N53°31'27.9" E18°50'58.1" waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115 * ft)} // N53°31'27.9" E18°50'58.1"
}; };
return waypoints; return waypoints;
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

@@ -20,14 +20,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/energy.h> // IWYU pragma: keep #include <units/format.h>
#include <units/isq/si/energy.h> // IWYU pragma: keep
#include <units/isq/si/force.h> #include <units/isq/si/force.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream> #include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA { namespace STD_LA {
@@ -73,9 +73,9 @@ void vector_of_quantity_add()
{ {
std::cout << "\nvector_of_quantity_add:\n"; std::cout << "\nvector_of_quantity_add:\n";
vector<si::length<si::metre>> v = { 1 * m, 2 * m, 3 * m }; vector<si::length<si::metre>> v = {1 * m, 2 * m, 3 * m};
vector<si::length<si::metre>> u = { 3 * m, 2 * m, 1 * m }; vector<si::length<si::metre>> u = {3 * m, 2 * m, 1 * m};
vector<si::length<si::kilometre>> t = { 3 * km, 2 * km, 1 * km }; vector<si::length<si::kilometre>> t = {3 * km, 2 * km, 1 * km};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -90,8 +90,8 @@ void vector_of_quantity_multiply_same()
{ {
std::cout << "\nvector_of_quantity_multiply_same:\n"; std::cout << "\nvector_of_quantity_multiply_same:\n";
vector<si::length<si::metre>> v = { 1 * m, 2 * m, 3 * m }; vector<si::length<si::metre>> v = {1 * m, 2 * m, 3 * m};
vector<si::length<si::metre>> u = { 3 * m, 2 * m, 1 * m }; vector<si::length<si::metre>> u = {3 * m, 2 * m, 1 * m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -104,8 +104,8 @@ void vector_of_quantity_multiply_different()
{ {
std::cout << "\nvector_of_quantity_multiply_different:\n"; std::cout << "\nvector_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1 * N, 2 * N, 3 * N }; vector<si::force<si::newton>> v = {1 * N, 2 * N, 3 * N};
vector<si::length<si::metre>> u = { 3 * m, 2 * m, 1 * m }; vector<si::length<si::metre>> u = {3 * m, 2 * m, 1 * m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -119,7 +119,7 @@ void vector_of_quantity_divide_by_scalar()
{ {
std::cout << "\nvector_of_quantity_divide_by_scalar:\n"; std::cout << "\nvector_of_quantity_divide_by_scalar:\n";
vector<si::length<si::metre>> v = { 4 * m, 8 * m, 12 * m }; vector<si::length<si::metre>> v = {4 * m, 8 * m, 12 * m};
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -140,9 +140,9 @@ void matrix_of_quantity_add()
{ {
std::cout << "\nmatrix_of_quantity_add:\n"; std::cout << "\nmatrix_of_quantity_add:\n";
matrix<si::length<si::metre>> v = {{ 1 * m, 2 * m, 3 * m }, { 4 * m, 5 * m, 6 * m }, { 7 * m, 8 * m, 9 * m }}; matrix<si::length<si::metre>> v = {{1 * m, 2 * m, 3 * m}, {4 * m, 5 * m, 6 * m}, {7 * m, 8 * m, 9 * m}};
matrix<si::length<si::metre>> u = {{ 3 * m, 2 * m, 1 * m }, { 3 * m, 2 * m, 1 * m }, { 3 * m, 2 * m, 1 * m }}; matrix<si::length<si::metre>> u = {{3 * m, 2 * m, 1 * m}, {3 * m, 2 * m, 1 * m}, {3 * m, 2 * m, 1 * m}};
matrix<si::length<si::millimetre>> t = {{ 3 * mm, 2 * mm, 1 * mm }, { 3 * mm, 2 * mm, 1 * mm }, { 3 * mm, 2 * mm, 1 * mm }}; matrix<si::length<si::millimetre>> t = {{3 * mm, 2 * mm, 1 * mm}, {3 * mm, 2 * mm, 1 * mm}, {3 * mm, 2 * mm, 1 * mm}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -159,8 +159,8 @@ void matrix_of_quantity_multiply_same()
{ {
std::cout << "\nmatrix_of_quantity_multiply_same:\n"; std::cout << "\nmatrix_of_quantity_multiply_same:\n";
matrix<si::length<si::metre>> v = {{ 1 * m, 2 * m, 3 * m }, { 4 * m, 5 * m, 6 * m }, { 7 * m, 8 * m, 9 * m }}; matrix<si::length<si::metre>> v = {{1 * m, 2 * m, 3 * m}, {4 * m, 5 * m, 6 * m}, {7 * m, 8 * m, 9 * m}};
vector<si::length<si::metre>> u = { 3 * m, 2 * m, 1 * m }; vector<si::length<si::metre>> u = {3 * m, 2 * m, 1 * m};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -173,8 +173,8 @@ void matrix_of_quantity_multiply_different()
{ {
std::cout << "\nmatrix_of_quantity_multiply_different:\n"; std::cout << "\nmatrix_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1 * N, 2 * N, 3 * N }; vector<si::force<si::newton>> v = {1 * N, 2 * N, 3 * N};
matrix<si::length<si::metre>> u = {{ 1 * m, 2 * m, 3 * m }, { 4 * m, 5 * m, 6 * m }, { 7 * m, 8 * m, 9 * m }}; matrix<si::length<si::metre>> u = {{1 * m, 2 * m, 3 * m}, {4 * m, 5 * m, 6 * m}, {7 * m, 8 * m, 9 * m}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -188,7 +188,7 @@ void matrix_of_quantity_divide_by_scalar()
{ {
std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n"; std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n";
matrix<si::length<si::metre>> v = {{ 2 * m, 4 * m, 6 * m }, { 4 * m, 6 * m, 8 * m }, { 8 * m, 4 * m, 2 * m }}; matrix<si::length<si::metre>> v = {{2 * m, 4 * m, 6 * m}, {4 * m, 6 * m, 8 * m}, {8 * m, 4 * m, 2 * m}};
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
@@ -215,9 +215,9 @@ void quantity_of_vector_add()
{ {
std::cout << "\nquantity_of_vector_add:\n"; std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{ 3, 2, 1 }); length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -232,8 +232,8 @@ void quantity_of_vector_multiply_same()
{ {
std::cout << "\nquantity_of_vector_multiply_same:\n"; std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 }); length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -246,8 +246,8 @@ void quantity_of_vector_multiply_different()
{ {
std::cout << "\nquantity_of_vector_multiply_different:\n"; std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n"; std::cout << "u = " << u << "\n";
@@ -261,7 +261,7 @@ void quantity_of_vector_divide_by_scalar()
{ {
std::cout << "\nquantity_of_vector_divide_by_scalar:\n"; std::cout << "\nquantity_of_vector_divide_by_scalar:\n";
length_v<> v(vector<>{ 4, 8, 12 }); length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n"; std::cout << "v = " << v << "\n";
@@ -285,9 +285,9 @@ void quantity_of_matrix_add()
{ {
std::cout << "\nquantity_of_matrix_add:\n"; std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }}); length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -304,8 +304,8 @@ void quantity_of_matrix_multiply_same()
{ {
std::cout << "\nquantity_of_matrix_multiply_same:\n"; std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{ 3, 2, 1 }); length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -318,8 +318,8 @@ void quantity_of_matrix_multiply_different()
{ {
std::cout << "\nquantity_of_matrix_multiply_different:\n"; std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 }); force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}); length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n"; std::cout << "u =\n" << u << "\n";
@@ -333,7 +333,7 @@ void quantity_of_matrix_divide_by_scalar()
{ {
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n"; std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }}); length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n"; std::cout << "v =\n" << v << "\n";

View File

@@ -25,7 +25,7 @@
#include <units/isq/si/energy.h> #include <units/isq/si/energy.h>
#include <units/isq/si/mass.h> #include <units/isq/si/mass.h>
#include <units/isq/si/momentum.h> #include <units/isq/si/momentum.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/math.h> #include <units/math.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -87,18 +87,16 @@ void natural_example()
<< "E = " << E << "\n"; << "E = " << E << "\n";
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
si_example(); si_example();
natural_example(); natural_example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -21,7 +21,7 @@
// SOFTWARE. // SOFTWARE.
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep #include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/quantity_io.h> #include <units/quantity_io.h>
#include <exception> #include <exception>
@@ -44,8 +44,9 @@ void example()
Time auto t1 = 10 * s; Time auto t1 = 10 * s;
Speed auto v1 = avg_speed(d1, t1); Speed auto v1 = avg_speed(d1, t1);
auto temp1 = v1 * (50 * m); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit' auto temp1 =
Speed auto v2 = temp1 / (100 * m); // back to known dimensions again v1 * (50 * m); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
Speed auto v2 = temp1 / (100 * m); // back to known dimensions again
Length auto d2 = v2 * (60 * s); Length auto d2 = v2 * (60 * s);
std::cout << "d1 = " << d1 << '\n'; std::cout << "d1 = " << d1 << '\n';
@@ -56,17 +57,15 @@ void example()
std::cout << "d2 = " << d2 << '\n'; std::cout << "d2 = " << d2 << '\n';
} }
} // namespace } // namespace
int main() int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -20,11 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
project(mp-units project(mp-units VERSION 0.8.0 LANGUAGES CXX)
VERSION 0.8.0
LANGUAGES CXX
)
set(projectPrefix UNITS_) set(projectPrefix UNITS_)
@@ -47,12 +44,7 @@ add_subdirectory(systems)
# project-wide wrapper # project-wide wrapper
add_library(mp-units INTERFACE) add_library(mp-units INTERFACE)
target_link_libraries(mp-units INTERFACE target_link_libraries(mp-units INTERFACE mp-units::core mp-units::core-io mp-units::core-fmt mp-units::systems)
mp-units::core
mp-units::core-io
mp-units::core-fmt
mp-units::systems
)
add_library(mp-units::mp-units ALIAS mp-units) add_library(mp-units::mp-units ALIAS mp-units)
install(TARGETS mp-units EXPORT mp-unitsTargets) install(TARGETS mp-units EXPORT mp-unitsTargets)
@@ -63,11 +55,8 @@ include(CMakePackageConfigHelpers)
write_basic_package_version_file(mp-unitsConfigVersion.cmake COMPATIBILITY SameMajorVersion) write_basic_package_version_file(mp-unitsConfigVersion.cmake COMPATIBILITY SameMajorVersion)
# installation # installation
install(EXPORT mp-unitsTargets install(EXPORT mp-unitsTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units NAMESPACE mp-units::)
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units
NAMESPACE mp-units::
)
install(FILES mp-unitsConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/mp-unitsConfigVersion.cmake install(FILES mp-unitsConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/mp-unitsConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units
) )

View File

@@ -20,17 +20,46 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
function(validate_unparsed module prefix)
if(${prefix}_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}' " "for module '${module}'")
endif()
endfunction()
function(validate_argument_exists module prefix arg)
if(NOT ${prefix}_${arg})
message(FATAL_ERROR "'${arg}' not provided for module '${module}'")
endif()
endfunction()
function(validate_arguments_exists module prefix)
foreach(arg ${ARGN})
validate_argument_exists(${module} ${prefix} ${arg})
endforeach()
endfunction()
# #
# add_units_module(ModuleName <depependencies>...) # add_units_module(ModuleName
# DEPENDENCIES <depependency>...
# HEADERS <header_file>...)
# #
function(add_units_module name) function(add_units_module name)
add_library(mp-units-${name} INTERFACE) # parse arguments
target_link_libraries(mp-units-${name} INTERFACE ${ARGN}) set(multiValues DEPENDENCIES HEADERS)
target_include_directories(mp-units-${name} ${unitsAsSystem} INTERFACE cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "${multiValues}")
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> # 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>
) )
set_target_properties(mp-units-${name} PROPERTIES EXPORT_NAME ${name}) set_target_properties(mp-units-${name} PROPERTIES EXPORT_NAME ${name})
add_library(mp-units::${name} ALIAS mp-units-${name}) add_library(mp-units::${name} ALIAS mp-units-${name})

View File

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

View File

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

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
# core library options # core library options
set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode") set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode")
@@ -34,14 +34,38 @@ include(CheckLibcxxInUse)
check_libcxx_in_use(${projectPrefix}LIBCXX) check_libcxx_in_use(${projectPrefix}LIBCXX)
# core library definition # core library definition
add_library(mp-units-core INTERFACE) add_library(
target_compile_features(mp-units-core INTERFACE cxx_std_20) mp-units-core
target_link_libraries(mp-units-core INTERFACE INTERFACE
gsl::gsl-lite 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_include_directories(mp-units-core ${unitsAsSystem} INTERFACE target_compile_features(mp-units-core INTERFACE cxx_std_20)
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
$<INSTALL_INTERFACE:include> target_include_directories(
mp-units-core ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
) )
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
@@ -50,8 +74,9 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_link_libraries(mp-units-core INTERFACE range-v3::range-v3) target_link_libraries(mp-units-core INTERFACE range-v3::range-v3)
endif() endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(mp-units-core INTERFACE target_compile_options(
/utf-8 # Specifies both the source character set and the execution character set as UTF-8 mp-units-core
INTERFACE /utf-8 # Specifies both the source character set and the execution character set as UTF-8
) )
endif() endif()
@@ -59,7 +84,9 @@ if(DEFINED ${projectPrefix}DOWNCAST_MODE)
set(downcast_mode_options OFF ON AUTO) set(downcast_mode_options OFF ON AUTO)
list(FIND downcast_mode_options "${${projectPrefix}DOWNCAST_MODE}" downcast_mode) list(FIND downcast_mode_options "${${projectPrefix}DOWNCAST_MODE}" downcast_mode)
if(downcast_mode EQUAL -1) if(downcast_mode EQUAL -1)
message(FATAL_ERROR "'${projectPrefix}DOWNCAST_MODE' should be one of ${downcast_mode_options} ('${${projectPrefix}DOWNCAST_MODE}' received)") message(FATAL_ERROR
"'${projectPrefix}DOWNCAST_MODE' should be one of ${downcast_mode_options} ('${${projectPrefix}DOWNCAST_MODE}' received)"
)
else() else()
message(STATUS "${projectPrefix}DOWNCAST_MODE: ${${projectPrefix}DOWNCAST_MODE}") message(STATUS "${projectPrefix}DOWNCAST_MODE: ${${projectPrefix}DOWNCAST_MODE}")
target_compile_definitions(mp-units-core INTERFACE ${projectPrefix}DOWNCAST_MODE=${downcast_mode}) target_compile_definitions(mp-units-core INTERFACE ${projectPrefix}DOWNCAST_MODE=${downcast_mode})

View File

@@ -24,7 +24,6 @@
#include <units/bits/algorithm.h> #include <units/bits/algorithm.h>
#include <array> #include <array>
#include <cassert>
#include <cstddef> #include <cstddef>
#include <numeric> #include <numeric>
#include <optional> #include <optional>

View File

@@ -48,12 +48,16 @@ using angle = quantity<dim_angle<>, U, Rep>;
inline namespace literals { inline namespace literals {
// rad // rad
constexpr auto operator"" _q_rad(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return angle<radian, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_rad(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return angle<radian, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_rad(long double l) { return angle<radian, long double>(l); } constexpr auto operator"" _q_rad(long double l) { return angle<radian, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
@@ -69,6 +73,6 @@ using namespace angle_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units } // namespace units

View File

@@ -392,7 +392,7 @@ template<typename T, BasePower auto... BPs>
constexpr T get_value(const magnitude<BPs...>&) constexpr T get_value(const magnitude<BPs...>&)
{ {
// Force the expression to be evaluated in a constexpr context, to catch, e.g., overflow. // Force the expression to be evaluated in a constexpr context, to catch, e.g., overflow.
constexpr auto result = detail::checked_static_cast<T>((detail::compute_base_power<T>(BPs) * ...)); constexpr auto result = detail::checked_static_cast<T>((detail::compute_base_power<T>(BPs) * ... * T{1}));
return result; return result;
} }
@@ -480,6 +480,51 @@ constexpr auto operator*(magnitude<H1, T1...>, magnitude<H2, T2...>)
constexpr auto operator/(Magnitude auto l, Magnitude auto r) { return l * pow<-1>(r); } constexpr auto operator/(Magnitude auto l, Magnitude auto r) { return l * pow<-1>(r); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Magnitude numerator and denominator implementation.
namespace detail {
// The largest integer which can be extracted from any magnitude with only a single basis vector.
template<BasePower auto BP>
constexpr auto integer_part(magnitude<BP>)
{
constexpr auto power_num = numerator(BP.power);
constexpr auto power_den = denominator(BP.power);
if constexpr (std::is_integral_v<decltype(BP.get_base())> && (power_num >= power_den)) {
constexpr auto largest_integer_power = [=](BasePower auto bp) {
bp.power = (power_num / power_den); // Note: integer division intended.
return bp;
}(BP); // Note: lambda is immediately invoked.
return magnitude<largest_integer_power>{};
} else {
return magnitude<>{};
}
}
} // namespace detail
template<BasePower auto... BPs>
constexpr auto numerator(magnitude<BPs...>)
{
return (detail::integer_part(magnitude<BPs>{}) * ... * magnitude<>{});
}
constexpr auto denominator(Magnitude auto m) { return numerator(pow<-1>(m)); }
// Implementation of conversion to ratio goes here, because it needs `numerator()` and `denominator()`.
constexpr ratio as_ratio(Magnitude auto m)
requires(is_rational(decltype(m){}))
{
return ratio{
get_value<std::intmax_t>(numerator(m)),
get_value<std::intmax_t>(denominator(m)),
};
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// `as_magnitude()` implementation. // `as_magnitude()` implementation.

View File

@@ -87,6 +87,24 @@ struct ratio {
} }
[[nodiscard]] friend constexpr ratio operator/(const ratio& lhs, const ratio& rhs) { return lhs * inverse(rhs); } [[nodiscard]] friend constexpr ratio operator/(const ratio& lhs, const ratio& rhs) { return lhs * inverse(rhs); }
[[nodiscard]] friend constexpr std::intmax_t numerator(const ratio& r)
{
std::intmax_t true_num = r.num;
for (auto i = r.exp; i > 0; --i) {
true_num *= 10;
}
return true_num;
}
[[nodiscard]] friend constexpr std::intmax_t denominator(const ratio& r)
{
std::intmax_t true_den = r.den;
for (auto i = r.exp; i < 0; ++i) {
true_den *= 10;
}
return true_den;
}
}; };
[[nodiscard]] constexpr ratio inverse(const ratio& r) { return ratio(r.den, r.num, -r.exp); } [[nodiscard]] constexpr ratio inverse(const ratio& r) { return ratio(r.den, r.num, -r.exp); }

View File

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

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
# systems # systems
add_subdirectory(isq) add_subdirectory(isq)
@@ -38,19 +38,21 @@ add_subdirectory(si-uscs)
# wrapper for all the systems # wrapper for all the systems
add_library(mp-units-systems INTERFACE) add_library(mp-units-systems INTERFACE)
target_link_libraries(mp-units-systems INTERFACE target_link_libraries(
mp-units::isq mp-units-systems
mp-units::isq-iec80000 INTERFACE
mp-units::isq-natural mp-units::isq
mp-units::si mp-units::isq-iec80000
mp-units::si-cgs mp-units::isq-natural
mp-units::si-fps mp-units::si
mp-units::si-hep mp-units::si-cgs
mp-units::si-iau mp-units::si-fps
mp-units::si-imperial mp-units::si-hep
mp-units::si-international mp-units::si-iau
mp-units::si-typographic mp-units::si-imperial
mp-units::si-uscs mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
) )
add_library(mp-units::systems ALIAS mp-units-systems) add_library(mp-units::systems ALIAS mp-units-systems)
set_target_properties(mp-units-systems PROPERTIES EXPORT_NAME systems) set_target_properties(mp-units-systems PROPERTIES EXPORT_NAME systems)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,12 +44,16 @@ using acceleration = quantity<dim_acceleration, U, Rep>;
inline namespace literals { inline namespace literals {
// ft/s2 // ft/s2
constexpr auto operator"" _q_ft_per_s2(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return acceleration<foot_per_second_sq, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ft_per_s2(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return acceleration<foot_per_second_sq, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft_per_s2(long double l) { return acceleration<foot_per_second_sq, long double>(l); } constexpr auto operator"" _q_ft_per_s2(long double l) { return acceleration<foot_per_second_sq, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -57,8 +61,9 @@ constexpr auto operator"" _q_ft_per_s2(long double l) { return acceleration<foot
namespace units::aliases::isq::si::fps::inline acceleration { namespace units::aliases::isq::si::fps::inline acceleration {
template<Representation Rep = double> using ft_per_s2 = units::isq::si::fps::acceleration<units::isq::si::fps::foot_per_second_sq, Rep>; template<Representation Rep = double>
using ft_per_s2 = units::isq::si::fps::acceleration<units::isq::si::fps::foot_per_second_sq, Rep>;
} // namespace units::aliases::isq::si::fps::inline acceleration } // namespace units::aliases::isq::si::fps::inline acceleration
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -46,12 +46,16 @@ using area = quantity<dim_area, U, Rep>;
inline namespace literals { inline namespace literals {
// ft2 // ft2
constexpr auto operator"" _q_ft2(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<square_foot, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ft2(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<square_foot, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft2(long double l) { return area<square_foot, long double>(l); } constexpr auto operator"" _q_ft2(long double l) { return area<square_foot, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
@@ -67,7 +71,7 @@ using namespace area_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -75,8 +79,9 @@ using namespace area_references;
namespace units::aliases::isq::si::fps::inline area { namespace units::aliases::isq::si::fps::inline area {
template<Representation Rep = double> using ft2 = units::isq::si::fps::area<units::isq::si::fps::square_foot, Rep>; template<Representation Rep = double>
using ft2 = units::isq::si::fps::area<units::isq::si::fps::square_foot, Rep>;
} // namespace units::aliases::isq::si::fps::inlipne area } // namespace units::aliases::isq::si::fps::inline area
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -28,8 +28,8 @@
#include <units/symbol_text.h> #include <units/symbol_text.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/length.h> #include <units/isq/si/fps/length.h>
#include <units/isq/si/fps/mass.h>
#include <units/unit.h> #include <units/unit.h>
namespace units::isq::si::fps { namespace units::isq::si::fps {
@@ -46,12 +46,16 @@ using density = quantity<dim_density, U, Rep>;
inline namespace literals { inline namespace literals {
// lb/ft³ // lb/ft³
constexpr auto operator"" _q_lb_per_ft3(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return density<pound_per_foot_cub, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_lb_per_ft3(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return density<pound_per_foot_cub, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_lb_per_ft3(long double l) { return density<pound_per_foot_cub, long double>(l); } constexpr auto operator"" _q_lb_per_ft3(long double l) { return density<pound_per_foot_cub, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -59,8 +63,9 @@ constexpr auto operator"" _q_lb_per_ft3(long double l) { return density<pound_pe
namespace units::aliases::isq::si::fps::inline density { namespace units::aliases::isq::si::fps::inline density {
template<Representation Rep = double> using lb_per_ft3 = units::isq::si::fps::density<units::isq::si::fps::pound_per_foot_cub, Rep>; template<Representation Rep = double>
using lb_per_ft3 = units::isq::si::fps::density<units::isq::si::fps::pound_per_foot_cub, Rep>;
} // namespace units::aliases::isq::si::fps::inline density } // namespace units::aliases::isq::si::fps::inline density
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -40,7 +40,7 @@ struct foot_poundal : unit<foot_poundal> {};
struct dim_energy : isq::dim_energy<dim_energy, foot_poundal, dim_length, dim_force> {}; struct dim_energy : isq::dim_energy<dim_energy, foot_poundal, dim_length, dim_force> {};
// https://en.wikipedia.org/wiki/Foot-pound_(energy) // https://en.wikipedia.org/wiki/Foot-pound_(energy)
struct foot_pound_force : derived_unit<foot_pound_force, dim_energy, foot, pound_force> {}; struct foot_pound_force : derived_unit<foot_pound_force, dim_energy, foot, pound_force> {};
template<UnitOf<dim_energy> U, Representation Rep = double> template<UnitOf<dim_energy> U, Representation Rep = double>
using energy = quantity<dim_energy, U, Rep>; using energy = quantity<dim_energy, U, Rep>;
@@ -50,16 +50,24 @@ using energy = quantity<dim_energy, U, Rep>;
inline namespace literals { inline namespace literals {
// foot poundal // foot poundal
constexpr auto operator"" _q_ft_pdl(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return energy<foot_poundal, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ft_pdl(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return energy<foot_poundal, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft_pdl(long double l) { return energy<foot_poundal, long double>(l); } constexpr auto operator"" _q_ft_pdl(long double l) { return energy<foot_poundal, long double>(l); }
// foot_pound force // foot_pound force
constexpr auto operator"" _q_ft_lbf(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return energy<foot_pound_force, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ft_lbf(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return energy<foot_pound_force, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft_lbf(long double l) { return energy<foot_pound_force, long double>(l); } constexpr auto operator"" _q_ft_lbf(long double l) { return energy<foot_pound_force, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -67,9 +75,11 @@ constexpr auto operator"" _q_ft_lbf(long double l) { return energy<foot_pound_fo
namespace units::aliases::isq::si::fps::inline energy { namespace units::aliases::isq::si::fps::inline energy {
template<Representation Rep = double> using ft_pdl = units::isq::si::fps::energy<units::isq::si::fps::foot_poundal, Rep>; template<Representation Rep = double>
template<Representation Rep = double> using ft_lbf = units::isq::si::fps::energy<units::isq::si::fps::foot_pound_force, Rep>; using ft_pdl = units::isq::si::fps::energy<units::isq::si::fps::foot_poundal, Rep>;
template<Representation Rep = double>
using ft_lbf = units::isq::si::fps::energy<units::isq::si::fps::foot_pound_force, Rep>;
} // namespace units::aliases::isq::si::fps::inline energy } // namespace units::aliases::isq::si::fps::inline energy
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -57,20 +57,32 @@ using force = quantity<dim_force, U, Rep>;
inline namespace literals { inline namespace literals {
// poundal // poundal
constexpr auto operator"" _q_pdl(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<poundal, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_pdl(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<poundal, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_pdl(long double l) { return force<poundal, long double>(l); } constexpr auto operator"" _q_pdl(long double l) { return force<poundal, long double>(l); }
// pound force // pound force
constexpr auto operator"" _q_lbf(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<pound_force, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_lbf(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<pound_force, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_lbf(long double l) { return force<pound_force, long double>(l); } constexpr auto operator"" _q_lbf(long double l) { return force<pound_force, long double>(l); }
// kilopound force // kilopound force
constexpr auto operator"" _q_klbf(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<kilopound_force, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_klbf(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<kilopound_force, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_klbf(long double l) { return force<kilopound_force, long double>(l); } constexpr auto operator"" _q_klbf(long double l) { return force<kilopound_force, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
@@ -88,7 +100,7 @@ using namespace force_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -96,10 +108,13 @@ using namespace force_references;
namespace units::aliases::isq::si::fps::inline force { namespace units::aliases::isq::si::fps::inline force {
template<Representation Rep = double> using pdl = units::isq::si::fps::force<units::isq::si::fps::poundal, Rep>; template<Representation Rep = double>
template<Representation Rep = double> using lbf = units::isq::si::fps::force<units::isq::si::fps::pound_force, Rep>; using pdl = units::isq::si::fps::force<units::isq::si::fps::poundal, Rep>;
template<Representation Rep = double> using klbf = units::isq::si::fps::force<units::isq::si::fps::kilopound_force, Rep>; template<Representation Rep = double>
using lbf = units::isq::si::fps::force<units::isq::si::fps::pound_force, Rep>;
template<Representation Rep = double>
using klbf = units::isq::si::fps::force<units::isq::si::fps::kilopound_force, Rep>;
} // namespace units::aliases::isq::si::fps::inline force } // namespace units::aliases::isq::si::fps::inline force
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -23,17 +23,16 @@
#pragma once #pragma once
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/isq/si/fps/length.h>
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/time.h>
#include <units/isq/si/fps/acceleration.h> #include <units/isq/si/fps/acceleration.h>
#include <units/isq/si/fps/area.h> #include <units/isq/si/fps/area.h>
#include <units/isq/si/fps/density.h> #include <units/isq/si/fps/density.h>
#include <units/isq/si/fps/energy.h> #include <units/isq/si/fps/energy.h>
#include <units/isq/si/fps/force.h> #include <units/isq/si/fps/force.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/power.h>
#include <units/isq/si/fps/pressure.h> #include <units/isq/si/fps/pressure.h>
#include <units/isq/si/fps/speed.h> #include <units/isq/si/fps/speed.h>
#include <units/isq/si/fps/time.h>
#include <units/isq/si/fps/volume.h> #include <units/isq/si/fps/volume.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports

View File

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

View File

@@ -43,9 +43,12 @@ struct dim_pressure : isq::dim_pressure<dim_pressure, poundal_per_foot_sq, dim_f
template<UnitOf<dim_pressure> U, Representation Rep = double> template<UnitOf<dim_pressure> U, Representation Rep = double>
using pressure = quantity<dim_pressure, U, Rep>; using pressure = quantity<dim_pressure, U, Rep>;
struct pound_force_per_foot_sq : named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", si::prefix, ratio(32'174'049, 1'000'000), poundal_per_foot_sq> {}; struct pound_force_per_foot_sq :
named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", si::prefix, 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, ratio(1, 144), pound_force_per_foot_sq> {}; struct pound_force_per_inch_sq :
named_scaled_unit<pound_force_per_inch_sq, "psi", si::prefix, 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> {}; struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq, si::kilo, pound_force_per_inch_sq> {};
@@ -54,20 +57,32 @@ struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq,
inline namespace literals { inline namespace literals {
// Poundal per square foot // Poundal per square foot
constexpr auto operator"" _q_pdl_per_ft2(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return pressure<poundal_per_foot_sq, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_pdl_per_ft2(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return pressure<poundal_per_foot_sq, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_pdl_per_ft2(long double l) { return pressure<poundal_per_foot_sq, long double>(l); } constexpr auto operator"" _q_pdl_per_ft2(long double l) { return pressure<poundal_per_foot_sq, long double>(l); }
// Pounds per square inch // Pounds per square inch
constexpr auto operator"" _q_psi(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return pressure<pound_force_per_inch_sq, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_psi(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return pressure<pound_force_per_inch_sq, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_psi(long double l) { return pressure<pound_force_per_inch_sq, long double>(l); } constexpr auto operator"" _q_psi(long double l) { return pressure<pound_force_per_inch_sq, long double>(l); }
// kilopounds per square inch // kilopounds per square inch
constexpr auto operator"" _q_kpsi(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return pressure<kilopound_force_per_inch_sq, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_kpsi(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return pressure<kilopound_force_per_inch_sq, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_kpsi(long double l) { return pressure<kilopound_force_per_inch_sq, long double>(l); } constexpr auto operator"" _q_kpsi(long double l) { return pressure<kilopound_force_per_inch_sq, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
@@ -84,7 +99,7 @@ using namespace pressure_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -92,10 +107,13 @@ using namespace pressure_references;
namespace units::aliases::isq::si::fps::inline pressure { namespace units::aliases::isq::si::fps::inline pressure {
template<Representation Rep = double> using pdl_per_ft2 = units::isq::si::fps::pressure<units::isq::si::fps::poundal_per_foot_sq, Rep>; template<Representation Rep = double>
template<Representation Rep = double> using psi = units::isq::si::fps::pressure<units::isq::si::fps::pound_force_per_inch_sq, Rep>; using pdl_per_ft2 = units::isq::si::fps::pressure<units::isq::si::fps::poundal_per_foot_sq, Rep>;
template<Representation Rep = double> using kpsi = units::isq::si::fps::pressure<units::isq::si::fps::kilopound_force_per_inch_sq, Rep>; template<Representation Rep = double>
using psi = units::isq::si::fps::pressure<units::isq::si::fps::pound_force_per_inch_sq, Rep>;
template<Representation Rep = double>
using kpsi = units::isq::si::fps::pressure<units::isq::si::fps::kilopound_force_per_inch_sq, Rep>;
} // namespace units::aliases::isq::si::fps::inline pressure } // namespace units::aliases::isq::si::fps::inline pressure
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -41,36 +41,48 @@ struct dim_speed : isq::dim_speed<dim_speed, foot_per_second, dim_length, dim_ti
template<UnitOf<dim_speed> U, Representation Rep = double> template<UnitOf<dim_speed> U, Representation Rep = double>
using speed = quantity<dim_speed, U, Rep>; using speed = quantity<dim_speed, U, Rep>;
struct mile_per_hour : derived_unit<mile_per_hour, dim_speed, mile, hour>{}; struct mile_per_hour : derived_unit<mile_per_hour, dim_speed, mile, hour> {};
struct nautical_mile_per_hour : derived_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour>{}; struct nautical_mile_per_hour : derived_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour> {};
struct knot : alias_unit<nautical_mile_per_hour, "knot", no_prefix> {}; struct knot : alias_unit<nautical_mile_per_hour, "kn", no_prefix> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
// ft/s // ft/s
constexpr auto operator"" _q_ft_per_s(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return speed<foot_per_second, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ft_per_s(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return speed<foot_per_second, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft_per_s(long double l) { return speed<foot_per_second, long double>(l); } constexpr auto operator"" _q_ft_per_s(long double l) { return speed<foot_per_second, long double>(l); }
// mph // mph
constexpr auto operator"" _q_mph(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return speed<mile_per_hour, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_mph(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return speed<mile_per_hour, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_mph(long double l) { return speed<mile_per_hour, long double>(l); } constexpr auto operator"" _q_mph(long double l) { return speed<mile_per_hour, long double>(l); }
// kn // kn
constexpr auto operator"" _q_knot(unsigned long long l) { 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_kn(unsigned long long l)
constexpr auto operator"" _q_knot(long double l) { return speed<knot, long double>(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_kn(long double l) { return speed<knot, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace speed_references { namespace speed_references {
inline constexpr auto mph = reference<dim_speed, mile_per_hour>{}; inline constexpr auto mph = reference<dim_speed, mile_per_hour>{};
inline constexpr auto knot = reference<dim_speed, fps::knot>{}; inline constexpr auto kn = reference<dim_speed, fps::knot>{};
} // namespace speed_references } // namespace speed_references
@@ -80,7 +92,7 @@ using namespace speed_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps } // namespace units::isq::si::fps
@@ -88,10 +100,13 @@ using namespace speed_references;
namespace units::aliases::isq::si::fps::inline speed { namespace units::aliases::isq::si::fps::inline speed {
template<Representation Rep = double> using ft_per_s = units::isq::si::fps::speed<units::isq::si::fps::foot_per_second, Rep>; template<Representation Rep = double>
template<Representation Rep = double> using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>; using ft_per_s = units::isq::si::fps::speed<units::isq::si::fps::foot_per_second, Rep>;
template<Representation Rep = double> using knot = units::isq::si::fps::speed<units::isq::si::fps::knot, Rep>; template<Representation Rep = double>
using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>;
template<Representation Rep = double>
using kn = units::isq::si::fps::speed<units::isq::si::fps::knot, Rep>;
} // namespace units::aliases::isq::si::fps::inline speed } // namespace units::aliases::isq::si::fps::inline speed
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

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

View File

@@ -29,7 +29,7 @@
#include <units/symbol_text.h> #include <units/symbol_text.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
#include <units/isq/si/length.h> #include <units/isq/si/area.h>
#include <units/unit.h> #include <units/unit.h>
namespace units::isq::si::hep { namespace units::isq::si::hep {
@@ -50,27 +50,63 @@ struct milli_barn : prefixed_unit<milli_barn, milli, barn> {};
#ifndef UNITS_NO_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
constexpr auto operator"" _q_yb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<yocto_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_yb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<yocto_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_yb(long double l) { return area<yocto_barn, long double>(l); } constexpr auto operator"" _q_yb(long double l) { return area<yocto_barn, long double>(l); }
constexpr auto operator"" _q_zb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<zepto_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_zb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<zepto_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_zb(long double l) { return area<zepto_barn, long double>(l); } constexpr auto operator"" _q_zb(long double l) { return area<zepto_barn, long double>(l); }
constexpr auto operator"" _q_ab(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<atto_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ab(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<atto_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ab(long double l) { return area<atto_barn, long double>(l); } constexpr auto operator"" _q_ab(long double l) { return area<atto_barn, long double>(l); }
constexpr auto operator"" _q_fb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<femto_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_fb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<femto_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_fb(long double l) { return area<femto_barn, long double>(l); } constexpr auto operator"" _q_fb(long double l) { return area<femto_barn, long double>(l); }
constexpr auto operator"" _q_pb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<pico_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_pb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<pico_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_pb(long double l) { return area<pico_barn, long double>(l); } constexpr auto operator"" _q_pb(long double l) { return area<pico_barn, long double>(l); }
constexpr auto operator"" _q_nb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<nano_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_nb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<nano_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_nb(long double l) { return area<nano_barn, long double>(l); } constexpr auto operator"" _q_nb(long double l) { return area<nano_barn, long double>(l); }
constexpr auto operator"" _q_ub(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<micro_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_ub(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<micro_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ub(long double l) { return area<micro_barn, long double>(l); } constexpr auto operator"" _q_ub(long double l) { return area<micro_barn, long double>(l); }
constexpr auto operator"" _q_mb(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<milli_barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_mb(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<milli_barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_mb(long double l) { return area<milli_barn, long double>(l); } constexpr auto operator"" _q_mb(long double l) { return area<milli_barn, long double>(l); }
constexpr auto operator"" _q_b(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return area<barn, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_b(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return area<barn, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_b(long double l) { return area<barn, long double>(l); } constexpr auto operator"" _q_b(long double l) { return area<barn, long double>(l); }
} // namespace literals } // namespace literals
#endif // UNITS_NO_LITERALS #endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES #ifndef UNITS_NO_REFERENCES
@@ -86,7 +122,7 @@ using namespace area_references;
} // namespace references } // namespace references
#endif // UNITS_NO_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::hep } // namespace units::isq::si::hep
@@ -94,8 +130,9 @@ using namespace area_references;
namespace units::aliases::isq::si::hep::inline area { namespace units::aliases::isq::si::hep::inline area {
template<Representation Rep = double> using barn = units::isq::si::area<units::isq::si::hep::barn, Rep>; template<Representation Rep = double>
using barn = units::isq::si::area<units::isq::si::hep::barn, Rep>;
} // namespace units::aliases::isq::si::hep::inline area } // namespace units::aliases::isq::si::hep::inline area
#endif // UNITS_NO_ALIASES #endif // UNITS_NO_ALIASES

View File

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

View File

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

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