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

3
.gitignore vendored
View File

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

View File

@@ -10,10 +10,11 @@ repos:
# rev: v1.3.5
# hooks:
# - id: clang-format
# - repo: https://github.com/cheshirekow/cmake-format-precommit
# rev: v0.6.13
# hooks:
# - id: cmake-format
# additional_dependencies: ["cmakelang"]
# - id: cmake-lint
# additional_dependencies: ["cmakelang"]
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
additional_dependencies: ["cmakelang[YAML]"]
# - id: cmake-lint
# 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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
project(mp-units-dev
LANGUAGES CXX
)
cmake_minimum_required(VERSION 3.19)
project(mp-units-dev LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -50,8 +48,7 @@ if(${projectPrefix}IWYU)
include(include-what-you-use)
enable_iwyu(
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
NO_FORWARD_DECLARATIONS
QUOTED_INCLUDES_FIRST
NO_FORWARD_DECLARATIONS QUOTED_INCLUDES_FIRST
MAX_LINE_LENGTH 120
NO_COMMENTS
)
@@ -74,3 +71,7 @@ add_subdirectory(docs)
# add unit tests
enable_testing()
add_subdirectory(test)
# tests for standalone headers
include(TestPublicHeaders)
add_public_header_test(test_headers mp-units::mp-units)

View File

@@ -1,11 +1,7 @@
# Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
# Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
find_package_handle_standard_args(Sphinx "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()
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()
if(_enable_ccache_MODE STREQUAL DIRECT_DEPEND)
@@ -188,25 +188,18 @@ function(enable_ccache)
if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles")
foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA)
set(CMAKE_${_lang}_COMPILER_LAUNCHER
${CMAKE_COMMAND} -E env
${_ccacheEnv} ${CCACHE_PATH}
PARENT_SCOPE
)
set(CMAKE_${_lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${_ccacheEnv} ${CCACHE_PATH} PARENT_SCOPE)
endforeach()
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.
# A separate launch script needs to be written out and the project variables pointed at them.
foreach(_lang IN ITEMS C CXX)
set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang})
file(WRITE ${launch${_lang}} "#!/bin/bash\n\n")
foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach()
file(APPEND ${launch${_lang}}
"exec \"${CCACHE_PROGRAM}\" "
"\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n"
)
set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang})
file(WRITE ${launch${_lang}} "#!/bin/bash\n\n")
foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach()
file(APPEND ${launch${_lang}} "exec \"${CCACHE_PROGRAM}\" " "\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n")
execute_process(COMMAND chmod a+rx ${launch${_lang}})
endforeach()
set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE)

View File

@@ -22,7 +22,8 @@
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)
#
@@ -80,16 +81,14 @@ function(add_documentation targetName)
set(_doxygenIndexFile "${DOXYGEN_OUTPUT_DIR}/xml/index.xml")
# 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 Doxygen::doxygen ARGS "${_doxyfile}"
MAIN_DEPENDENCY "${_doxyfileIn}"
DEPENDS
"${_doxyfile}"
"${_args_CODE_DEPENDS}"
DEPENDS "${_doxyfile}" "${_args_CODE_DEPENDS}"
COMMENT "Generating doxygen XML metadata"
USES_TERMINAL
VERBATIM
USES_TERMINAL VERBATIM
)
set(_sphinx_docs_dir "${CMAKE_CURRENT_BINARY_DIR}/sphinx")
@@ -99,16 +98,16 @@ function(add_documentation targetName)
# - Doxygen has rerun
# - Our doc files have been updated
# - The Sphinx config has been updated
add_custom_command(OUTPUT "${_sphinx_index_file}"
COMMAND "${SPHINX_EXECUTABLE}" ARGS -b html -j auto "-Dbreathe_projects.${_args_BREATHE_PROJECT}=${DOXYGEN_OUTPUT_DIR}/xml" "${_args_DOCS_SOURCE_DIR}" "${_sphinx_docs_dir}"
add_custom_command(
OUTPUT "${_sphinx_index_file}"
COMMAND "${SPHINX_EXECUTABLE}" ARGS -b html -j auto
"-Dbreathe_projects.${_args_BREATHE_PROJECT}=${DOXYGEN_OUTPUT_DIR}/xml" "${_args_DOCS_SOURCE_DIR}"
"${_sphinx_docs_dir}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
MAIN_DEPENDENCY "${_args_DOCS_SOURCE_DIR}/conf.py"
DEPENDS
"${_doxygenIndexFile}"
"${_args_DOCS_DEPENDS}"
DEPENDS "${_doxygenIndexFile}" "${_args_DOCS_DEPENDS}"
COMMENT "Generating documentation with Sphinx"
USES_TERMINAL
VERBATIM
USES_TERMINAL VERBATIM
)
# Custom target
@@ -118,7 +117,7 @@ function(add_documentation targetName)
add_custom_target(${targetName} ${_all} DEPENDS "${_sphinx_index_file}")
if(_args_INSTALL_DIR)
# Add an install step to install the docs
install(DIRECTORY ${_sphinx_docs_dir} TYPE DOC)
# Add an install step to install the docs
install(DIRECTORY ${_sphinx_docs_dir} TYPE DOC)
endif()
endfunction()

View File

@@ -48,7 +48,17 @@ macro(_enable_iwyu_failed log_postfix)
endmacro()
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(_multi_value_args KEEP)
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)
_process_iwyu_arguments(1 " for '${target}'")
set_target_properties(${target} PROPERTIES
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
)
set_target_properties(${target} PROPERTIES CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}")
endfunction()

File diff suppressed because it is too large Load Diff

View File

@@ -23,9 +23,11 @@
cmake_minimum_required(VERSION 3.4)
function(ensure_entry_point)
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 "
"as a CMake entry point and should not be included from other CMake files. "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead.")
endif()
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 "
"as a CMake entry point and should not be included from other CMake files. "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead."
)
endif()
endfunction()

View File

@@ -70,9 +70,7 @@ macro(_set_flags)
-Wformat=2 # warn on security issues around functions that format output (ie printf)
)
set(CLANG_WARNINGS
${GCC_COMMON_WARNINGS}
)
set(CLANG_WARNINGS ${GCC_COMMON_WARNINGS})
set(GCC_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
# SOFTWARE.
from conans import ConanFile, tools
from conans.tools import Version, check_min_cppstd
from conan import ConanFile
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
required_conan_version = ">=1.44.0"
required_conan_version = ">=1.48.0"
class MPUnitsConan(ConanFile):
name = "mp-units"
homepage = "https://github.com/mpusz/units"
description = "Physical Units library for C++"
topics = ("units", "dimensions", "quantities", "dimensional-analysis", "physical-quantities", "physical-units", "system-of-units", "cpp23", "cpp20", "library", "quantity-manipulation")
topics = (
"units",
"dimensions",
"quantities",
"dimensional-analysis",
"physical-quantities",
"physical-units",
"system-of-units",
"cpp23",
"cpp20",
"library",
"quantity-manipulation",
)
license = "MIT"
url = "https://github.com/mpusz/units"
settings = "os", "compiler", "build_type", "arch"
@@ -48,12 +62,13 @@ class MPUnitsConan(ConanFile):
"build_docs": True
}
exports = ["LICENSE.md"]
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"]
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*", "CMakeLists.txt"]
no_copy_source = True
generators = "cmake_paths"
@property
def _run_tests(self):
return tools.get_env("CONAN_RUN_TESTS", False)
return get_env("CONAN_RUN_TESTS", False)
@property
def _use_libfmt(self):
@@ -68,18 +83,18 @@ class MPUnitsConan(ConanFile):
def _use_range_v3(self):
compiler = self.settings.compiler
version = Version(self.settings.compiler.version)
return ("clang" in compiler and compiler.libcxx == "libc++" and version < 14)
return "clang" in compiler and compiler.libcxx == "libc++" and version < 14
@property
def _msvc_version(self):
compiler = self.settings.compiler
if (compiler.update):
if compiler.update:
return int(f"{compiler.version}{compiler.update}")
else:
return int(f"{compiler.version}0")
def set_version(self):
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
self.version = version.strip()
@@ -97,7 +112,8 @@ class MPUnitsConan(ConanFile):
if self.options.build_docs:
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
version = Version(self.settings.compiler.version)
if compiler == "gcc":
@@ -146,16 +162,17 @@ class MPUnitsConan(ConanFile):
self.info.header_only()
def package(self):
self.copy("LICENSE.md", dst="licenses")
copy(self, "LICENSE.md", self.source_folder, os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
def package_info(self):
compiler = self.settings.compiler
# core
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
self.cpp_info.components["core"].includedirs = ["include"]
if compiler == "Visual Studio":
self.cpp_info.components["core"].cxxflags = ["/utf-8"]
if self._use_range_v3:
@@ -163,19 +180,60 @@ class MPUnitsConan(ConanFile):
# rest
self.cpp_info.components["core-io"].requires = ["core"]
self.cpp_info.components["core-io"].includedirs = ["include"]
self.cpp_info.components["core-fmt"].requires = ["core"]
self.cpp_info.components["core-fmt"].includedirs = ["include"]
if self._use_libfmt:
self.cpp_info.components["core-fmt"].requires.append("fmt::fmt")
self.cpp_info.components["isq"].requires = ["core"]
self.cpp_info.components["isq"].includedirs = ["include"]
self.cpp_info.components["isq-natural"].requires = ["isq"]
self.cpp_info.components["isq-natural"].includedirs = ["include"]
self.cpp_info.components["si"].requires = ["isq"]
self.cpp_info.components["si"].includedirs = ["include"]
self.cpp_info.components["si-cgs"].requires = ["si"]
self.cpp_info.components["si-cgs"].includedirs = ["include"]
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"].includedirs = ["include"]
self.cpp_info.components["si-iau"].requires = ["si"]
self.cpp_info.components["si-iau"].includedirs = ["include"]
self.cpp_info.components["si-imperial"].requires = ["si"]
self.cpp_info.components["si-imperial"].includedirs = ["include"]
self.cpp_info.components["si-international"].requires = ["si"]
self.cpp_info.components["si-international"].includedirs = ["include"]
self.cpp_info.components["si-typographic"].requires = ["si"]
self.cpp_info.components["si-typographic"].includedirs = ["include"]
self.cpp_info.components["si-uscs"].requires = ["si"]
self.cpp_info.components["si-uscs"].includedirs = ["include"]
self.cpp_info.components["isq-iec80000"].requires = ["si"]
self.cpp_info.components["systems"].requires = ["isq", "isq-natural", "si", "si-cgs", "si-fps", "si-hep", "si-iau", "si-imperial", "si-international", "si-typographic", "si-uscs", "isq-iec80000"]
self.cpp_info.components["isq-iec80000"].includedirs = ["include"]
self.cpp_info.components["systems"].requires = [
"isq",
"isq-natural",
"si",
"si-cgs",
"si-fps",
"si-hep",
"si-iau",
"si-imperial",
"si-international",
"si-typographic",
"si-uscs",
"isq-iec80000",
]

View File

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

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

View File

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

View File

@@ -28,16 +28,23 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target)
add_executable(${target}-aliases ${target}.cpp)
target_link_libraries(${target}-aliases PRIVATE ${ARGN})
target_compile_definitions(${target}-aliases PRIVATE
${projectPrefix}NO_LITERALS
${projectPrefix}NO_REFERENCES
)
target_compile_definitions(${target}-aliases PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_REFERENCES)
endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
add_example(box_example mp-units::core-fmt mp-units::si)
add_example(capacitor_time_curve mp-units::core-io mp-units::si)
add_example(clcpp_response mp-units::core-fmt mp-units::core-io mp-units::si mp-units::si-iau mp-units::si-imperial mp-units::si-international mp-units::si-typographic mp-units::si-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(foot_pound_second mp-units::core-fmt mp-units::si-fps)
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)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-aliases PRIVATE
${projectPrefix}NO_LITERALS
${projectPrefix}NO_REFERENCES
target_compile_definitions(
glide_computer_example-aliases PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_REFERENCES
)
find_package(wg21_linear_algebra CONFIG REQUIRED)

View File

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

View File

@@ -29,7 +29,7 @@
#include <units/isq/si/force.h>
#include <units/isq/si/length.h>
#include <units/isq/si/mass.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h>
#include <units/isq/si/volume.h>
#include <cassert>
@@ -40,7 +40,7 @@ namespace {
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);
class Box {
@@ -48,7 +48,10 @@ class Box {
length::m<> height_;
density::kg_per_m3<> density_ = air_density;
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
{
@@ -86,13 +89,13 @@ int main()
auto box = Box(mm<>(1000.0), mm<>(500.0), height);
box.set_contents_density(kg_per_m3<>(1000.0));
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 fill_time = s<>(200.0); // time since starting fill
const auto measured_mass = kg<>(20.0); // measured mass at fill_time
const Length auto fill_level = box.fill_level(measured_mass);
const Dimensionless auto fill_percent = quantity_cast<percent>(fill_level / height);
const Volume auto spare_capacity = box.spare_capacity(measured_mass);
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
const auto input_flow_rate = measured_mass / fill_time; // unknown dimension
const Speed auto float_rise_rate = fill_level / fill_time;
const Time auto fill_time_left = (height / fill_level - 1) * fill_time;

View File

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

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h>
#include <units/isq/si/mass.h>
#include <units/isq/si/power.h>
@@ -52,7 +53,7 @@ struct Ship {
};
// 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)
{
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);
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_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", "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", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns", fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns))
<< 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));
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", "beam", fmt_line<si::fps::length::yd<>, si::length::m<>>(ship.beam))
<< STD_FMT::format("{:20} : {}\n", "mass", fmt_line<si::fps::mass::lton<>, si::mass::t<>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed",
fmt_line<si::international::speed::kn<>, si::speed::km_per_h<>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "power", fmt_line<si::fps::power::hp<>, si::power::kW<>>(ship.power))
<< STD_FMT::format("{:20} : {}\n", "main guns",
fmt_line<si::fps::length::in<>, si::length::mm<>>(ship.mainGuns))
<< 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()
@@ -82,13 +88,37 @@ int main()
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
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
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
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);
std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h>
#include <array>
#include <exception>
#include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders()
{
using namespace units::aliases::isq::si;
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = {
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-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))}}};
UNITS_DIAGNOSTIC_POP
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-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))}}};
UNITS_DIAGNOSTIC_POP
return gliders;
}
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{
using namespace units::aliases::isq::si;
static const std::array weather_conditions = {
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("Bad", weather{height(m<>(850)), rate_of_climb(m_per_s<>(1.8))})};
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("Bad", weather{height(m<>(850)), rate_of_climb(m_per_s<>(1.8))})};
return weather_conditions;
}
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals;
using namespace units::aliases::isq::si::international;
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{"EPGI", {53.52442_N, 18.84947_E}, altitude(ft<>(115))} // N53°31'27.9" E18°50'58.1"
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"
};
return waypoints;
}
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)
{
std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n";
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";
}
}
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)
{
std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
}
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)
{
std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\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())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
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
// 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/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA {
@@ -72,9 +72,9 @@ void vector_of_quantity_add()
{
std::cout << "\nvector_of_quantity_add:\n";
vector<length::m<>> v = { m<>(1), m<>(2), m<>(3) };
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) };
vector<length::km<>> t = { km<>(3), km<>(2), km<>(1) };
vector<length::m<>> v = {m<>(1), m<>(2), m<>(3)};
vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
vector<length::km<>> t = {km<>(3), km<>(2), km<>(1)};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -89,8 +89,8 @@ void vector_of_quantity_multiply_same()
{
std::cout << "\nvector_of_quantity_multiply_same:\n";
vector<length::m<>> v = { m<>(1), m<>(2), m<>(3) };
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) };
vector<length::m<>> v = {m<>(1), m<>(2), m<>(3)};
vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -103,8 +103,8 @@ void vector_of_quantity_multiply_different()
{
std::cout << "\nvector_of_quantity_multiply_different:\n";
vector<force::N<>> v = { N<>(1), N<>(2), N<>(3) };
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) };
vector<force::N<>> v = {N<>(1), N<>(2), N<>(3)};
vector<length::m<>> u = {m<>(3), m<>(2), m<>(1)};
std::cout << "v = " << v << "\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";
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";
@@ -139,9 +139,9 @@ void matrix_of_quantity_add()
{
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<>> 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::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::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 << "u =\n" << u << "\n";
@@ -158,8 +158,8 @@ void matrix_of_quantity_multiply_same()
{
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) }};
vector<length::m<>> u = { m<>(3), m<>(2), m<>(1) };
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)};
std::cout << "v =\n" << v << "\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";
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) }};
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)}};
std::cout << "v =\n" << v << "\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";
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";
@@ -216,9 +216,9 @@ void quantity_of_vector_add()
{
std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<si::kilometre> t(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -233,8 +233,8 @@ void quantity_of_vector_multiply_same()
{
std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -247,8 +247,8 @@ void quantity_of_vector_multiply_different()
{
std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\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";
length_v<> v(vector<>{ 4, 8, 12 });
length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n";
@@ -286,9 +286,9 @@ void quantity_of_matrix_add()
{
std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -305,8 +305,8 @@ void quantity_of_matrix_multiply_same()
{
std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_v<> u(vector<>{ 3, 2, 1 });
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -319,8 +319,8 @@ void quantity_of_matrix_multiply_different()
{
std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -334,7 +334,7 @@ void quantity_of_matrix_divide_by_scalar()
{
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }});
length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n";

View File

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

View File

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

View File

@@ -21,7 +21,7 @@
// SOFTWARE.
#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/quantity_io.h>
#include <exception>
@@ -44,8 +44,9 @@ void example()
Time auto t1 = s<>(10);
Speed auto v1 = avg_speed(d1, t1);
auto temp1 = 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
auto temp1 =
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);
std::cout << "d1 = " << d1 << '\n';
@@ -56,17 +57,15 @@ void example()
std::cout << "d2 = " << d2 << '\n';
}
} // namespace
} // namespace
int main()
{
try {
example();
}
catch (const std::exception& ex) {
} catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
}
catch (...) {
} catch (...) {
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("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",
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
template<typename Q, typename U>
concept castable_to = Quantity<Q> && Unit<U> &&
requires (Q q) {
quantity_cast<U>(q);
};
concept castable_to = Quantity<Q> && Unit<U> && requires(Q q) { quantity_cast<U>(q); };
void conversions()
{

View File

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

View File

@@ -1,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;
res.reserve(wpts.size() - 1);
auto to_leg = [](const waypoint& w1, const waypoint& w2) { return task::leg(w1, w2); };
std::ranges::transform(wpts.cbegin(), prev(wpts.cend()), next(wpts.cbegin()), wpts.cend(), std::back_inserter(res), to_leg);
std::ranges::transform(wpts.cbegin(), prev(wpts.cend()), next(wpts.cbegin()), wpts.cend(), std::back_inserter(res),
to_leg);
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])));
}
}
} // namespace glide_computer
namespace {
using namespace glide_computer;
void print(std::string_view phase_name, timestamp start_ts, const glide_computer::flight_point& point, const glide_computer::flight_point& new_point)
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(
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) |\n",
phase_name, quantity_cast<si::minute>(new_point.ts - point.ts), quantity_cast<si::minute>(new_point.ts - start_ts),
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt);
"| {:<12} | {:>9%.1Q %q} (Total: {:>9%.1Q %q}) | {:>8%.1Q %q} (Total: {:>8%.1Q %q}) | {:>7%.0Q %q} ({:>6%.0Q %q}) "
"|\n",
phase_name, quantity_cast<si::minute>(new_point.ts - point.ts), quantity_cast<si::minute>(new_point.ts - start_ts),
new_point.dist - point.dist, new_point.dist, new_point.alt - point.alt, new_point.alt);
}
flight_point takeoff(timestamp start_ts, const task& t)
{
return {start_ts, t.get_start().alt};
}
flight_point takeoff(timestamp start_ts, const task& t) { return {start_ts, t.get_start().alt}; }
flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow& at)
{
@@ -92,7 +92,8 @@ flight_point tow(timestamp start_ts, const flight_point& pos, const aircraft_tow
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 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 l3d = length_3d(dist, pos.alt - alt);
const duration d = l3d / g.polar[0].v.common();
const flight_point new_pos{pos.ts + d, terrain_level_alt(t, pos) + s.min_agl_height, t.get_leg_index(new_distance), new_distance};
const flight_point new_pos{pos.ts + d, terrain_level_alt(t, pos) + s.min_agl_height, t.get_leg_index(new_distance),
new_distance};
print("Glide", start_ts, pos, new_pos);
return new_pos;
@@ -135,9 +137,11 @@ flight_point final_glide(timestamp start_ts, const flight_point& pos, const glid
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", "");
// ready to takeoff

View File

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

View File

@@ -32,14 +32,14 @@
#include <units/chrono.h>
#include <units/format.h>
#include <units/math.h> // IWYU pragma: keep
#include <units/math.h> // IWYU pragma: keep
#include <algorithm>
#include <array>
#include <initializer_list>
#include <iterator>
#include <ostream>
#include <ranges>
#include <string> // IWYU pragma: keep
#include <string> // IWYU pragma: keep
#include <vector>
// An example of a really simplified tactical glide computer
@@ -69,7 +69,7 @@ namespace glide_computer {
template<units::QuantityKind QK1, units::QuantityKind QK2>
constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
requires(!units::QuantityKindRelatedTo<QK1, QK2>) && requires { lhs.common() / rhs.common();}
requires(!units::QuantityKindRelatedTo<QK1, QK2>) && requires { lhs.common() / rhs.common(); }
{
return lhs.common() / rhs.common();
}
@@ -136,7 +136,7 @@ struct weather {
struct waypoint {
std::string name;
geographic::position pos;
geographic::position<long double> pos;
altitude alt;
};
@@ -149,7 +149,7 @@ public:
const waypoint* end_;
distance length_ = geographic::spherical_distance(begin().pos, end().pos);
public:
leg(const waypoint& b, const waypoint& e) noexcept: begin_(&b), end_(&e) {}
leg(const waypoint& b, const waypoint& e) noexcept : begin_(&b), end_(&e) {}
constexpr const waypoint& begin() const { return *begin_; };
constexpr const waypoint& end() const { return *end_; }
constexpr const distance get_length() const { return length_; }
@@ -157,8 +157,11 @@ public:
using legs = std::vector<leg>;
template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint>
explicit task(const R& r) : waypoints_(std::ranges::begin(r), std::ranges::end(r)) {}
requires std::same_as<std::ranges::range_value_t<R>,
waypoint> explicit task(const R& r) :
waypoints_(std::ranges::begin(r), std::ranges::end(r))
{
}
task(std::initializer_list<waypoint> wpts) : waypoints_(wpts) {}
@@ -170,10 +173,14 @@ public:
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
{
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:
@@ -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);
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

View File

@@ -22,19 +22,16 @@
#include <units/format.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/speed.h> // IWYU pragma: keep
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/isq/si/time.h>
#include <units/quantity_io.h>
#include <iostream>
using namespace units::isq;
constexpr Speed auto avg_speed(Length auto d, Time auto t)
{
return d / t;
}
constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
int main()
{
@@ -55,11 +52,11 @@ int main()
#endif
constexpr Speed auto v7 = quantity_cast<int>(v6);
std::cout << v1 << '\n'; // 110 km/h
std::cout << v2 << '\n'; // 70 mi/h
std::cout << STD_FMT::format("{}", v3) << '\n'; // 110 km/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("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
std::cout << STD_FMT::format("{:%Q}", v7) << '\n'; // 31
std::cout << v1 << '\n'; // 110 km/h
std::cout << v2 << '\n'; // 70 mi/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("{:%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("{:%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)
add_executable(${target} ${target}.cpp)
target_link_libraries(${target} PRIVATE ${ARGN})
target_compile_definitions(${target} PRIVATE
${projectPrefix}NO_LITERALS
${projectPrefix}NO_ALIASES
)
target_compile_definitions(${target} PRIVATE ${projectPrefix}NO_LITERALS ${projectPrefix}NO_ALIASES)
endfunction()
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)

View File

@@ -34,7 +34,8 @@
namespace kalman {
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>
inline constexpr bool are_derivatives = false;
@@ -44,34 +45,42 @@ inline constexpr bool are_derivatives<Q> = true;
template<typename Q1, typename Q2, typename... 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...>;
// state
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 {
std::tuple<QQPs...> variables_;
constexpr state(QQPs... qqps): variables_(std::move(qqps)...) {}
constexpr state(QQPs... qqps) : variables_(std::move(qqps)...) {}
};
template<typename T>
concept State = units::is_specialization_of<T, state>;
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>
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
template<QuantityOrQuantityPoint QQP, QuantityOrQuantityPoint... QQPs>
struct estimation {
private:
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:
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;
};
@@ -94,7 +103,7 @@ template<typename Q, QuantityOrQuantityPoint QM, units::Dimensionless K>
requires units::equivalent<typename Q::dimension, typename QM::dimension>
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>
@@ -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 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>
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 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);
return { q1, q2, q3 };
return {q1, q2, q3};
}
// 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 q2 = get<1>(estimated);
return { q1, q2 };
return {q1, q2};
}
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 q2 = get<1>(estimated) + get<2>(estimated) * interval;
const auto q3 = get<2>(estimated);
return { q1, q2, q3 };
return {q1, q2, q3};
}
// covariance extrapolation
@@ -164,24 +174,26 @@ struct STD_FMT::formatter<kalman::state<Qs...>> {
std::string value_buffer;
auto to_value_buffer = std::back_inserter(value_buffer);
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));
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));
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));
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));
}
else {
if constexpr(sizeof...(Qs) == 1)
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 {
if constexpr (sizeof...(Qs) == 1)
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));
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;
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);
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)
{
units::Quantity auto q = [](const Q& t) {
if constexpr(units::Quantity<Q>)
if constexpr (units::Quantity<Q>)
return t;
else
return t.relative();
@@ -212,13 +224,12 @@ struct STD_FMT::formatter<kalman::estimation<Q>> {
auto to_value_buffer = std::back_inserter(value_buffer);
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);
}
else {
} else {
STD_FMT::format_to(to_value_buffer, "{0:%Q} ± {1:%Q} {0:%q}", q, sqrt(e.uncertainty));
}
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);
return STD_FMT::vformat_to(ctx.out(), global_format_buffer, STD_FMT::make_format_args(value_buffer));

View File

@@ -21,9 +21,9 @@
// SOFTWARE.
#include "kalman.h"
#include <units/isq/si/mass.h>
#include <units/format.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/mass.h>
#include <array>
#include <iostream>
@@ -34,10 +34,12 @@ using namespace units;
void print_header(const kalman::State auto& 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);
}
@@ -48,13 +50,13 @@ int main()
using namespace units::isq::si::references;
using state = kalman::state<si::mass<si::gram>>;
const state initial = { 1 * kg };
const std::array measurements = { 1030 * g, 989 * g, 1017 * g, 1009 * g, 1013 * g,
979 * g, 1008 * g, 1042 * g, 1012 * g, 1011 * g };
const state initial = {1 * kg};
const std::array measurements = {1030 * g, 989 * g, 1017 * g, 1009 * g, 1013 * g,
979 * g, 1008 * g, 1042 * g, 1012 * g, 1011 * g};
print_header(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 dimensionless<one> gain = 1. / index;
const auto current = state_update(previous, m, gain);

View File

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

View File

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

View File

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

View File

@@ -21,8 +21,8 @@
// SOFTWARE.
#include "kalman.h"
#include <units/isq/si/length.h>
#include <units/format.h>
#include <units/isq/si/length.h>
#include <units/math.h>
#include <array>
#include <iostream>
@@ -35,13 +35,15 @@ template<Quantity Q>
void print_header(kalman::estimation<Q> 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>
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()
@@ -50,20 +52,20 @@ int main()
using namespace units::isq;
using namespace units::isq::si::references;
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,
40.85 * m, 46.72 * m, 50.05 * m, 51.27 * m, 49.95 * 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,
40.85 * m, 46.72 * m, 50.05 * m, 51.27 * m, 49.95 * m};
const auto measurement_uncertainty = pow<2>(5. * m);
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; };
print_header(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 gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, measured, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE.
#include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h>
#include <units/quantity_point.h>
#include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> 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>
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()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references;
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 std::array measurements = {
quantity_point(49.95 * deg_C),
quantity_point(49.967 * deg_C),
quantity_point(50.1 * deg_C),
quantity_point(50.106 * 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 estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = {quantity_point(49.95 * deg_C), quantity_point(49.967 * deg_C),
quantity_point(50.1 * deg_C), quantity_point(50.106 * 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);
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) {
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);
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 gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE.
#include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h>
#include <units/quantity_point.h>
#include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> 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>
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()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references;
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 std::array measurements = {
quantity_point(50.45 * deg_C),
quantity_point(50.967 * deg_C),
quantity_point(51.6 * deg_C),
quantity_point(52.106 * 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 estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = {quantity_point(50.45 * deg_C), quantity_point(50.967 * deg_C),
quantity_point(51.6 * deg_C), quantity_point(52.106 * 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);
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) {
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);
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 gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain);

View File

@@ -21,8 +21,8 @@
// SOFTWARE.
#include "kalman.h"
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/format.h>
#include <units/isq/si/thermodynamic_temperature.h>
#include <units/math.h>
#include <units/quantity_point.h>
#include <units/unit.h>
@@ -56,13 +56,15 @@ template<QuantityPoint QP>
void print_header(kalman::estimation<QP> 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>
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()
@@ -72,32 +74,25 @@ int main()
using namespace units::isq::si::references;
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 std::array measurements = {
quantity_point(50.45 * deg_C),
quantity_point(50.967 * deg_C),
quantity_point(51.6 * deg_C),
quantity_point(52.106 * 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 estimation initial = {state{quantity_point(10. * deg_C)}, pow<2>(100. * deg_C)};
const std::array measurements = {quantity_point(50.45 * deg_C), quantity_point(50.967 * deg_C),
quantity_point(51.6 * deg_C), quantity_point(52.106 * 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);
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) {
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);
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 gain = kalman_gain(previous.uncertainty, measurement_uncertainty);
const estimation current = update(previous, m, gain);

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,6 +26,7 @@
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/power.h>
#include <units/isq/si/fps/speed.h>
#include <units/isq/si/international/speed.h>
#include <units/isq/si/length.h>
#include <units/isq/si/mass.h>
#include <units/isq/si/power.h>
@@ -53,7 +54,7 @@ struct Ship {
};
// 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)
{
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;
const auto waterDensity = 62.4_q_lb_per_ft3;
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_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "mass", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "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));
std::cout << STD_FMT::format("{:20} : {}\n", "length",
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length))
<< STD_FMT::format("{:20} : {}\n", "draft",
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format(
"{:20} : {}\n", "speed",
fmt_line<si::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()
@@ -83,13 +96,37 @@ int main()
using namespace units::isq::si::fps::literals;
// KMS Bismark, using the units the Germans would use, taken from Wiki
auto bismark = Ship{.length{251._q_m}, .draft{9.3_q_m}, .beam{36_q_m}, .speed{56_q_km_per_h}, .mass{50'300_q_t}, .mainGuns{380_q_mm}, .shellMass{800_q_kg}, .shellSpeed{820._q_m_per_s}, .power{110.45_q_kW}};
auto bismark = Ship{.length{251._q_m},
.draft{9.3_q_m},
.beam{36_q_m},
.speed{56_q_km_per_h},
.mass{50'300_q_t},
.mainGuns{380_q_mm},
.shellMass{800_q_kg},
.shellSpeed{820._q_m_per_s},
.power{110.45_q_kW}};
// USS Iowa, using units from the foot-pound-second system
auto iowa = Ship{.length{860._q_ft}, .draft{37._q_ft + 2._q_in}, .beam{108._q_ft + 2._q_in}, .speed{33_q_knot}, .mass{57'540_q_lton}, .mainGuns{16_q_in}, .shellMass{2700_q_lb}, .shellSpeed{2690._q_ft_per_s}, .power{212'000_q_hp}};
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
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);
std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h>
#include <array>
#include <exception>
#include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders()
{
using namespace si::literals;
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}},
glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}},
glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}},
glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}};
UNITS_DIAGNOSTIC_POP
glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}},
glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}},
glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}},
glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}};
UNITS_DIAGNOSTIC_POP
return gliders;
}
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{
using namespace si::literals;
static const std::array weather_conditions = {
std::pair("Good", weather{height(1900_q_m), rate_of_climb(4.3_q_m_per_s)}),
std::pair("Medium", weather{height(1550_q_m), rate_of_climb(2.8_q_m_per_s)}),
std::pair("Bad", weather{height(850_q_m), rate_of_climb(1.8_q_m_per_s)})};
std::pair("Good", weather{height(1900_q_m), rate_of_climb(4.3_q_m_per_s)}),
std::pair("Medium", weather{height(1550_q_m), rate_of_climb(2.8_q_m_per_s)}),
std::pair("Bad", weather{height(850_q_m), rate_of_climb(1.8_q_m_per_s)})};
return weather_conditions;
}
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals;
using namespace units::isq::si::international::literals;
static const std::array waypoints = {
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16_q_ft)}, // N54°14'51.8" E18°40'28.2"
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115_q_ft)} // N53°31'27.9" E18°50'58.1"
waypoint{"EPPR", {54.24772_N, 18.6745_E}, altitude(16_q_ft)}, // N54°14'51.8" E18°40'28.2"
waypoint{"EPGI", {53.52442_N, 18.84947_E}, altitude(115_q_ft)} // N53°31'27.9" E18°50'58.1"
};
return waypoints;
}
template<std::ranges::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)
{
std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n";
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";
}
}
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)
{
std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
}
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)
{
std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\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())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
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
// 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/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA {
@@ -73,9 +73,9 @@ void vector_of_quantity_add()
{
std::cout << "\nvector_of_quantity_add:\n";
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m };
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
vector<si::length<si::kilometre>> t = { 3_q_km, 2_q_km, 1_q_km };
vector<si::length<si::metre>> v = {1_q_m, 2_q_m, 3_q_m};
vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
vector<si::length<si::kilometre>> t = {3_q_km, 2_q_km, 1_q_km};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -90,8 +90,8 @@ void vector_of_quantity_multiply_same()
{
std::cout << "\nvector_of_quantity_multiply_same:\n";
vector<si::length<si::metre>> v = { 1_q_m, 2_q_m, 3_q_m };
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
vector<si::length<si::metre>> v = {1_q_m, 2_q_m, 3_q_m};
vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -104,8 +104,8 @@ void vector_of_quantity_multiply_different()
{
std::cout << "\nvector_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N };
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
vector<si::force<si::newton>> v = {1_q_N, 2_q_N, 3_q_N};
vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -119,7 +119,7 @@ void vector_of_quantity_divide_by_scalar()
{
std::cout << "\nvector_of_quantity_divide_by_scalar:\n";
vector<si::length<si::metre>> v = { 4_q_m, 8_q_m, 12_q_m };
vector<si::length<si::metre>> v = {4_q_m, 8_q_m, 12_q_m};
std::cout << "v = " << v << "\n";
@@ -140,9 +140,9 @@ void matrix_of_quantity_add()
{
std::cout << "\nmatrix_of_quantity_add:\n";
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
matrix<si::length<si::metre>> u = {{ 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }, { 3_q_m, 2_q_m, 1_q_m }};
matrix<si::length<si::millimetre>> t = {{ 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }, { 3_q_mm, 2_q_mm, 1_q_mm }};
matrix<si::length<si::metre>> v = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
matrix<si::length<si::metre>> u = {{3_q_m, 2_q_m, 1_q_m}, {3_q_m, 2_q_m, 1_q_m}, {3_q_m, 2_q_m, 1_q_m}};
matrix<si::length<si::millimetre>> t = {{3_q_mm, 2_q_mm, 1_q_mm}, {3_q_mm, 2_q_mm, 1_q_mm}, {3_q_mm, 2_q_mm, 1_q_mm}};
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -159,8 +159,8 @@ void matrix_of_quantity_multiply_same()
{
std::cout << "\nmatrix_of_quantity_multiply_same:\n";
matrix<si::length<si::metre>> v = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
vector<si::length<si::metre>> u = { 3_q_m, 2_q_m, 1_q_m };
matrix<si::length<si::metre>> v = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
vector<si::length<si::metre>> u = {3_q_m, 2_q_m, 1_q_m};
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -173,8 +173,8 @@ void matrix_of_quantity_multiply_different()
{
std::cout << "\nmatrix_of_quantity_multiply_different:\n";
vector<si::force<si::newton>> v = { 1_q_N, 2_q_N, 3_q_N };
matrix<si::length<si::metre>> u = {{ 1_q_m, 2_q_m, 3_q_m }, { 4_q_m, 5_q_m, 6_q_m }, { 7_q_m, 8_q_m, 9_q_m }};
vector<si::force<si::newton>> v = {1_q_N, 2_q_N, 3_q_N};
matrix<si::length<si::metre>> u = {{1_q_m, 2_q_m, 3_q_m}, {4_q_m, 5_q_m, 6_q_m}, {7_q_m, 8_q_m, 9_q_m}};
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -188,7 +188,7 @@ void matrix_of_quantity_divide_by_scalar()
{
std::cout << "\nmatrix_of_quantity_divide_by_scalar:\n";
matrix<si::length<si::metre>> v = {{ 2_q_m, 4_q_m, 6_q_m }, { 4_q_m, 6_q_m, 8_q_m }, { 8_q_m, 4_q_m, 2_q_m }};
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";
@@ -215,9 +215,9 @@ void quantity_of_vector_add()
{
std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<si::kilometre> t(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -232,8 +232,8 @@ void quantity_of_vector_multiply_same()
{
std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -246,8 +246,8 @@ void quantity_of_vector_multiply_different()
{
std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\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";
length_v<> v(vector<>{ 4, 8, 12 });
length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n";
@@ -285,9 +285,9 @@ void quantity_of_matrix_add()
{
std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -304,8 +304,8 @@ void quantity_of_matrix_multiply_same()
{
std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_v<> u(vector<>{ 3, 2, 1 });
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -318,8 +318,8 @@ void quantity_of_matrix_multiply_different()
{
std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -333,7 +333,7 @@ void quantity_of_matrix_divide_by_scalar()
{
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }});
length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -39,15 +39,15 @@ void simple_quantities()
using distance = si::length<si::metre>;
using duration = si::time<si::second>;
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW
constexpr distance km = 1.0 * references::km;
constexpr distance miles = 1.0 * mi;
constexpr duration sec = 1 * s;
constexpr duration min = 1 * references::min;
constexpr duration hr = 1 * h;
UNITS_DIAGNOSTIC_POP
UNITS_DIAGNOSTIC_POP
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";
@@ -66,8 +66,8 @@ void quantities_with_typed_units()
using namespace units::isq::si::international;
using namespace units::isq::si::international::references;
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_SHADOW
constexpr length<kilometre> km = 1.0 * si::references::km;
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<minute> min = 1 * si::references::min;
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 << km << '\n';

View File

@@ -20,17 +20,17 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <units/bits/external/hacks.h> // IWYU pragma: keep
#include <units/bits/external/hacks.h> // IWYU pragma: keep
UNITS_DIAGNOSTIC_PUSH
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
#include <units/generic/angle.h>
#include <units/isq/si/energy.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 <iostream>

View File

@@ -21,13 +21,14 @@
// SOFTWARE.
#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/mass.h>
#include <units/isq/si/fps/power.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/international/speed.h>
#include <units/isq/si/length.h>
#include <units/isq/si/mass.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
template<class ...Args, units::Quantity Q>
template<class... Args, units::Quantity Q>
auto fmt_line(const Q 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;
const auto waterDensity = 62.4 * (lb / ft3);
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_FMT::format("{:20} : {}\n", "draft", fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "mass", fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format("{:20} : {}\n", "speed", fmt_line<si::fps::speed<si::fps::knot>, si::speed<si::kilometre_per_hour>>(ship.speed))
<< STD_FMT::format("{:20} : {}\n", "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));
std::cout << STD_FMT::format("{:20} : {}\n", "length",
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.length))
<< STD_FMT::format("{:20} : {}\n", "draft",
fmt_line<si::fps::length<si::fps::yard>, si::length<si::metre>>(ship.draft))
<< 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", "mass",
fmt_line<si::fps::mass<si::fps::long_ton>, si::mass<si::tonne>>(ship.mass))
<< STD_FMT::format(
"{:20} : {}\n", "speed",
fmt_line<si::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()
@@ -87,13 +100,37 @@ int main()
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
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
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
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);
std::cout << "\n\n";

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h>
#include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h>
#include <array>
#include <exception>
#include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders()
{
using namespace si::references;
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = {
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-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))}}};
UNITS_DIAGNOSTIC_POP
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-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))}}};
UNITS_DIAGNOSTIC_POP
return gliders;
}
@@ -58,9 +57,9 @@ auto get_weather_conditions()
{
using namespace si::references;
static const std::array weather_conditions = {
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("Bad", weather{height(850 * m), rate_of_climb(1.8 * (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("Bad", weather{height(850 * m), rate_of_climb(1.8 * (m / s))})};
return weather_conditions;
}
@@ -69,14 +68,14 @@ auto get_waypoints()
using namespace geographic::literals;
using namespace units::isq::si::international::references;
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{"EPGI", {53.52442_N, 18.84947_E}, altitude(115 * ft)} // N53°31'27.9" E18°50'58.1"
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"
};
return waypoints;
}
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)
{
std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n";
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";
}
}
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)
{
std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
}
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)
{
std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\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())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
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
// 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/length.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/format.h>
#include <units/isq/si/speed.h> // IWYU pragma: keep
#include <units/quantity_io.h>
#include <linear_algebra.hpp>
#include <iostream>
#include <linear_algebra.hpp>
namespace STD_LA {
@@ -73,9 +73,9 @@ void vector_of_quantity_add()
{
std::cout << "\nvector_of_quantity_add:\n";
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::kilometre>> t = { 3 * km, 2 * km, 1 * km };
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::kilometre>> t = {3 * km, 2 * km, 1 * km};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -90,8 +90,8 @@ void vector_of_quantity_multiply_same()
{
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>> u = { 3 * m, 2 * m, 1 * 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};
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -104,8 +104,8 @@ void vector_of_quantity_multiply_different()
{
std::cout << "\nvector_of_quantity_multiply_different:\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::force<si::newton>> v = {1 * N, 2 * N, 3 * N};
vector<si::length<si::metre>> u = {3 * m, 2 * m, 1 * m};
std::cout << "v = " << v << "\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";
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";
@@ -140,9 +140,9 @@ void matrix_of_quantity_add()
{
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>> 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::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::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 << "u =\n" << u << "\n";
@@ -159,8 +159,8 @@ void matrix_of_quantity_multiply_same()
{
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 }};
vector<si::length<si::metre>> u = { 3 * m, 2 * m, 1 * 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};
std::cout << "v =\n" << v << "\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";
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 }};
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}};
std::cout << "v =\n" << v << "\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";
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";
@@ -215,9 +215,9 @@ void quantity_of_vector_add()
{
std::cout << "\nquantity_of_vector_add:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<si::kilometre> t(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
length_v<si::kilometre> t(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -232,8 +232,8 @@ void quantity_of_vector_multiply_same()
{
std::cout << "\nquantity_of_vector_multiply_same:\n";
length_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
length_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\n";
std::cout << "u = " << u << "\n";
@@ -246,8 +246,8 @@ void quantity_of_vector_multiply_different()
{
std::cout << "\nquantity_of_vector_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_v<> u(vector<>{ 3, 2, 1 });
force_v<> v(vector<>{1, 2, 3});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v = " << v << "\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";
length_v<> v(vector<>{ 4, 8, 12 });
length_v<> v(vector<>{4, 8, 12});
std::cout << "v = " << v << "\n";
@@ -285,9 +285,9 @@ void quantity_of_matrix_add()
{
std::cout << "\nquantity_of_matrix_add:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_m<> u(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<si::kilometre> t(matrix<>{{ 3, 2, 1 }, { 3, 2, 1 }, { 3, 2, 1 }});
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_m<> u(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
length_m<si::kilometre> t(matrix<>{{3, 2, 1}, {3, 2, 1}, {3, 2, 1}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -304,8 +304,8 @@ void quantity_of_matrix_multiply_same()
{
std::cout << "\nquantity_of_matrix_multiply_same:\n";
length_m<> v(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
length_v<> u(vector<>{ 3, 2, 1 });
length_m<> v(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
length_v<> u(vector<>{3, 2, 1});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -318,8 +318,8 @@ void quantity_of_matrix_multiply_different()
{
std::cout << "\nquantity_of_matrix_multiply_different:\n";
force_v<> v(vector<>{ 1, 2, 3 });
length_m<> u(matrix<>{{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }});
force_v<> v(vector<>{1, 2, 3});
length_m<> u(matrix<>{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
std::cout << "v =\n" << v << "\n";
std::cout << "u =\n" << u << "\n";
@@ -333,7 +333,7 @@ void quantity_of_matrix_divide_by_scalar()
{
std::cout << "\nquantity_of_matrix_divide_by_scalar:\n";
length_m<> v(matrix<>{{ 2, 4, 6 }, { 4, 6, 8 }, { 8, 4, 2 }});
length_m<> v(matrix<>{{2, 4, 6}, {4, 6, 8}, {8, 4, 2}});
std::cout << "v =\n" << v << "\n";

View File

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

View File

@@ -21,7 +21,7 @@
// SOFTWARE.
#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/quantity_io.h>
#include <exception>
@@ -44,8 +44,9 @@ void example()
Time auto t1 = 10 * s;
Speed auto v1 = avg_speed(d1, t1);
auto temp1 = 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
auto temp1 =
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);
std::cout << "d1 = " << d1 << '\n';
@@ -56,17 +57,15 @@ void example()
std::cout << "d2 = " << d2 << '\n';
}
} // namespace
} // namespace
int main()
{
try {
example();
}
catch (const std::exception& ex) {
} catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
}
catch (...) {
} catch (...) {
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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
project(mp-units
VERSION 0.8.0
LANGUAGES CXX
)
cmake_minimum_required(VERSION 3.19)
project(mp-units VERSION 0.8.0 LANGUAGES CXX)
set(projectPrefix UNITS_)
@@ -47,12 +44,7 @@ add_subdirectory(systems)
# project-wide wrapper
add_library(mp-units INTERFACE)
target_link_libraries(mp-units INTERFACE
mp-units::core
mp-units::core-io
mp-units::core-fmt
mp-units::systems
)
target_link_libraries(mp-units INTERFACE mp-units::core mp-units::core-io mp-units::core-fmt mp-units::systems)
add_library(mp-units::mp-units ALIAS mp-units)
install(TARGETS mp-units EXPORT mp-unitsTargets)
@@ -63,11 +55,8 @@ include(CMakePackageConfigHelpers)
write_basic_package_version_file(mp-unitsConfigVersion.cmake COMPATIBILITY SameMajorVersion)
# installation
install(EXPORT mp-unitsTargets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units
NAMESPACE mp-units::
)
install(EXPORT mp-unitsTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mp-units NAMESPACE mp-units::)
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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
function(validate_unparsed module prefix)
if(${prefix}_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}' " "for module '${module}'")
endif()
endfunction()
function(validate_argument_exists module prefix arg)
if(NOT ${prefix}_${arg})
message(FATAL_ERROR "'${arg}' not provided for module '${module}'")
endif()
endfunction()
function(validate_arguments_exists module prefix)
foreach(arg ${ARGN})
validate_argument_exists(${module} ${prefix} ${arg})
endforeach()
endfunction()
#
# add_units_module(ModuleName <depependencies>...)
# add_units_module(ModuleName
# DEPENDENCIES <depependency>...
# HEADERS <header_file>...)
#
function(add_units_module name)
add_library(mp-units-${name} INTERFACE)
target_link_libraries(mp-units-${name} INTERFACE ${ARGN})
target_include_directories(mp-units-${name} ${unitsAsSystem} INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
# parse arguments
set(multiValues DEPENDENCIES HEADERS)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "${multiValues}")
# validate and process arguments
validate_unparsed(${name} ARG)
validate_arguments_exists(${name} ARG DEPENDENCIES HEADERS)
# define the target for a module
add_library(mp-units-${name} INTERFACE ${ARG_HEADERS})
target_link_libraries(mp-units-${name} INTERFACE ${ARG_DEPENDENCIES})
target_include_directories(
mp-units-${name} ${unitsAsSystem} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set_target_properties(mp-units-${name} PROPERTIES EXPORT_NAME ${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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON)
message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}")
add_units_module(core-fmt mp-units::core)
add_units_module(core-fmt DEPENDENCIES mp-units::core HEADERS include/units/format.h)
target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$<BOOL:${${projectPrefix}USE_LIBFMT}>)
if(${projectPrefix}USE_LIBFMT)
find_package(fmt CONFIG REQUIRED)
target_link_libraries(mp-units-core-fmt INTERFACE fmt::fmt)
find_package(fmt CONFIG REQUIRED)
target_link_libraries(mp-units-core-fmt INTERFACE fmt::fmt)
endif()

View File

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

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
# core library options
set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode")
@@ -34,14 +34,38 @@ include(CheckLibcxxInUse)
check_libcxx_in_use(${projectPrefix}LIBCXX)
# core library definition
add_library(mp-units-core INTERFACE)
target_compile_features(mp-units-core INTERFACE cxx_std_20)
target_link_libraries(mp-units-core INTERFACE
gsl::gsl-lite
add_library(
mp-units-core
INTERFACE
include/units/base_dimension.h
include/units/chrono.h
include/units/concepts.h
include/units/customization_points.h
include/units/derived_dimension.h
include/units/exponent.h
include/units/generic/angle.h
include/units/generic/dimensionless.h
include/units/kind.h
include/units/magnitude.h
include/units/math.h
include/units/point_origin.h
include/units/prefix.h
include/units/quantity.h
include/units/quantity_cast.h
include/units/quantity_kind.h
include/units/quantity_point.h
include/units/quantity_point_kind.h
include/units/random.h
include/units/ratio.h
include/units/reference.h
include/units/symbol_text.h
include/units/unit.h
)
target_include_directories(mp-units-core ${unitsAsSystem} INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
target_compile_features(mp-units-core INTERFACE cxx_std_20)
target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
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")
@@ -50,8 +74,9 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_link_libraries(mp-units-core INTERFACE range-v3::range-v3)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(mp-units-core INTERFACE
/utf-8 # Specifies both the source character set and the execution character set as UTF-8
target_compile_options(
mp-units-core
INTERFACE /utf-8 # Specifies both the source character set and the execution character set as UTF-8
)
endif()
@@ -59,7 +84,9 @@ if(DEFINED ${projectPrefix}DOWNCAST_MODE)
set(downcast_mode_options OFF ON AUTO)
list(FIND downcast_mode_options "${${projectPrefix}DOWNCAST_MODE}" downcast_mode)
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()
message(STATUS "${projectPrefix}DOWNCAST_MODE: ${${projectPrefix}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 <array>
#include <cassert>
#include <cstddef>
#include <numeric>
#include <optional>

View File

@@ -48,12 +48,16 @@ using angle = quantity<dim_angle<>, U, Rep>;
inline namespace literals {
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
@@ -69,6 +73,6 @@ using namespace angle_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units

View File

@@ -392,7 +392,7 @@ template<typename T, BasePower auto... BPs>
constexpr T get_value(const magnitude<BPs...>&)
{
// 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;
}
@@ -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); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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.

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 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); }

View File

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

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
# systems
add_subdirectory(isq)
@@ -38,19 +38,21 @@ add_subdirectory(si-uscs)
# wrapper for all the systems
add_library(mp-units-systems INTERFACE)
target_link_libraries(mp-units-systems INTERFACE
mp-units::isq
mp-units::isq-iec80000
mp-units::isq-natural
mp-units::si
mp-units::si-cgs
mp-units::si-fps
mp-units::si-hep
mp-units::si-iau
mp-units::si-imperial
mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
target_link_libraries(
mp-units-systems
INTERFACE
mp-units::isq
mp-units::isq-iec80000
mp-units::isq-natural
mp-units::si
mp-units::si-cgs
mp-units::si-fps
mp-units::si-hep
mp-units::si-iau
mp-units::si-imperial
mp-units::si-international
mp-units::si-typographic
mp-units::si-uscs
)
add_library(mp-units::systems ALIAS mp-units-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
# 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
# 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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
add_units_module(isq mp-units::core)
add_units_module(
isq
DEPENDENCIES mp-units::core
HEADERS include/units/isq/dimensions/absorbed_dose.h
include/units/isq/dimensions/acceleration.h
include/units/isq/dimensions/amount_of_substance.h
include/units/isq/dimensions/angular_velocity.h
include/units/isq/dimensions/area.h
include/units/isq/dimensions/capacitance.h
include/units/isq/dimensions/catalytic_activity.h
include/units/isq/dimensions/charge_density.h
include/units/isq/dimensions/concentration.h
include/units/isq/dimensions/conductance.h
include/units/isq/dimensions/current_density.h
include/units/isq/dimensions/density.h
include/units/isq/dimensions/dynamic_viscosity.h
include/units/isq/dimensions/electric_charge.h
include/units/isq/dimensions/electric_current.h
include/units/isq/dimensions/electric_field_strength.h
include/units/isq/dimensions/energy.h
include/units/isq/dimensions/energy_density.h
include/units/isq/dimensions/force.h
include/units/isq/dimensions/frequency.h
include/units/isq/dimensions/heat_capacity.h
include/units/isq/dimensions/inductance.h
include/units/isq/dimensions/length.h
include/units/isq/dimensions/luminance.h
include/units/isq/dimensions/luminous_intensity.h
include/units/isq/dimensions/magnetic_flux.h
include/units/isq/dimensions/magnetic_induction.h
include/units/isq/dimensions/mass.h
include/units/isq/dimensions/molar_energy.h
include/units/isq/dimensions/momentum.h
include/units/isq/dimensions/permeability.h
include/units/isq/dimensions/permittivity.h
include/units/isq/dimensions/power.h
include/units/isq/dimensions/pressure.h
include/units/isq/dimensions/radioactivity.h
include/units/isq/dimensions/resistance.h
include/units/isq/dimensions/speed.h
include/units/isq/dimensions/surface_tension.h
include/units/isq/dimensions/thermal_conductivity.h
include/units/isq/dimensions/thermodynamic_temperature.h
include/units/isq/dimensions/time.h
include/units/isq/dimensions/torque.h
include/units/isq/dimensions/voltage.h
include/units/isq/dimensions/volume.h
include/units/isq/dimensions.h
)

View File

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

View File

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

View File

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

View File

@@ -44,12 +44,16 @@ using acceleration = quantity<dim_acceleration, U, Rep>;
inline namespace literals {
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
} // 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 {
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
#endif // UNITS_NO_ALIASES
#endif // UNITS_NO_ALIASES

View File

@@ -46,12 +46,16 @@ using area = quantity<dim_area, U, Rep>;
inline namespace literals {
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
@@ -67,7 +71,7 @@ using namespace area_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps
@@ -75,8 +79,9 @@ using namespace area_references;
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>
// IWYU pragma: end_exports
#include <units/isq/si/fps/mass.h>
#include <units/isq/si/fps/length.h>
#include <units/isq/si/fps/mass.h>
#include <units/unit.h>
namespace units::isq::si::fps {
@@ -46,12 +46,16 @@ using density = quantity<dim_density, U, Rep>;
inline namespace literals {
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
} // 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 {
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
#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> {};
// 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>
using energy = quantity<dim_energy, U, Rep>;
@@ -50,16 +50,24 @@ using energy = quantity<dim_energy, U, Rep>;
inline namespace literals {
// 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); }
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
} // 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 {
template<Representation Rep = double> 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>;
template<Representation Rep = double>
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
#endif // UNITS_NO_ALIASES
#endif // UNITS_NO_ALIASES

View File

@@ -57,20 +57,32 @@ using force = quantity<dim_force, U, Rep>;
inline namespace literals {
// 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); }
// 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); }
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
@@ -88,7 +100,7 @@ using namespace force_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps
@@ -96,10 +108,13 @@ using namespace force_references;
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> 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>;
template<Representation Rep = double>
using pdl = units::isq::si::fps::force<units::isq::si::fps::poundal, 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
#endif // UNITS_NO_ALIASES
#endif // UNITS_NO_ALIASES

View File

@@ -23,17 +23,16 @@
#pragma once
// 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/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/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>
// IWYU pragma: end_exports

View File

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

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>
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> {};
@@ -54,20 +57,32 @@ struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq,
inline namespace literals {
// 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); }
// 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); }
// 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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
@@ -84,7 +99,7 @@ using namespace pressure_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps
@@ -92,10 +107,13 @@ using namespace pressure_references;
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> 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>;
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>
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
#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>
using speed = quantity<dim_speed, U, Rep>;
struct mile_per_hour : derived_unit<mile_per_hour, dim_speed, mile, hour>{};
struct nautical_mile_per_hour : derived_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour>{};
struct knot : alias_unit<nautical_mile_per_hour, "knot", no_prefix> {};
struct mile_per_hour : derived_unit<mile_per_hour, dim_speed, mile, hour> {};
struct nautical_mile_per_hour : derived_unit<nautical_mile_per_hour, dim_speed, nautical_mile, hour> {};
struct knot : alias_unit<nautical_mile_per_hour, "kn", no_prefix> {};
#ifndef UNITS_NO_LITERALS
inline namespace literals {
// 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); }
// 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); }
// 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_knot(long double l) { return speed<knot, long double>(l); }
constexpr auto operator"" _q_kn(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return speed<knot, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_kn(long double l) { return speed<knot, long double>(l); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
namespace speed_references {
inline constexpr auto mph = reference<dim_speed, mile_per_hour>{};
inline constexpr auto knot = reference<dim_speed, fps::knot>{};
inline constexpr auto kn = reference<dim_speed, fps::knot>{};
} // namespace speed_references
@@ -80,7 +92,7 @@ using namespace speed_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::fps
@@ -88,10 +100,13 @@ using namespace speed_references;
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> using mph = units::isq::si::fps::speed<units::isq::si::fps::mile_per_hour, Rep>;
template<Representation Rep = double> using knot = units::isq::si::fps::speed<units::isq::si::fps::knot, Rep>;
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>
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
#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
# SOFTWARE.
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.19)
add_units_module(si-hep mp-units::si)
add_units_module(
si-hep DEPENDENCIES mp-units::si
HEADERS include/units/isq/si/hep/area.h include/units/isq/si/hep/energy.h include/units/isq/si/hep/hep.h
include/units/isq/si/hep/mass.h include/units/isq/si/hep/momentum.h
)

View File

@@ -29,7 +29,7 @@
#include <units/symbol_text.h>
// IWYU pragma: end_exports
#include <units/isq/si/length.h>
#include <units/isq/si/area.h>
#include <units/unit.h>
namespace units::isq::si::hep {
@@ -50,27 +50,63 @@ struct milli_barn : prefixed_unit<milli_barn, milli, barn> {};
#ifndef UNITS_NO_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_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_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_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_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_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_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_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_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); }
} // namespace literals
#endif // UNITS_NO_LITERALS
#endif // UNITS_NO_LITERALS
#ifndef UNITS_NO_REFERENCES
@@ -86,7 +122,7 @@ using namespace area_references;
} // namespace references
#endif // UNITS_NO_REFERENCES
#endif // UNITS_NO_REFERENCES
} // namespace units::isq::si::hep
@@ -94,8 +130,9 @@ using namespace area_references;
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
#endif // UNITS_NO_ALIASES
#endif // UNITS_NO_ALIASES

View File

@@ -24,7 +24,6 @@
// IWYU pragma: begin_exports
#include <units/isq/dimensions/momentum.h>
#include <units/isq/si/momentum.h>
#include <units/quantity.h>
#include <units/symbol_text.h>
// IWYU pragma: end_exports
@@ -35,9 +34,11 @@
namespace units::isq::si::hep {
struct kilogram_metre_per_second : unit<kilogram_metre_per_second> {};
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),
::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 peV_per_c : prefixed_unit<peV_per_c, pico, eV_per_c> {};
struct neV_per_c : prefixed_unit<neV_per_c, nano, eV_per_c> {};

View File

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

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