Merge branch 'master' into downcast_mode_off

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

47
.cmake-format.yaml Normal file
View File

@@ -0,0 +1,47 @@
parse:
additional_commands:
add_documentation:
pargs:
nargs: 1
flags:
- ALL
kwargs:
BREATHE_PROJECT: 1
CODE_SOURCE_DIR: 1
INSTALL_DIR: 1
CODE_DEPENDS: 1
DOCS_DEPENDS: 1
add_units_module:
pargs:
nargs: 1
kwargs:
DEPENDENCIES: +
HEADERS: +
enable_iwyu:
pargs:
flags:
- NO_FORWARD_DECLARATIONS
- QUOTED_INCLUDES_FIRST
- NO_COMMENTS
kwargs:
MAPPING_FILE: 1
MAX_LINE_LENGTH: 1
metabench_add_chart:
pargs:
nargs: 1
kwargs:
TITLE: 1
SUBTITLE: 1
DATASETS: +
format:
line_width: 120
tab_size: 4
max_subgroups_hwrap: 3
max_pargs_hwrap: 6
max_rows_cmdline: 2
dangle_parens: true
min_prefix_chars: 8
max_prefix_chars: 8
max_lines_hwrap: 2
markup:
enable_markup: false

View File

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

3
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

129
cmake/TestHeaders.cmake Normal file
View File

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

View File

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

View File

@@ -188,11 +188,7 @@ function(enable_ccache)
if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles") if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles")
foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA) foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA)
set(CMAKE_${_lang}_COMPILER_LAUNCHER set(CMAKE_${_lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${_ccacheEnv} ${CCACHE_PATH} PARENT_SCOPE)
${CMAKE_COMMAND} -E env
${_ccacheEnv} ${CCACHE_PATH}
PARENT_SCOPE
)
endforeach() endforeach()
elseif(CMAKE_GENERATOR STREQUAL Xcode) elseif(CMAKE_GENERATOR STREQUAL Xcode)
# Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options. # Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options.
@@ -203,10 +199,7 @@ function(enable_ccache)
foreach(keyVal IN LISTS _ccacheEnv) foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n") file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach() endforeach()
file(APPEND ${launch${_lang}} file(APPEND ${launch${_lang}} "exec \"${CCACHE_PROGRAM}\" " "\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n")
"exec \"${CCACHE_PROGRAM}\" "
"\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n"
)
execute_process(COMMAND chmod a+rx ${launch${_lang}}) execute_process(COMMAND chmod a+rx ${launch${_lang}})
endforeach() endforeach()
set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE) set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE)

View File

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

View File

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

View File

@@ -20,7 +20,6 @@ endif()
# avoid polluting the build tree. # avoid polluting the build tree.
set(METABENCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/_metabench") set(METABENCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/_metabench")
# metabench_add_dataset(target path_to_template range # metabench_add_dataset(target path_to_template range
# [NAME name] # [NAME name]
# [ENV env] # [ENV env]
@@ -124,41 +123,40 @@ function(metabench_add_dataset target path_to_template range)
set(multi_value_args) set(multi_value_args)
cmake_parse_arguments(ARGS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) cmake_parse_arguments(ARGS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
if (NOT IS_ABSOLUTE "${path_to_template}") if(NOT IS_ABSOLUTE "${path_to_template}")
set(path_to_template "${CMAKE_CURRENT_SOURCE_DIR}/${path_to_template}") set(path_to_template "${CMAKE_CURRENT_SOURCE_DIR}/${path_to_template}")
endif() endif()
if (NOT EXISTS ${path_to_template}) if(NOT EXISTS ${path_to_template})
message(FATAL_ERROR "The file specified to metabench_add_dataset (${path_to_template}) does not exist.") message(FATAL_ERROR "The file specified to metabench_add_dataset (${path_to_template}) does not exist.")
endif() endif()
if (NOT ARGS_NAME) if(NOT ARGS_NAME)
set(ARGS_NAME ${target}) set(ARGS_NAME ${target})
endif() endif()
if (NOT ARGS_ENV) if(NOT ARGS_ENV)
set(ARGS_ENV "{}") set(ARGS_ENV "{}")
endif() endif()
if (NOT ARGS_COLOR) if(NOT ARGS_COLOR)
set(ARGS_COLOR "") set(ARGS_COLOR "")
endif() endif()
if (NOT ARGS_SCALE) if(NOT ARGS_SCALE)
set(ARGS_SCALE 1.0) set(ARGS_SCALE 1.0)
endif() endif()
if (NOT ARGS_MEDIAN_OF) if(NOT ARGS_MEDIAN_OF)
set(ARGS_MEDIAN_OF 1) set(ARGS_MEDIAN_OF 1)
endif() endif()
if (NOT ARGS_OUTPUT) if(NOT ARGS_OUTPUT)
set(ARGS_OUTPUT "${target}.json") set(ARGS_OUTPUT "${target}.json")
endif() endif()
if(NOT IS_ABSOLUTE "${ARGS_OUTPUT}") if(NOT IS_ABSOLUTE "${ARGS_OUTPUT}")
set(ARGS_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_OUTPUT}") set(ARGS_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_OUTPUT}")
endif() endif()
# Add a dummy executable that will be used to collect the dataset. # Add a dummy executable that will be used to collect the dataset.
# We'll build this executable multiple times for different values # We'll build this executable multiple times for different values
# of `n`, and collect compilation statistics each time. Compiling # of `n`, and collect compilation statistics each time. Compiling
@@ -169,7 +167,9 @@ function(metabench_add_dataset target path_to_template range)
# so we store it in a custom property. # so we store it in a custom property.
file(WRITE "${METABENCH_DIR}/${target}.cpp" "") file(WRITE "${METABENCH_DIR}/${target}.cpp" "")
add_executable(${target} EXCLUDE_FROM_ALL "${METABENCH_DIR}/${target}.cpp") add_executable(${target} EXCLUDE_FROM_ALL "${METABENCH_DIR}/${target}.cpp")
set_target_properties(${target} PROPERTIES set_target_properties(
${target}
PROPERTIES
RULE_LAUNCH_COMPILE "${RUBY_EXECUTABLE} -- \"${COMPILE_RB_PATH}\"" RULE_LAUNCH_COMPILE "${RUBY_EXECUTABLE} -- \"${COMPILE_RB_PATH}\""
RULE_LAUNCH_LINK "${RUBY_EXECUTABLE} -- \"${LINK_RB_PATH}\"" RULE_LAUNCH_LINK "${RUBY_EXECUTABLE} -- \"${LINK_RB_PATH}\""
RUNTIME_OUTPUT_DIRECTORY "${METABENCH_DIR}" RUNTIME_OUTPUT_DIRECTORY "${METABENCH_DIR}"
@@ -184,31 +184,25 @@ function(metabench_add_dataset target path_to_template range)
# Add a command to generate the JSON file that will contain the measurements # Add a command to generate the JSON file that will contain the measurements
# we collect for this dataset when we build the executable above. # we collect for this dataset when we build the executable above.
add_custom_command(OUTPUT "${ARGS_OUTPUT}" add_custom_command(
COMMAND "${RUBY_EXECUTABLE}" -r json -r fileutils -r "${METABENCH_RB_PATH}" OUTPUT "${ARGS_OUTPUT}"
-e "range = (${range}).to_a" COMMAND "${RUBY_EXECUTABLE}" -r json -r fileutils -r "${METABENCH_RB_PATH}" -e "range = (${range}).to_a" -e
-e "env = (${ARGS_ENV})" "env = (${ARGS_ENV})" -e "data = {}" -e "data['key'] = '${ARGS_NAME}'" -e
-e "data = {}" "data['scale'] = (${ARGS_SCALE})" -e "data['color'] = '${ARGS_COLOR}'" -e
-e "data['key'] = '${ARGS_NAME}'" "data['values'] = measure('${target}', '${path_to_template}', range, env, ${ARGS_MEDIAN_OF})" -e
-e "data['scale'] = (${ARGS_SCALE})" "FileUtils.mkdir_p(File.dirname('${ARGS_OUTPUT}'))" -e "IO.write('${ARGS_OUTPUT}', JSON.generate(data))"
-e "data['color'] = '${ARGS_COLOR}'"
-e "data['values'] = measure('${target}', '${path_to_template}', range, env, ${ARGS_MEDIAN_OF})"
-e "FileUtils.mkdir_p(File.dirname('${ARGS_OUTPUT}'))"
-e "IO.write('${ARGS_OUTPUT}', JSON.generate(data))"
DEPENDS "${path_to_template}" DEPENDS "${path_to_template}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
VERBATIM USES_TERMINAL VERBATIM USES_TERMINAL
) )
# We also setup a CTest target to test the generation of the dataset. # We also setup a CTest target to test the generation of the dataset.
# We do not actually collect any data here. # We do not actually collect any data here.
add_test(NAME ${target} add_test(
COMMAND "${RUBY_EXECUTABLE}" -r "${METABENCH_RB_PATH}" NAME ${target}
-e "range = (${range}).to_a" COMMAND "${RUBY_EXECUTABLE}" -r "${METABENCH_RB_PATH}" -e "range = (${range}).to_a" -e
-e "range = [range[0], range[-1]] if range.length >= 2" "range = [range[0], range[-1]] if range.length >= 2" -e "env = (${ARGS_ENV})" -e
-e "env = (${ARGS_ENV})" "data = measure('${target}', '${path_to_template}', range, env, 1)"
-e "data = measure('${target}', '${path_to_template}', range, env, 1)"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
) )
endfunction() endfunction()
@@ -276,7 +270,7 @@ function(metabench_add_chart target)
set(multi_value_args DATASETS) set(multi_value_args DATASETS)
cmake_parse_arguments(ARGS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) cmake_parse_arguments(ARGS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
if (NOT ARGS_ASPECT) if(NOT ARGS_ASPECT)
set(ARGS_ASPECT "COMPILATION_TIME") set(ARGS_ASPECT "COMPILATION_TIME")
endif() endif()
@@ -284,7 +278,7 @@ function(metabench_add_chart target)
message(FATAL_ERROR "metabench_add_chart requires at least one dataset.") message(FATAL_ERROR "metabench_add_chart requires at least one dataset.")
endif() endif()
if (NOT ARGS_OUTPUT) if(NOT ARGS_OUTPUT)
set(ARGS_OUTPUT "${target}.html") set(ARGS_OUTPUT "${target}.html")
endif() endif()
@@ -300,22 +294,17 @@ function(metabench_add_chart target)
add_custom_command( add_custom_command(
OUTPUT "${ARGS_OUTPUT}" OUTPUT "${ARGS_OUTPUT}"
COMMAND "${RUBY_EXECUTABLE}" -r erb -r json -r fileutils COMMAND "${RUBY_EXECUTABLE}" -r erb -r json -r fileutils -e "options = {}" -e
-e "options = {}" "options['TITLE'] = '${ARGS_TITLE}'" -e "options['SUBTITLE'] = '${ARGS_SUBTITLE}'" -e
-e "options['TITLE'] = '${ARGS_TITLE}'" "options['XLABEL'] = '${ARGS_XLABEL}'" -e "options['YLABEL'] = '${ARGS_YLABEL}'" -e
-e "options['SUBTITLE'] = '${ARGS_SUBTITLE}'" "aspect = '${ARGS_ASPECT}'" -e "data = '${data}'.split(';').map { |datum| JSON.parse(IO.read(datum)) }"
-e "options['XLABEL'] = '${ARGS_XLABEL}'" -e "html = ERB.new(File.read('${CHART_HTML_ERB_PATH}')).result(binding)" -e
-e "options['YLABEL'] = '${ARGS_YLABEL}'" "FileUtils.mkdir_p(File.dirname('${ARGS_OUTPUT}'))" -e "IO.write('${ARGS_OUTPUT}', html)"
-e "aspect = '${ARGS_ASPECT}'"
-e "data = '${data}'.split(';').map { |datum| JSON.parse(IO.read(datum)) }"
-e "html = ERB.new(File.read('${CHART_HTML_ERB_PATH}')).result(binding)"
-e "FileUtils.mkdir_p(File.dirname('${ARGS_OUTPUT}'))"
-e "IO.write('${ARGS_OUTPUT}', html)"
DEPENDS ${data} "${ARGS_CHART}" DEPENDS ${data} "${ARGS_CHART}"
VERBATIM VERBATIM
) )
if (${ARGS_ALL}) if(${ARGS_ALL})
add_custom_target(${target} ALL DEPENDS "${ARGS_OUTPUT}") add_custom_target(${target} ALL DEPENDS "${ARGS_OUTPUT}")
else() else()
add_custom_target(${target} DEPENDS "${ARGS_OUTPUT}") add_custom_target(${target} DEPENDS "${ARGS_OUTPUT}")
@@ -338,109 +327,109 @@ endfunction()
################################################################################ ################################################################################
set(METABENCH_RB_PATH "${METABENCH_DIR}/metabench.rb") set(METABENCH_RB_PATH "${METABENCH_DIR}/metabench.rb")
file(WRITE "${METABENCH_RB_PATH}" file(WRITE "${METABENCH_RB_PATH}"
"require 'benchmark' \n" "require 'benchmark' \n"
"require 'erb' \n" "require 'erb' \n"
"require 'fileutils' \n" "require 'fileutils' \n"
"require 'open3' \n" "require 'open3' \n"
"require 'pathname' \n" "require 'pathname' \n"
"require 'time' \n" "require 'time' \n"
" \n" " \n"
" \n" " \n"
"def report_error(command_line, stdout, stderr, code) \n" "def report_error(command_line, stdout, stderr, code) \n"
" raise [%{\\ncommand line: #{command_line}}, \n" " raise [%{\\ncommand line: #{command_line}}, \n"
" %{stdout\\n#{'-'*80}\\n#{stdout}}, \n" " %{stdout\\n#{'-'*80}\\n#{stdout}}, \n"
" %{stderr\\n#{'-'*80}\\n#{stderr}}, \n" " %{stderr\\n#{'-'*80}\\n#{stderr}}, \n"
" %{code\\n#{'-'*80}\\n#{code}}].join(%{\\n\\n}) \n" " %{code\\n#{'-'*80}\\n#{code}}].join(%{\\n\\n}) \n"
"end \n" "end \n"
" \n" " \n"
"# Build the specified CMake target and return the measurements that were taken. \n" "# Build the specified CMake target and return the measurements that were taken. \n"
"# The exact format of a measurement returned by this function is explained \n" "# The exact format of a measurement returned by this function is explained \n"
"# in the JavaScript code that loads it, in the chart template file below. \n" "# in the JavaScript code that loads it, in the chart template file below. \n"
"def build(target) \n" "def build(target) \n"
" command = ['${CMAKE_COMMAND}', '--build', '${CMAKE_BINARY_DIR}', '--target', target] \n" " command = ['${CMAKE_COMMAND}', '--build', '${CMAKE_BINARY_DIR}', '--target', target] \n"
" exe_file = %{${METABENCH_DIR}/#{target}${CMAKE_EXECUTABLE_SUFFIX}} \n" " exe_file = %{${METABENCH_DIR}/#{target}${CMAKE_EXECUTABLE_SUFFIX}} \n"
" cpp_file = %{${METABENCH_DIR}/#{target}.cpp} \n" " cpp_file = %{${METABENCH_DIR}/#{target}.cpp} \n"
" \n" " \n"
" # We change the timestamp of the source file and remove the executable \n" " # We change the timestamp of the source file and remove the executable \n"
" # to make sure CMake considers the target as outdated; otherwise, we \n" " # to make sure CMake considers the target as outdated; otherwise, we \n"
" # might skip the compilation and/or link steps. This is because CMake's \n" " # might skip the compilation and/or link steps. This is because CMake's \n"
" # timestamps are not precise enough. \n" " # timestamps are not precise enough. \n"
" FileUtils.touch(cpp_file, mtime: Time.now+1) \n" " FileUtils.touch(cpp_file, mtime: Time.now+1) \n"
" File.delete(exe_file) if File.exist?(exe_file) \n" " File.delete(exe_file) if File.exist?(exe_file) \n"
" \n" " \n"
" stdout, stderr, status = Open3.capture3(*command) \n" " stdout, stderr, status = Open3.capture3(*command) \n"
" compile_cli = stdout.match(/\\[compilation command: (.+)\\]/i) \n" " compile_cli = stdout.match(/\\[compilation command: (.+)\\]/i) \n"
" compile_cli = compile_cli ? compile_cli.captures[0] : '(unavailable)' \n" " compile_cli = compile_cli ? compile_cli.captures[0] : '(unavailable)' \n"
" link_cli = stdout.match(/\\[link command: (.+)\\]/i) \n" " link_cli = stdout.match(/\\[link command: (.+)\\]/i) \n"
" link_cli = link_cli ? link_cli.captures[0] : '(unavailable)' \n" " link_cli = link_cli ? link_cli.captures[0] : '(unavailable)' \n"
" \n" " \n"
" if not status.success? \n" " if not status.success? \n"
" cli = %{compile: #{compile_cli}\\nlink: #{link_cli}} \n" " cli = %{compile: #{compile_cli}\\nlink: #{link_cli}} \n"
" report_error(cli, stdout, stderr, IO.read(cpp_file)) \n" " report_error(cli, stdout, stderr, IO.read(cpp_file)) \n"
" end \n" " end \n"
" \n" " \n"
" result = {} \n" " result = {} \n"
" \n" " \n"
" # Compilation and link times in seconds. They are output to stdout because \n" " # Compilation and link times in seconds. They are output to stdout because \n"
" # we use the `compile.rb` and `link.rb` scripts below to launch the compiler \n" " # we use the `compile.rb` and `link.rb` scripts below to launch the compiler \n"
" # and linker with CMake. \n" " # and linker with CMake. \n"
" result['COMPILATION_TIME'] = stdout.match(/\\[COMPILATION_TIME: (.+)\\]/i).captures[0].to_f \n" " result['COMPILATION_TIME'] = stdout.match(/\\[COMPILATION_TIME: (.+)\\]/i).captures[0].to_f \n"
" result['LINK_TIME'] = stdout.match(/\\[LINK_TIME: (.+)\\]/i).captures[0].to_f \n" " result['LINK_TIME'] = stdout.match(/\\[LINK_TIME: (.+)\\]/i).captures[0].to_f \n"
" \n" " \n"
" # Peak memory usage \n" " # Peak memory usage \n"
" result['PEAK_MEMORY'] = stdout.match(/\\[PEAK_MEMORY: (.+)\\]/i).captures[0].to_f \n" " result['PEAK_MEMORY'] = stdout.match(/\\[PEAK_MEMORY: (.+)\\]/i).captures[0].to_f \n"
" \n" " \n"
" # Size of the generated executable in KB \n" " # Size of the generated executable in KB \n"
" result['EXECUTABLE_SIZE'] = File.size(exe_file).to_f / 1000 \n" " result['EXECUTABLE_SIZE'] = File.size(exe_file).to_f / 1000 \n"
" \n" " \n"
" return result \n" " return result \n"
"end \n" "end \n"
" \n" " \n"
"# Render the ERB template and return the generated code. \n" "# Render the ERB template and return the generated code. \n"
"def render(erb_template, n, env) \n" "def render(erb_template, n, env) \n"
" begin \n" " begin \n"
" ERB.new(File.read(erb_template)).result(binding) \n" " ERB.new(File.read(erb_template)).result(binding) \n"
" rescue Exception => e \n" " rescue Exception => e \n"
" $stderr.puts(%{\\nError while generating a C++ file from the ERB template #{erb_template}:\\n}) \n" " $stderr.puts(%{\\nError while generating a C++ file from the ERB template #{erb_template}:\\n}) \n"
" raise e \n" " raise e \n"
" end \n" " end \n"
"end \n" "end \n"
" \n" " \n"
"# Formats the progress bar that we print while we run the benchmark \n" "# Formats the progress bar that we print while we run the benchmark \n"
"def progress_bar(range, index, start_time, filename) \n" "def progress_bar(range, index, start_time, filename) \n"
" n = range[index] \n" " n = range[index] \n"
" percentage = (index+1) * 100 / range.size \n" " percentage = (index+1) * 100 / range.size \n"
" relative = filename.relative_path_from(Pathname.getwd) \n" " relative = filename.relative_path_from(Pathname.getwd) \n"
" elapsed = Time.now - start_time \n" " elapsed = Time.now - start_time \n"
" return %{==> #{percentage}% (#{elapsed.round(2)}s) #{relative} (n = #{n})} \n" " return %{==> #{percentage}% (#{elapsed.round(2)}s) #{relative} (n = #{n})} \n"
"end \n" "end \n"
" \n" " \n"
"# Returns an array of measurements representing the compilation of an ERB \n" "# Returns an array of measurements representing the compilation of an ERB \n"
"# template for the values of `n` in the specified `range`. \n" "# template for the values of `n` in the specified `range`. \n"
"def measure(target, erb_template, range, env, repetitions) \n" "def measure(target, erb_template, range, env, repetitions) \n"
" erb_template = Pathname.new(erb_template) \n" " erb_template = Pathname.new(erb_template) \n"
" cpp_file = %{${METABENCH_DIR}/#{target}.cpp} \n" " cpp_file = %{${METABENCH_DIR}/#{target}.cpp} \n"
" data = [] \n" " data = [] \n"
" range = range.to_a \n" " range = range.to_a \n"
" start = Time.now \n" " start = Time.now \n"
" $stderr.write(progress_bar(range, 0, start, erb_template)) # Setup the initial progress bar \n" " $stderr.write(progress_bar(range, 0, start, erb_template)) # Setup the initial progress bar \n"
" range.each_with_index do |n, index| \n" " range.each_with_index do |n, index| \n"
" compile = -> (code) { \n" " compile = -> (code) { \n"
" IO.write(cpp_file, code) \n" " IO.write(cpp_file, code) \n"
" return repetitions.times.map { build(target) } \n" " return repetitions.times.map { build(target) } \n"
" } \n" " } \n"
" code = render(erb_template, n, env) \n" " code = render(erb_template, n, env) \n"
" compile[code] if index == 0 # Fill the cache on the first iteration \n" " compile[code] if index == 0 # Fill the cache on the first iteration \n"
" base = compile[code] \n" " base = compile[code] \n"
" total = compile[%{#define METABENCH\\n} + code] \n" " total = compile[%{#define METABENCH\\n} + code] \n"
" data << {'n' => n, 'base' => base, 'total' => total} \n" " data << {'n' => n, 'base' => base, 'total' => total} \n"
" $stderr.write(%{\\r} + progress_bar(range, index, start, erb_template)) # Update the progress bar \n" " $stderr.write(%{\\r} + progress_bar(range, index, start, erb_template)) # Update the progress bar \n"
" end \n" " end \n"
" return data \n" " return data \n"
"ensure \n" "ensure \n"
" $stderr.puts # Otherwise the output of the next CMake command appears on the same line \n" " $stderr.puts # Otherwise the output of the next CMake command appears on the same line \n"
" IO.write(cpp_file, '') \n" " IO.write(cpp_file, '') \n"
"end \n" "end \n"
) )
################################################################################ ################################################################################
# end metabench.rb # end metabench.rb
@@ -454,47 +443,47 @@ file(WRITE "${METABENCH_RB_PATH}"
################################################################################ ################################################################################
set(MEMUSG_RB_PATH "${METABENCH_DIR}/memusg.rb") set(MEMUSG_RB_PATH "${METABENCH_DIR}/memusg.rb")
file(WRITE "${MEMUSG_RB_PATH}" file(WRITE "${MEMUSG_RB_PATH}"
"module OS \n" "module OS \n"
" def OS.windows? \n" " def OS.windows? \n"
" (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil \n" " (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil \n"
" end \n" " end \n"
" def OS.mac? \n" " def OS.mac? \n"
" (/darwin/ =~ RUBY_PLATFORM) != nil \n" " (/darwin/ =~ RUBY_PLATFORM) != nil \n"
" end \n" " end \n"
" def OS.unix? \n" " def OS.unix? \n"
" !OS.windows? \n" " !OS.windows? \n"
" end \n" " end \n"
" def OS.linux? \n" " def OS.linux? \n"
" OS.unix? and not OS.mac? \n" " OS.unix? and not OS.mac? \n"
" end \n" " end \n"
"end \n" "end \n"
" \n" " \n"
"if OS.mac? \n" "if OS.mac? \n"
" def memusg(pgid) \n" " def memusg(pgid) \n"
" `/bin/ps -o rss= -g #{pgid}`.to_i \n" " `/bin/ps -o rss= -g #{pgid}`.to_i \n"
" end \n" " end \n"
"elsif OS.linux? \n" "elsif OS.linux? \n"
" def memusg(pgid) \n" " def memusg(pgid) \n"
" `/bin/ps -o rss= -#{pgid}`.to_i \n" " `/bin/ps -o rss= -#{pgid}`.to_i \n"
" end \n" " end \n"
"else \n" "else \n"
" throw %{Unsupported platform #{RUBY_PLATFORM}} \n" " throw %{Unsupported platform #{RUBY_PLATFORM}} \n"
"end \n" "end \n"
" \n" " \n"
"pid = Process.spawn(*ARGV) \n" "pid = Process.spawn(*ARGV) \n"
"Process.detach(pid) # Make sure the child process does not become a zombie \n" "Process.detach(pid) # Make sure the child process does not become a zombie \n"
"peak = 0 \n" "peak = 0 \n"
"# Loop until getpgid throws ESRCH, which means the process is not alive anymore \n" "# Loop until getpgid throws ESRCH, which means the process is not alive anymore \n"
"begin \n" "begin \n"
" while true \n" " while true \n"
" pgid = Process.getpgid(pid) \n" " pgid = Process.getpgid(pid) \n"
" peak = [peak, memusg(pgid)].max \n" " peak = [peak, memusg(pgid)].max \n"
" sleep 0.01 \n" " sleep 0.01 \n"
" end \n" " end \n"
"rescue Errno::ESRCH \n" "rescue Errno::ESRCH \n"
"end \n" "end \n"
" \n" " \n"
"puts %{[PEAK_MEMORY: #{peak}]} \n" "puts %{[PEAK_MEMORY: #{peak}]} \n"
) )
################################################################################ ################################################################################
# end memusg.rb # end memusg.rb
@@ -508,18 +497,18 @@ file(WRITE "${MEMUSG_RB_PATH}"
################################################################################ ################################################################################
set(COMPILE_RB_PATH "${METABENCH_DIR}/compile.rb") set(COMPILE_RB_PATH "${METABENCH_DIR}/compile.rb")
file(WRITE "${COMPILE_RB_PATH}" file(WRITE "${COMPILE_RB_PATH}"
"require 'benchmark' \n" "require 'benchmark' \n"
"require 'open3' \n" "require 'open3' \n"
"stdout = stderr = status = nil \n" "stdout = stderr = status = nil \n"
"command_line = ['${RUBY_EXECUTABLE}', '--', '${MEMUSG_RB_PATH}'] + ARGV \n" "command_line = ['${RUBY_EXECUTABLE}', '--', '${MEMUSG_RB_PATH}'] + ARGV \n"
"time = Benchmark.measure { \n" "time = Benchmark.measure { \n"
" stdout, stderr, status = Open3.capture3(*command_line) \n" " stdout, stderr, status = Open3.capture3(*command_line) \n"
"}.total \n" "}.total \n"
"$stdout.puts(stdout) \n" "$stdout.puts(stdout) \n"
"$stdout.puts(%{[compilation command: #{command_line.join(' ')}]}) \n" "$stdout.puts(%{[compilation command: #{command_line.join(' ')}]}) \n"
"$stdout.puts(%{[COMPILATION_TIME: #{time}]}) \n" "$stdout.puts(%{[COMPILATION_TIME: #{time}]}) \n"
"$stderr.puts(stderr) \n" "$stderr.puts(stderr) \n"
"exit(status.success?) \n" "exit(status.success?) \n"
) )
################################################################################ ################################################################################
# end compile.rb # end compile.rb
@@ -532,15 +521,15 @@ file(WRITE "${COMPILE_RB_PATH}"
################################################################################ ################################################################################
set(LINK_RB_PATH "${METABENCH_DIR}/link.rb") set(LINK_RB_PATH "${METABENCH_DIR}/link.rb")
file(WRITE "${LINK_RB_PATH}" file(WRITE "${LINK_RB_PATH}"
"require 'benchmark' \n" "require 'benchmark' \n"
"require 'open3' \n" "require 'open3' \n"
"stdout = stderr = status = nil \n" "stdout = stderr = status = nil \n"
"time = Benchmark.measure { stdout, stderr, status = Open3.capture3(*ARGV) }.total\n" "time = Benchmark.measure { stdout, stderr, status = Open3.capture3(*ARGV) }.total\n"
"$stdout.puts(stdout) \n" "$stdout.puts(stdout) \n"
"$stdout.puts(%{[link command: #{ARGV.join(' ')}]}) \n" "$stdout.puts(%{[link command: #{ARGV.join(' ')}]}) \n"
"$stdout.puts(%{[LINK_TIME: #{time}]}) \n" "$stdout.puts(%{[LINK_TIME: #{time}]}) \n"
"$stderr.puts(stderr) \n" "$stderr.puts(stderr) \n"
"exit(status.success?) \n" "exit(status.success?) \n"
) )
################################################################################ ################################################################################
# end link.rb # end link.rb
@@ -555,191 +544,191 @@ file(WRITE "${LINK_RB_PATH}"
################################################################################ ################################################################################
set(CHART_HTML_ERB_PATH "${METABENCH_DIR}/chart.html.erb") set(CHART_HTML_ERB_PATH "${METABENCH_DIR}/chart.html.erb")
file(WRITE "${CHART_HTML_ERB_PATH}" file(WRITE "${CHART_HTML_ERB_PATH}"
"<!DOCTYPE html> \n" "<!DOCTYPE html> \n"
"<html> \n" "<html> \n"
" <head> \n" " <head> \n"
" <meta charset='utf-8'> \n" " <meta charset='utf-8'> \n"
" <style><%= IO.read('${METABENCH_DIR}/nvd3.css') %></style> \n" " <style><%= IO.read('${METABENCH_DIR}/nvd3.css') %></style> \n"
" <style> \n" " <style> \n"
" * { \n" " * { \n"
" box-sizing: border-box; \n" " box-sizing: border-box; \n"
" } \n" " } \n"
" html, body { \n" " html, body { \n"
" position: relative; \n" " position: relative; \n"
" height: 100%; \n" " height: 100%; \n"
" width: 100%; \n" " width: 100%; \n"
" border: 0; \n" " border: 0; \n"
" margin: 0; \n" " margin: 0; \n"
" padding: 0; \n" " padding: 0; \n"
" font-size: 0; \n" " font-size: 0; \n"
" } \n" " } \n"
" svg g { \n" " svg g { \n"
" clip-path: none; \n" " clip-path: none; \n"
" } \n" " } \n"
" svg text { \n" " svg text { \n"
" fill: #333; \n" " fill: #333; \n"
" } \n" " } \n"
" .nv-axislabel { \n" " .nv-axislabel { \n"
" font-size: 16px !important; \n" " font-size: 16px !important; \n"
" } \n" " } \n"
" .control { \n" " .control { \n"
" cursor: pointer; \n" " cursor: pointer; \n"
" visibility: hidden; \n" " visibility: hidden; \n"
" pointer-events: visible; \n" " pointer-events: visible; \n"
" } \n" " } \n"
" @media (min-width: 768px) { \n" " @media (min-width: 768px) { \n"
" .control { \n" " .control { \n"
" visibility: visible; \n" " visibility: visible; \n"
" } \n" " } \n"
" } \n" " } \n"
" </style> \n" " </style> \n"
" <script><%= IO.read('${METABENCH_DIR}/d3.js') %></script> \n" " <script><%= IO.read('${METABENCH_DIR}/d3.js') %></script> \n"
" <script><%= IO.read('${METABENCH_DIR}/nvd3.js') %></script> \n" " <script><%= IO.read('${METABENCH_DIR}/nvd3.js') %></script> \n"
" </head> \n" " </head> \n"
" <body> \n" " <body> \n"
" <svg id='chart'></svg> \n" " <svg id='chart'></svg> \n"
" <script type='text/javascript'> \n" " <script type='text/javascript'> \n"
" // Simple helper to compute the median of a sequence of values \n" " // Simple helper to compute the median of a sequence of values \n"
" var median = function(values) { \n" " var median = function(values) { \n"
" values.sort(function(a, b) { return a - b; }); \n" " values.sort(function(a, b) { return a - b; }); \n"
" var half = Math.floor(values.length / 2); \n" " var half = Math.floor(values.length / 2); \n"
" if (values.length % 2) \n" " if (values.length % 2) \n"
" return values[half]; \n" " return values[half]; \n"
" else \n" " else \n"
" return (values[half - 1] + values[half]) / 2.0; \n" " return (values[half - 1] + values[half]) / 2.0; \n"
" }; \n" " }; \n"
" \n" " \n"
" var customSettings = <%= options.to_json %>; \n" " var customSettings = <%= options.to_json %>; \n"
" var aspect = '<%= aspect %>'; \n" " var aspect = '<%= aspect %>'; \n"
" // 'data' is an array of datasets (i.e. curves), each of which is an object of the form \n" " // 'data' is an array of datasets (i.e. curves), each of which is an object of the form \n"
" // { \n" " // { \n"
" // key: <name of the curve>, \n" " // key: <name of the curve>, \n"
" // color: <COLOR argument for that dataset (optional, may be the empty string)>, \n" " // color: <COLOR argument for that dataset (optional, may be the empty string)>, \n"
" // scale: <SCALE argument for that dataset>, \n" " // scale: <SCALE argument for that dataset>, \n"
" // values: [{ \n" " // values: [{ \n"
" // n: <value of n for that run>, \n" " // n: <value of n for that run>, \n"
" // base: [{ // an array of samples for the same 'n' \n" " // base: [{ // an array of samples for the same 'n' \n"
" // COMPILATION_TIME: <compilation time in seconds>, \n" " // COMPILATION_TIME: <compilation time in seconds>, \n"
" // LINK_TIME: <link time in seconds>, \n" " // LINK_TIME: <link time in seconds>, \n"
" // EXECUTABLE_SIZE: <executable size in KB>, \n" " // EXECUTABLE_SIZE: <executable size in KB>, \n"
" // PEAK_MEMORY: <peak memory usage in KB> \n" " // PEAK_MEMORY: <peak memory usage in KB> \n"
" // }], \n" " // }], \n"
" // total: <same as 'base', but with METABENCH defined> \n" " // total: <same as 'base', but with METABENCH defined> \n"
" // }] \n" " // }] \n"
" // } \n" " // } \n"
" var data = <%= data.to_json %>; \n" " var data = <%= data.to_json %>; \n"
" \n" " \n"
" // massage the measurements for ingestion by nvd3 \n" " // massage the measurements for ingestion by nvd3 \n"
" data.forEach(function(dataset) { \n" " data.forEach(function(dataset) { \n"
" dataset.values = dataset.values.map(function(value) { \n" " dataset.values = dataset.values.map(function(value) { \n"
" new_value = {'n': value['n'], 'base': {}, 'total': {}}; \n" " new_value = {'n': value['n'], 'base': {}, 'total': {}}; \n"
" ['COMPILATION_TIME', 'LINK_TIME', 'EXECUTABLE_SIZE', 'PEAK_MEMORY'].forEach(function(aspect) { \n" " ['COMPILATION_TIME', 'LINK_TIME', 'EXECUTABLE_SIZE', 'PEAK_MEMORY'].forEach(function(aspect) { \n"
" new_value['base'][aspect] = value.base.map(function(v){ return dataset.scale * v[aspect]; }); \n" " new_value['base'][aspect] = value.base.map(function(v){ return dataset.scale * v[aspect]; }); \n"
" new_value['total'][aspect] = value.total.map(function(v){ return dataset.scale * v[aspect]; }); \n" " new_value['total'][aspect] = value.total.map(function(v){ return dataset.scale * v[aspect]; }); \n"
" }); \n" " }); \n"
" return new_value; \n" " return new_value; \n"
" }); \n" " }); \n"
" }); \n" " }); \n"
" \n" " \n"
" // setup per-aspect custom settings \n" " // setup per-aspect custom settings \n"
" var aspectDefaults = { \n" " var aspectDefaults = { \n"
" 'COMPILATION_TIME': { \n" " 'COMPILATION_TIME': { \n"
" axisLabel: 'Compilation time', \n" " axisLabel: 'Compilation time', \n"
" tickFormat: function(val){ return d3.format('.2f')(val) + 's'; } \n" " tickFormat: function(val){ return d3.format('.2f')(val) + 's'; } \n"
" }, \n" " }, \n"
" 'EXECUTABLE_SIZE': { \n" " 'EXECUTABLE_SIZE': { \n"
" axisLabel: 'Executable size', \n" " axisLabel: 'Executable size', \n"
" tickFormat: function(val){ return d3.format('.0f')(val) + 'kb'; } \n" " tickFormat: function(val){ return d3.format('.0f')(val) + 'kb'; } \n"
" }, \n" " }, \n"
" 'LINK_TIME': { \n" " 'LINK_TIME': { \n"
" axisLabel: 'Link time', \n" " axisLabel: 'Link time', \n"
" tickFormat: function(val){ return d3.format('.2f')(val) + 's'; } \n" " tickFormat: function(val){ return d3.format('.2f')(val) + 's'; } \n"
" }, \n" " }, \n"
" 'PEAK_MEMORY': { \n" " 'PEAK_MEMORY': { \n"
" axisLabel: 'Peak memory usage', \n" " axisLabel: 'Peak memory usage', \n"
" tickFormat: function(val){ return d3.format('.0f')(val) + 'kb'; } \n" " tickFormat: function(val){ return d3.format('.0f')(val) + 'kb'; } \n"
" } \n" " } \n"
" }; \n" " }; \n"
" \n" " \n"
" // setup the chart and its options \n" " // setup the chart and its options \n"
" var chart = nv.models.lineChart() \n" " var chart = nv.models.lineChart() \n"
" .color(d3.scale.category10().range()) \n" " .color(d3.scale.category10().range()) \n"
" .margin({left: 75, bottom: 50}) \n" " .margin({left: 75, bottom: 50}) \n"
" .forceX([0]).forceY([0]); \n" " .forceX([0]).forceY([0]); \n"
" \n" " \n"
" chart.x(function(datum){ return datum.n; }) \n" " chart.x(function(datum){ return datum.n; }) \n"
" .xAxis.options({ \n" " .xAxis.options({ \n"
" axisLabel: customSettings.XLABEL || 'Number of elements', \n" " axisLabel: customSettings.XLABEL || 'Number of elements', \n"
" tickFormat: d3.format('.0f') \n" " tickFormat: d3.format('.0f') \n"
" }); \n" " }); \n"
" \n" " \n"
" var subtract_baseline = function(datum) { \n" " var subtract_baseline = function(datum) { \n"
" return Math.max(0, median(datum.total[aspect]) - median(datum.base[aspect])); \n" " return Math.max(0, median(datum.total[aspect]) - median(datum.base[aspect])); \n"
" }; \n" " }; \n"
" chart.y(subtract_baseline) \n" " chart.y(subtract_baseline) \n"
" .yAxis.options({ \n" " .yAxis.options({ \n"
" axisLabel: customSettings.YLABEL || aspectDefaults[aspect].axisLabel, \n" " axisLabel: customSettings.YLABEL || aspectDefaults[aspect].axisLabel, \n"
" tickFormat: aspectDefaults[aspect].tickFormat \n" " tickFormat: aspectDefaults[aspect].tickFormat \n"
" }); \n" " }); \n"
" \n" " \n"
" chart.interpolate('cardinal').useInteractiveGuideline(true); \n" " chart.interpolate('cardinal').useInteractiveGuideline(true); \n"
" d3.select('#chart').datum(data).call(chart); \n" " d3.select('#chart').datum(data).call(chart); \n"
" var plot = d3.select('#chart > g'); \n" " var plot = d3.select('#chart > g'); \n"
" \n" " \n"
" // setup the title \n" " // setup the title \n"
" plot.append('text') \n" " plot.append('text') \n"
" .style('font-size', '24px') \n" " .style('font-size', '24px') \n"
" .attr('text-anchor', 'middle').attr('x', '50%').attr('y', '20px') \n" " .attr('text-anchor', 'middle').attr('x', '50%').attr('y', '20px') \n"
" .text(customSettings.TITLE || ''); \n" " .text(customSettings.TITLE || ''); \n"
" \n" " \n"
" // setup the subtitle \n" " // setup the subtitle \n"
" plot.append('text') \n" " plot.append('text') \n"
" .style('font-size', '16px') \n" " .style('font-size', '16px') \n"
" .attr('text-anchor', 'middle').attr('x', '50%').attr('y', '40px') \n" " .attr('text-anchor', 'middle').attr('x', '50%').attr('y', '40px') \n"
" .text(customSettings.SUBTITLE || ''); \n" " .text(customSettings.SUBTITLE || ''); \n"
" \n" " \n"
" // setup interpolation control \n" " // setup interpolation control \n"
" var controls = plot.select('.nv-x.nv-axis').append('g').attr('transform', 'translate(24,30)'); \n" " var controls = plot.select('.nv-x.nv-axis').append('g').attr('transform', 'translate(24,30)'); \n"
" var interpolate = controls.append('g').attr('class', 'control interpolate').datum([chart.interpolate()]); \n" " var interpolate = controls.append('g').attr('class', 'control interpolate').datum([chart.interpolate()]); \n"
" interpolate.append('circle') \n" " interpolate.append('circle') \n"
" .style('fill', '#333').style('stroke', '#333').style('stroke-width', '2').style('fill-opacity', 1) \n" " .style('fill', '#333').style('stroke', '#333').style('stroke-width', '2').style('fill-opacity', 1) \n"
" .attr('cx', 0).attr('cy', 0).attr('r', 5); \n" " .attr('cx', 0).attr('cy', 0).attr('r', 5); \n"
" interpolate.append('text').attr('text-anchor', 'start').attr('dx', '8').attr('dy', '.32em').text('interpolate'); \n" " interpolate.append('text').attr('text-anchor', 'start').attr('dx', '8').attr('dy', '.32em').text('interpolate'); \n"
" interpolate.on('click', function() { \n" " interpolate.on('click', function() { \n"
" if (chart.interpolate() === interpolate.datum()[0]) { \n" " if (chart.interpolate() === interpolate.datum()[0]) { \n"
" interpolate.select('circle').style('fill-opacity', 0); \n" " interpolate.select('circle').style('fill-opacity', 0); \n"
" chart.interpolate('linear'); \n" " chart.interpolate('linear'); \n"
" } else { \n" " } else { \n"
" d3.select(this).select('circle').style('fill-opacity', 1); \n" " d3.select(this).select('circle').style('fill-opacity', 1); \n"
" chart.interpolate(interpolate.datum()[0]); \n" " chart.interpolate(interpolate.datum()[0]); \n"
" } \n" " } \n"
" chart.update(); \n" " chart.update(); \n"
" }); \n" " }); \n"
" \n" " \n"
" // setup baseline control \n" " // setup baseline control \n"
" var baseline = controls.append('g').attr('class', 'control baseline').datum(true /* whether button is checked */); \n" " var baseline = controls.append('g').attr('class', 'control baseline').datum(true /* whether button is checked */); \n"
" baseline.attr('transform', 'translate(80,0)').append('circle') \n" " baseline.attr('transform', 'translate(80,0)').append('circle') \n"
" .style('fill', '#333').style('stroke', '#333').style('stroke-width', '2').style('fill-opacity', 1) \n" " .style('fill', '#333').style('stroke', '#333').style('stroke-width', '2').style('fill-opacity', 1) \n"
" .attr('cx', 0).attr('cy', 0).attr('r', 5); \n" " .attr('cx', 0).attr('cy', 0).attr('r', 5); \n"
" baseline.append('text').attr('text-anchor', 'start').attr('dx', '8').attr('dy', '.32em').text('subtract baseline'); \n" " baseline.append('text').attr('text-anchor', 'start').attr('dx', '8').attr('dy', '.32em').text('subtract baseline'); \n"
" baseline.on('click', function() { \n" " baseline.on('click', function() { \n"
" // We subtract the baseline from the total if the button was just checked, otherwise we use the total unchanged. \n" " // We subtract the baseline from the total if the button was just checked, otherwise we use the total unchanged. \n"
" if (!baseline.datum()) { \n" " if (!baseline.datum()) { \n"
" d3.select(this).select('circle').style('fill-opacity', 1); \n" " d3.select(this).select('circle').style('fill-opacity', 1); \n"
" chart.y(subtract_baseline); \n" " chart.y(subtract_baseline); \n"
" } else { \n" " } else { \n"
" baseline.select('circle').style('fill-opacity', 0); \n" " baseline.select('circle').style('fill-opacity', 0); \n"
" chart.y(function(datum) { return median(datum.total[aspect]); }); \n" " chart.y(function(datum) { return median(datum.total[aspect]); }); \n"
" } \n" " } \n"
" baseline.datum(!baseline.datum()); // toggle the radio button \n" " baseline.datum(!baseline.datum()); // toggle the radio button \n"
" chart.update(); \n" " chart.update(); \n"
" }); \n" " }); \n"
" \n" " \n"
" // ensure the chart is responsive \n" " // ensure the chart is responsive \n"
" nv.utils.windowResize(chart.update); \n" " nv.utils.windowResize(chart.update); \n"
" </script> \n" " </script> \n"
" </body> \n" " </body> \n"
"</html> \n" "</html> \n"
) )
################################################################################ ################################################################################
# end chart.html.erb # end chart.html.erb
@@ -751,13 +740,15 @@ file(WRITE "${CHART_HTML_ERB_PATH}"
# The following is a copy of the nvd3 1.8.5 css file. # The following is a copy of the nvd3 1.8.5 css file.
# https://github.com/novus/nvd3 # https://github.com/novus/nvd3
################################################################################ ################################################################################
file(WRITE "${METABENCH_DIR}/nvd3.css" "\ file(WRITE "${METABENCH_DIR}/nvd3.css"
"\
.nvd3 .nv-axis line,.nvd3 .nv-axis path{fill:none;shape-rendering:crispEdges}.nv-brush .extent,.nvd3 .background path,.nvd3 .nv-axis line,.nvd3 .nv-axis path{shape-rendering:crispEdges}.nv-distx,.nv-disty,.nv-noninteractive,.nvd3 .nv-axis,.nvd3.nv-pie .nv-label,.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3 .nv-axis{opacity:1}.nvd3 .nv-axis.nv-disabled,.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3 .nv-axis path{stroke:#000;stroke-opacity:.75}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{stroke:#e5e5e5}.nvd3 .nv-axis .zero line, .nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:transparent}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-discretebar .nv-groups rect,.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick,.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover,.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:transparent}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover,.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet \ .nvd3 .nv-axis line,.nvd3 .nv-axis path{fill:none;shape-rendering:crispEdges}.nv-brush .extent,.nvd3 .background path,.nvd3 .nv-axis line,.nvd3 .nv-axis path{shape-rendering:crispEdges}.nv-distx,.nv-disty,.nv-noninteractive,.nvd3 .nv-axis,.nvd3.nv-pie .nv-label,.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3 .nv-axis{opacity:1}.nvd3 .nv-axis.nv-disabled,.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3 .nv-axis path{stroke:#000;stroke-opacity:.75}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{stroke:#e5e5e5}.nvd3 .nv-axis .zero line, .nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:transparent}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-discretebar .nv-groups rect,.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick,.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover,.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:transparent}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover,.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet \
.nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-markerLine{stroke:#000;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nv-force-node{stroke:#fff;stroke-width:1.5px}.nv-force-link{stroke:#999;stroke-opacity:.6}.nv-force-node text{stroke-width:0}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.nvd3 .nv-groups .nv-point.hover,.nvd3.nv-scatter .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;width:100%;\ .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-markerLine{stroke:#000;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nv-force-node{stroke:#fff;stroke-width:1.5px}.nv-force-link{stroke:#999;stroke-opacity:.6}.nv-force-node text{stroke-width:0}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.nvd3 .nv-groups .nv-point.hover,.nvd3.nv-scatter .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;width:100%;\
height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{box-shadow:0 5px 10px rgba(0,0,0,.2);border-radius:5px}.nvd3 text{font:400 12px Arial,sans-serif}.nvd3 .title{font:700 14px Arial,sans-serif}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}\@media print{.nvd3 text{stroke-width:0;fill-opacity:1}}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;stroke:#fff;stroke-width:1px;stroke-opacity:1;fill-opacity:.7}.nvd3.nv-pie .hover path{fill-opacity:1}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-interactiveGuideLine,.nvtooltip{pointer-events:none}.nvd3 .nv-hoverArea{fill-opacity:0;\ height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{box-shadow:0 5px 10px rgba(0,0,0,.2);border-radius:5px}.nvd3 text{font:400 12px Arial,sans-serif}.nvd3 .title{font:700 14px Arial,sans-serif}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}\@media print{.nvd3 text{stroke-width:0;fill-opacity:1}}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;stroke:#fff;stroke-width:1px;stroke-opacity:1;fill-opacity:.7}.nvd3.nv-pie .hover path{fill-opacity:1}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-interactiveGuideLine,.nvtooltip{pointer-events:none}.nvd3 .nv-hoverArea{fill-opacity:0;\
stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvtooltip h3,.nvtooltip table td.key{font-weight:400}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;color:rgba(0,0,0,1);padding:1px;z-index:10000;display:block;font-family:Arial,sans-serif;font-size:13px;text-align:left;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip h3,.nvtooltip p{margin:0;text-align:center}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{padding:4px 14px;line-height:18px;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.nvtooltip p{padding:5px 14px}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key.total{font-weight:700}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table td.percent{color:#a9a9a9}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{vertical-align:middle;width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;\ stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvtooltip h3,.nvtooltip table td.key{font-weight:400}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;color:rgba(0,0,0,1);padding:1px;z-index:10000;display:block;font-family:Arial,sans-serif;font-size:13px;text-align:left;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip h3,.nvtooltip p{margin:0;text-align:center}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{padding:4px 14px;line-height:18px;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.nvtooltip p{padding:5px 14px}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key.total{font-weight:700}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table td.percent{color:#a9a9a9}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{vertical-align:middle;width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;\
display:none}.nvd3 line.nv-guideline{stroke:#ccc}\ display:none}.nvd3 line.nv-guideline{stroke:#ccc}\
") "
)
################################################################################ ################################################################################
# end nvd3.css # end nvd3.css
################################################################################ ################################################################################
@@ -770,7 +761,8 @@ display:none}.nvd3 line.nv-guideline{stroke:#ccc}\
# parsing too long strings. # parsing too long strings.
# https://github.com/novus/nvd3 # https://github.com/novus/nvd3
################################################################################ ################################################################################
file(WRITE "${METABENCH_DIR}/nvd3.js" "\ file(WRITE "${METABENCH_DIR}/nvd3.js"
"\
/* nvd3 version 1.8.5 (https://github.com/novus/nvd3) 2016-12-01 */\ /* nvd3 version 1.8.5 (https://github.com/novus/nvd3) 2016-12-01 */\
!function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},\"undefined\"!=typeof module&&\"undefined\"!=typeof exports&&\"undefined\"==typeof d3&&(d3=require(\"d3\")),a.dispatch=d3.dispatch(\"render_start\",\"render_end\"),Function.prototype.bind||(Function.prototype.bind=function(a){if(\"function\"!=typeof this)throw new TypeError(\"Function.prototype.bind - what is trying to be bound is not callable\");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on(\"render_start\",function(b){a.logs.startTime=+new Date}),a.dispatch.on(\"render_end\",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log(\"total\",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&\"function\"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn(\"nvd3 warning: `\"+a+\"` has been deprecated. \",b||\"\")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},\"undefined\"!=typeof module&&\"undefined\"!=typeof exports&&(module.exports=a),\"undefined\"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.mutate(a):a()},\ !function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},\"undefined\"!=typeof module&&\"undefined\"!=typeof exports&&\"undefined\"==typeof d3&&(d3=require(\"d3\")),a.dispatch=d3.dispatch(\"render_start\",\"render_end\"),Function.prototype.bind||(Function.prototype.bind=function(a){if(\"function\"!=typeof this)throw new TypeError(\"Function.prototype.bind - what is trying to be bound is not callable\");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on(\"render_start\",function(b){a.logs.startTime=+new Date}),a.dispatch.on(\"render_end\",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log(\"total\",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&\"function\"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn(\"nvd3 warning: `\"+a+\"` has been deprecated. \",b||\"\")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},\"undefined\"!=typeof module&&\"undefined\"!=typeof exports&&(module.exports=a),\"undefined\"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.mutate(a):a()},\
a.dom.read=function(a){return void 0!==window.fastdom?fastdom.measure(a):a()},a.interactiveGuideline=function(){\"use strict\";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],h=!0,i=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,\"svg\"!==d3.event.target.tagName&&(h=!1),d3.event.target.className.baseVal.match(\"nv-legend\")&&(i=!0)),h&&(d-=c.left,e-=c.top),\"mouseout\"===d3.event.type||0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||i){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(j.nvPointerEventsClass)))return;return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0)}j.hidden(!1);var l=\"function\"==typeof f.rangeBands,m=void 0;if(l){var n=d3.bisect(f.range(),d)-1;if(!(f.range()[n]+f.rangeBand()>=d))return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0);m=f.domain()[d3.bisect(f.range(),d)-1]}else m=f.invert(d);g.elementMousemove({mouseX:d,mouseY:e,pointXValue:m}),\"dblclick\"===d3.event.type&&g.elementDblclick({mouseX:d,mouseY:e,pointXValue:m}),\"click\"===d3.event.type&&g.elementClick({mouseX:d,mouseY:e,pointXValue:m}),\"mousedown\"===d3.event.type&&g.elementMouseDown({mouseX:d,mouseY:e,pointXValue:m}),\"mouseup\"===d3.event.type&&g.elementMouseUp({mouseX:d,mouseY:e,pointXValue:m})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll(\"g.nv-wrap.nv-interactiveLineLayer\").data([l]),r=q.enter().append(\"g\").attr(\"class\",\" nv-wrap nv-interactiveLineLayer\");r.append(\"g\").attr(\"class\",\"nv-interactiveGuideLine\"),i&&(i.on(\"touchmove\",m).on(\"mousemove\",m,!0).on(\"mouseout\",m,!0).on(\"mousedown\",m,!0).on(\"mouseup\",m,!0).on(\"dblclick\",m).on(\"click\",m),b.guideLine=null,b.renderGuideLine=function(c){h&&(b.guideLine&&b.guideLine.attr(\"x1\")===c||a.dom.write(function(){var b=q.select(\".nv-interactiveGuideLine\").selectAll(\"line\").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append(\"line\").attr(\"class\",\ a.dom.read=function(a){return void 0!==window.fastdom?fastdom.measure(a):a()},a.interactiveGuideline=function(){\"use strict\";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],h=!0,i=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,\"svg\"!==d3.event.target.tagName&&(h=!1),d3.event.target.className.baseVal.match(\"nv-legend\")&&(i=!0)),h&&(d-=c.left,e-=c.top),\"mouseout\"===d3.event.type||0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||i){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(j.nvPointerEventsClass)))return;return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0)}j.hidden(!1);var l=\"function\"==typeof f.rangeBands,m=void 0;if(l){var n=d3.bisect(f.range(),d)-1;if(!(f.range()[n]+f.rangeBand()>=d))return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0);m=f.domain()[d3.bisect(f.range(),d)-1]}else m=f.invert(d);g.elementMousemove({mouseX:d,mouseY:e,pointXValue:m}),\"dblclick\"===d3.event.type&&g.elementDblclick({mouseX:d,mouseY:e,pointXValue:m}),\"click\"===d3.event.type&&g.elementClick({mouseX:d,mouseY:e,pointXValue:m}),\"mousedown\"===d3.event.type&&g.elementMouseDown({mouseX:d,mouseY:e,pointXValue:m}),\"mouseup\"===d3.event.type&&g.elementMouseUp({mouseX:d,mouseY:e,pointXValue:m})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll(\"g.nv-wrap.nv-interactiveLineLayer\").data([l]),r=q.enter().append(\"g\").attr(\"class\",\" nv-wrap nv-interactiveLineLayer\");r.append(\"g\").attr(\"class\",\"nv-interactiveGuideLine\"),i&&(i.on(\"touchmove\",m).on(\"mousemove\",m,!0).on(\"mouseout\",m,!0).on(\"mousedown\",m,!0).on(\"mouseup\",m,!0).on(\"dblclick\",m).on(\"click\",m),b.guideLine=null,b.renderGuideLine=function(c){h&&(b.guideLine&&b.guideLine.attr(\"x1\")===c||a.dom.write(function(){var b=q.select(\".nv-interactiveGuideLine\").selectAll(\"line\").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append(\"line\").attr(\"class\",\
@@ -800,9 +792,11 @@ c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=
h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){\"use strict\";function b(l){return I.reset(),I.models(f),s&&I.models(g),t&&I.models(h),l.each(function(l){function B(a,c){d3.select(b.container).style(\"cursor\",\"ew-resize\")}function F(a,b){H.x=d3.event.x,H.i=Math.round(G.invert(H.x)),L()}function I(a,c){d3.select(b.container).style(\"cursor\",\"auto\"),z.index=H.i,D.stateChange(z)}function L(){ba.data([H]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var M=d3.select(this);a.utils.initSVG(M),M.classed(\"nv-chart-\"+y,!0);var N=a.utils.availableWidth(p,M,m),O=a.utils.availableHeight(q,M,m);if(b.update=function(){0===E?M.call(b):M.transition().duration(E).call(b)},b.container=this,z.setter(K(l),b.update).getter(J(l)).update(),z.disabled=l.map(function(a){return!!a.disabled}),!A){var P;A={};for(P in z)z[P]instanceof Array?A[P]=z[P].slice(0):A[P]=z[P]}var Q=d3.behavior.drag().on(\"dragstart\",B).on(\"drag\",F).on(\"dragend\",I);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,M),b;if(M.selectAll(\".nv-noData\").remove(),d=f.xScale(),e=f.yScale(),x)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}G.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(H.i,l),T=w?\"none\":\"all\",U=M.selectAll(\"g.nv-wrap.nv-cumulativeLine\").data([l]),V=U.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-cumulativeLine\").append(\"g\"),W=U.select(\"g\");if(V.append(\"g\").attr(\"class\",\"nv-interactive\"),V.append(\"g\").attr(\"class\",\"nv-x nv-axis\").style(\"pointer-events\",\"none\"),V.append(\"g\").attr(\"class\",\"nv-y nv-axis\"),V.append(\"g\").attr(\"class\",\"nv-background\"),V.append(\"g\").attr(\"class\",\"nv-linesWrap\").style(\"pointer-events\",\ h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){\"use strict\";function b(l){return I.reset(),I.models(f),s&&I.models(g),t&&I.models(h),l.each(function(l){function B(a,c){d3.select(b.container).style(\"cursor\",\"ew-resize\")}function F(a,b){H.x=d3.event.x,H.i=Math.round(G.invert(H.x)),L()}function I(a,c){d3.select(b.container).style(\"cursor\",\"auto\"),z.index=H.i,D.stateChange(z)}function L(){ba.data([H]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var M=d3.select(this);a.utils.initSVG(M),M.classed(\"nv-chart-\"+y,!0);var N=a.utils.availableWidth(p,M,m),O=a.utils.availableHeight(q,M,m);if(b.update=function(){0===E?M.call(b):M.transition().duration(E).call(b)},b.container=this,z.setter(K(l),b.update).getter(J(l)).update(),z.disabled=l.map(function(a){return!!a.disabled}),!A){var P;A={};for(P in z)z[P]instanceof Array?A[P]=z[P].slice(0):A[P]=z[P]}var Q=d3.behavior.drag().on(\"dragstart\",B).on(\"drag\",F).on(\"dragend\",I);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,M),b;if(M.selectAll(\".nv-noData\").remove(),d=f.xScale(),e=f.yScale(),x)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}G.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(H.i,l),T=w?\"none\":\"all\",U=M.selectAll(\"g.nv-wrap.nv-cumulativeLine\").data([l]),V=U.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-cumulativeLine\").append(\"g\"),W=U.select(\"g\");if(V.append(\"g\").attr(\"class\",\"nv-interactive\"),V.append(\"g\").attr(\"class\",\"nv-x nv-axis\").style(\"pointer-events\",\"none\"),V.append(\"g\").attr(\"class\",\"nv-y nv-axis\"),V.append(\"g\").attr(\"class\",\"nv-background\"),V.append(\"g\").attr(\"class\",\"nv-linesWrap\").style(\"pointer-events\",\
T),V.append(\"g\").attr(\"class\",\"nv-avgLinesWrap\").style(\"pointer-events\",\"none\"),V.append(\"g\").attr(\"class\",\"nv-legendWrap\"),V.append(\"g\").attr(\"class\",\"nv-controlsWrap\"),r?(i.width(N),W.select(\".nv-legendWrap\").datum(l).call(i),n||i.height()===m.top||(m.top=i.height(),O=a.utils.availableHeight(q,M,m)),W.select(\".nv-legendWrap\").attr(\"transform\",\"translate(0,\"+-m.top+\")\")):W.select(\".nv-legendWrap\").selectAll(\"*\").remove(),v){var X=[{key:\"Re-scale y-axis\",disabled:!x}];j.width(140).color([\"#444\",\"#444\",\"#444\"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(\".nv-controlsWrap\").datum(X).attr(\"transform\",\"translate(0,\"+-m.top+\")\").call(j)}else W.select(\".nv-controlsWrap\").selectAll(\"*\").remove();U.attr(\"transform\",\"translate(\"+m.left+\",\"+m.top+\")\"),u&&W.select(\".nv-y.nv-axis\").attr(\"transform\",\"translate(\"+N+\",0)\");var Y=l.filter(function(a){return a.tempDisabled});U.select(\".tempDisabled\").remove(),Y.length&&U.append(\"text\").attr(\"class\",\"tempDisabled\").attr(\"x\",N/2).attr(\"y\",\"-.71em\").style(\"text-anchor\",\"end\").text(Y.map(function(a){return a.key}).join(\", \")+\" values cannot be calculated for this time period.\"),w&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(M).xScale(d),U.select(\".nv-interactive\").call(k)),V.select(\".nv-background\").append(\"rect\"),W.select(\".nv-background rect\").attr(\"width\",N).attr(\"height\",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(\".nv-linesWrap\").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!C(a)}),_=W.select(\".nv-avgLinesWrap\").selectAll(\"line\").data($,function(a){return a.key}),aa=function(a){var b=e(C(a));return 0>b?0:b>O?O:b};_.enter().append(\"line\").style(\"stroke-width\",2).style(\"stroke-dasharray\",\"10,10\").style(\"stroke\",function(a,b){return f.color()(a,a.seriesIndex)}).attr(\"x1\",0).attr(\"x2\",\ T),V.append(\"g\").attr(\"class\",\"nv-avgLinesWrap\").style(\"pointer-events\",\"none\"),V.append(\"g\").attr(\"class\",\"nv-legendWrap\"),V.append(\"g\").attr(\"class\",\"nv-controlsWrap\"),r?(i.width(N),W.select(\".nv-legendWrap\").datum(l).call(i),n||i.height()===m.top||(m.top=i.height(),O=a.utils.availableHeight(q,M,m)),W.select(\".nv-legendWrap\").attr(\"transform\",\"translate(0,\"+-m.top+\")\")):W.select(\".nv-legendWrap\").selectAll(\"*\").remove(),v){var X=[{key:\"Re-scale y-axis\",disabled:!x}];j.width(140).color([\"#444\",\"#444\",\"#444\"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(\".nv-controlsWrap\").datum(X).attr(\"transform\",\"translate(0,\"+-m.top+\")\").call(j)}else W.select(\".nv-controlsWrap\").selectAll(\"*\").remove();U.attr(\"transform\",\"translate(\"+m.left+\",\"+m.top+\")\"),u&&W.select(\".nv-y.nv-axis\").attr(\"transform\",\"translate(\"+N+\",0)\");var Y=l.filter(function(a){return a.tempDisabled});U.select(\".tempDisabled\").remove(),Y.length&&U.append(\"text\").attr(\"class\",\"tempDisabled\").attr(\"x\",N/2).attr(\"y\",\"-.71em\").style(\"text-anchor\",\"end\").text(Y.map(function(a){return a.key}).join(\", \")+\" values cannot be calculated for this time period.\"),w&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(M).xScale(d),U.select(\".nv-interactive\").call(k)),V.select(\".nv-background\").append(\"rect\"),W.select(\".nv-background rect\").attr(\"width\",N).attr(\"height\",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||o(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(\".nv-linesWrap\").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!C(a)}),_=W.select(\".nv-avgLinesWrap\").selectAll(\"line\").data($,function(a){return a.key}),aa=function(a){var b=e(C(a));return 0>b?0:b>O?O:b};_.enter().append(\"line\").style(\"stroke-width\",2).style(\"stroke-dasharray\",\"10,10\").style(\"stroke\",function(a,b){return f.color()(a,a.seriesIndex)}).attr(\"x1\",0).attr(\"x2\",\
N).attr(\"y1\",aa).attr(\"y2\",aa),_.style(\"stroke-opacity\",function(a){var b=e(C(a));return 0>b||b>O?0:1}).attr(\"x1\",0).attr(\"x2\",N).attr(\"y1\",aa).attr(\"y2\",aa),_.exit().remove();var ba=Z.selectAll(\".nv-indexLine\").data([H]);ba.enter().append(\"rect\").attr(\"class\",\"nv-indexLine\").attr(\"width\",3).attr(\"x\",-2).attr(\"fill\",\"red\").attr(\"fill-opacity\",.5).style(\"pointer-events\",\"all\").call(Q),ba.attr(\"transform\",function(a){return\"translate(\"+G(a.i)+\",0)\"}).attr(\"height\",O),s&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(\".nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+e.range()[0]+\")\"),W.select(\".nv-x.nv-axis\").call(g)),t&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(\".nv-y.nv-axis\").call(h)),W.select(\".nv-background rect\").on(\"click\",function(){H.x=d3.mouse(this)[0],H.i=Math.round(G.invert(H.x)),z.index=H.i,D.stateChange(z),L()}),f.dispatch.on(\"elementClick\",function(a){H.i=a.pointIndex,H.x=G(H.i),z.index=H.i,D.stateChange(z),L()}),j.dispatch.on(\"legendClick\",function(a,c){a.disabled=!a.disabled,x=!a.disabled,z.rescaleY=x,D.stateChange(z),b.update()}),i.dispatch.on(\"stateChange\",function(a){for(var c in a)z[c]=a[c];D.stateChange(z),b.update()}),k.dispatch.on(\"elementMousemove\",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];\"undefined\"!=typeof k&&(\"undefined\"==typeof d&&(d=k),\"undefined\"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:o(g,g.seriesIndex)}))}),j.length>2){var m=b.yScale().invert(c.mouseY),n=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*n,q=a.nearestValueIndex(j.map(function(a){return a.value}),m,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(b.x()(d,e),e);k.tooltip.valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on(\"elementMouseout\",function(a){f.clearHighlights()}),\ N).attr(\"y1\",aa).attr(\"y2\",aa),_.style(\"stroke-opacity\",function(a){var b=e(C(a));return 0>b||b>O?0:1}).attr(\"x1\",0).attr(\"x2\",N).attr(\"y1\",aa).attr(\"y2\",aa),_.exit().remove();var ba=Z.selectAll(\".nv-indexLine\").data([H]);ba.enter().append(\"rect\").attr(\"class\",\"nv-indexLine\").attr(\"width\",3).attr(\"x\",-2).attr(\"fill\",\"red\").attr(\"fill-opacity\",.5).style(\"pointer-events\",\"all\").call(Q),ba.attr(\"transform\",function(a){return\"translate(\"+G(a.i)+\",0)\"}).attr(\"height\",O),s&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(\".nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+e.range()[0]+\")\"),W.select(\".nv-x.nv-axis\").call(g)),t&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(\".nv-y.nv-axis\").call(h)),W.select(\".nv-background rect\").on(\"click\",function(){H.x=d3.mouse(this)[0],H.i=Math.round(G.invert(H.x)),z.index=H.i,D.stateChange(z),L()}),f.dispatch.on(\"elementClick\",function(a){H.i=a.pointIndex,H.x=G(H.i),z.index=H.i,D.stateChange(z),L()}),j.dispatch.on(\"legendClick\",function(a,c){a.disabled=!a.disabled,x=!a.disabled,z.rescaleY=x,D.stateChange(z),b.update()}),i.dispatch.on(\"stateChange\",function(a){for(var c in a)z[c]=a[c];D.stateChange(z),b.update()}),k.dispatch.on(\"elementMousemove\",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];\"undefined\"!=typeof k&&(\"undefined\"==typeof d&&(d=k),\"undefined\"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:o(g,g.seriesIndex)}))}),j.length>2){var m=b.yScale().invert(c.mouseY),n=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*n,q=a.nearestValueIndex(j.map(function(a){return a.value}),m,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(b.x()(d,e),e);k.tooltip.valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on(\"elementMouseout\",function(a){f.clearHighlights()}),\
") "
)
file(APPEND "${METABENCH_DIR}/nvd3.js" "\ file(APPEND "${METABENCH_DIR}/nvd3.js"
"\
D.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),z.disabled=a.disabled),\"undefined\"!=typeof a.index&&(H.i=a.index,H.x=G(H.i),z.index=a.index,ba.data([H])),\"undefined\"!=typeof a.rescaleY&&(x=a.rescaleY),b.update()})}),I.renderEnd(\"cumulativeLineChart immediate\"),b}function c(a,b){return L||(L=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=L(d,a);return-.95>e&&!F?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(L(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=null,o=a.utils.defaultColor(),p=null,q=null,r=!0,s=!0,t=!0,u=!1,v=!0,w=!1,x=!0,y=f.id(),z=a.utils.state(),A=null,B=null,C=function(a){return a.average},D=d3.dispatch(\"stateChange\",\"changeState\",\"renderEnd\"),E=250,F=!1;z.index=0,z.rescaleY=x,g.orient(\"bottom\").tickPadding(7),h.orient(u?\"right\":\"left\"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var G=d3.scale.linear(),H={i:0,x:0},I=a.utils.renderWatch(D,E),J=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:H.i,rescaleY:x}}},K=function(a){return function(b){void 0!==b.index&&(H.i=b.index),void 0!==b.rescaleY&&(x=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on(\"elementMouseover.tooltip\",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).hidden(!1)}),f.dispatch.on(\"elementMouseout.tooltip\",function(a){l.hidden(!0)});var L=null;return b.dispatch=D,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=z,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return p},set:function(a){p=a}},height:{get:function(){return \ D.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),z.disabled=a.disabled),\"undefined\"!=typeof a.index&&(H.i=a.index,H.x=G(H.i),z.index=a.index,ba.data([H])),\"undefined\"!=typeof a.rescaleY&&(x=a.rescaleY),b.update()})}),I.renderEnd(\"cumulativeLineChart immediate\"),b}function c(a,b){return L||(L=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=L(d,a);return-.95>e&&!F?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(L(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=null,o=a.utils.defaultColor(),p=null,q=null,r=!0,s=!0,t=!0,u=!1,v=!0,w=!1,x=!0,y=f.id(),z=a.utils.state(),A=null,B=null,C=function(a){return a.average},D=d3.dispatch(\"stateChange\",\"changeState\",\"renderEnd\"),E=250,F=!1;z.index=0,z.rescaleY=x,g.orient(\"bottom\").tickPadding(7),h.orient(u?\"right\":\"left\"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var G=d3.scale.linear(),H={i:0,x:0},I=a.utils.renderWatch(D,E),J=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:H.i,rescaleY:x}}},K=function(a){return function(b){void 0!==b.index&&(H.i=b.index),void 0!==b.rescaleY&&(x=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on(\"elementMouseover.tooltip\",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).hidden(!1)}),f.dispatch.on(\"elementMouseout.tooltip\",function(a){l.hidden(!0)});var L=null;return b.dispatch=D,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=z,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return p},set:function(a){p=a}},height:{get:function(){return \
q},set:function(a){q=a}},rescaleY:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return r},set:function(a){r=a}},average:{get:function(){return C},set:function(a){C=a}},defaultState:{get:function(){return A},set:function(a){A=a}},noData:{get:function(){return B},set:function(a){B=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},noErrorCheck:{get:function(){return F},set:function(a){F=a}},margin:{get:function(){return m},set:function(a){void 0!==a.top&&(m.top=a.top,n=a.top),m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),i.color(o)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,h.orient(a?\"right\":\"left\")}},duration:{get:function(){return E},set:function(a){E=a,f.duration(E),g.duration(E),h.duration(E),I.reset(E)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){\"use strict\";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),t?o.range(g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);var A=c.selectAll(\"g.nv-wrap.nv-discretebar\").data([b]),B=A.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-discretebar\"),C=B.append(\"g\");A.select(\"g\");C.append(\"g\").attr(\"class\",\"nv-groups\"),A.attr(\"transform\",\ q},set:function(a){q=a}},rescaleY:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return r},set:function(a){r=a}},average:{get:function(){return C},set:function(a){C=a}},defaultState:{get:function(){return A},set:function(a){A=a}},noData:{get:function(){return B},set:function(a){B=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},noErrorCheck:{get:function(){return F},set:function(a){F=a}},margin:{get:function(){return m},set:function(a){void 0!==a.top&&(m.top=a.top,n=a.top),m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),i.color(o)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,h.orient(a?\"right\":\"left\")}},duration:{get:function(){return E},set:function(a){E=a,f.duration(E),g.duration(E),h.duration(E),I.reset(E)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){\"use strict\";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),t?o.range(g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);var A=c.selectAll(\"g.nv-wrap.nv-discretebar\").data([b]),B=A.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-discretebar\"),C=B.append(\"g\");A.select(\"g\");C.append(\"g\").attr(\"class\",\"nv-groups\"),A.attr(\"transform\",\
\"translate(\"+j.left+\",\"+j.top+\")\");var D=A.select(\".nv-groups\").selectAll(\".nv-group\").data(function(a){return a},function(a){return a.key});D.enter().append(\"g\").style(\"stroke-opacity\",1e-6).style(\"fill-opacity\",1e-6),D.exit().watchTransition(y,\"discreteBar: exit groups\").style(\"stroke-opacity\",1e-6).style(\"fill-opacity\",1e-6).remove(),D.attr(\"class\",function(a,b){return\"nv-group nv-series-\"+b}).classed(\"hover\",function(a){return a.hover}),D.watchTransition(y,\"discreteBar: groups\").style(\"stroke-opacity\",1).style(\"fill-opacity\",.75);var E=D.selectAll(\"g.nv-bar\").data(function(a){return a.values});E.exit().remove();var F=E.enter().append(\"g\").attr(\"transform\",function(a,b,c){return\"translate(\"+(n(p(a,b))+.05*n.rangeBand())+\", \"+o(0)+\")\"}).on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"mousemove\",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"click\",function(a,b){var c=this;v.elementClick({data:a,index:b,color:d3.select(this).style(\"fill\"),event:d3.event,element:c}),d3.event.stopPropagation()}).on(\"dblclick\",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style(\"fill\")}),d3.event.stopPropagation()});F.append(\"rect\").attr(\"height\",0).attr(\"width\",.9*n.rangeBand()/b.length),t?(F.append(\"text\").attr(\"text-anchor\",\"middle\"),E.select(\"text\").text(function(a,b){return u(q(a,b))}).watchTransition(y,\"discreteBar: bars text\").attr(\"x\",.9*n.rangeBand()/2).attr(\"y\",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll(\"text\").remove(),E.attr(\"class\",function(a,b){return q(a,b)<0?\"nv-bar negative\":\"nv-bar positive\"}).style(\"fill\",function(a,b){return a.color||s(a,b)}).style(\"stroke\",function(a,b){return a.color||s(a,b)}).select(\"rect\").attr(\"class\",w).watchTransition(y,\"discreteBar: bars rect\").attr(\"width\",.9*n.rangeBand()/b.length),\ \"translate(\"+j.left+\",\"+j.top+\")\");var D=A.select(\".nv-groups\").selectAll(\".nv-group\").data(function(a){return a},function(a){return a.key});D.enter().append(\"g\").style(\"stroke-opacity\",1e-6).style(\"fill-opacity\",1e-6),D.exit().watchTransition(y,\"discreteBar: exit groups\").style(\"stroke-opacity\",1e-6).style(\"fill-opacity\",1e-6).remove(),D.attr(\"class\",function(a,b){return\"nv-group nv-series-\"+b}).classed(\"hover\",function(a){return a.hover}),D.watchTransition(y,\"discreteBar: groups\").style(\"stroke-opacity\",1).style(\"fill-opacity\",.75);var E=D.selectAll(\"g.nv-bar\").data(function(a){return a.values});E.exit().remove();var F=E.enter().append(\"g\").attr(\"transform\",function(a,b,c){return\"translate(\"+(n(p(a,b))+.05*n.rangeBand())+\", \"+o(0)+\")\"}).on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"mousemove\",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style(\"fill\")})}).on(\"click\",function(a,b){var c=this;v.elementClick({data:a,index:b,color:d3.select(this).style(\"fill\"),event:d3.event,element:c}),d3.event.stopPropagation()}).on(\"dblclick\",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style(\"fill\")}),d3.event.stopPropagation()});F.append(\"rect\").attr(\"height\",0).attr(\"width\",.9*n.rangeBand()/b.length),t?(F.append(\"text\").attr(\"text-anchor\",\"middle\"),E.select(\"text\").text(function(a,b){return u(q(a,b))}).watchTransition(y,\"discreteBar: bars text\").attr(\"x\",.9*n.rangeBand()/2).attr(\"y\",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll(\"text\").remove(),E.attr(\"class\",function(a,b){return q(a,b)<0?\"nv-bar negative\":\"nv-bar positive\"}).style(\"fill\",function(a,b){return a.color||s(a,b)}).style(\"stroke\",function(a,b){return a.color||s(a,b)}).select(\"rect\").attr(\"class\",w).watchTransition(y,\"discreteBar: bars rect\").attr(\"width\",.9*n.rangeBand()/b.length),\
@@ -833,9 +827,11 @@ K.select(\".nv-legendWrap\").attr(\"transform\",\"translate(0,\"+-l.top+\")\")))
i.tooltip.valueFormatter(i.tooltip.valueFormatter()||s).data({value:b.x()(f,h),index:h,series:m})(),i.renderGuideLine(l)}),i.dispatch.on(\"elementClick\",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if(\"undefined\"!=typeof h){\"undefined\"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on(\"elementMouseout\",function(a){e.clearHighlights()}),A.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),b.update()})}),C.renderEnd(\"lineChart immediate\"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k=a.models.focus(a.models.line()),l={top:30,right:20,bottom:50,left:60},m=null,n=a.utils.defaultColor(),o=null,p=null,q=!0,r=\"top\",s=!0,t=!0,u=!1,v=!1,w=!1,x=a.utils.state(),y=null,z=null,A=d3.dispatch(\"tooltipShow\",\"tooltipHide\",\"stateChange\",\"changeState\",\"renderEnd\"),B=250;f.orient(\"bottom\").tickPadding(7),g.orient(u?\"right\":\"left\"),e.clipEdge(!0).duration(0),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.tooltip.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var C=a.utils.renderWatch(A,B),D=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},E=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on(\"elementMouseover.tooltip\",function(a){a.series.disableTooltip||j.data(a).hidden(!1)}),e.dispatch.on(\"elementMouseout.tooltip\",function(a){j.hidden(!0)}),b.dispatch=A,b.lines=e,b.legend=h,b.focus=k,b.xAxis=f,b.x2Axis=k.xAxis,b.yAxis=g,b.y2Axis=k.yAxis,\ i.tooltip.valueFormatter(i.tooltip.valueFormatter()||s).data({value:b.x()(f,h),index:h,series:m})(),i.renderGuideLine(l)}),i.dispatch.on(\"elementClick\",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if(\"undefined\"!=typeof h){\"undefined\"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on(\"elementMouseout\",function(a){e.clearHighlights()}),A.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),b.update()})}),C.renderEnd(\"lineChart immediate\"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k=a.models.focus(a.models.line()),l={top:30,right:20,bottom:50,left:60},m=null,n=a.utils.defaultColor(),o=null,p=null,q=!0,r=\"top\",s=!0,t=!0,u=!1,v=!1,w=!1,x=a.utils.state(),y=null,z=null,A=d3.dispatch(\"tooltipShow\",\"tooltipHide\",\"stateChange\",\"changeState\",\"renderEnd\"),B=250;f.orient(\"bottom\").tickPadding(7),g.orient(u?\"right\":\"left\"),e.clipEdge(!0).duration(0),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.tooltip.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var C=a.utils.renderWatch(A,B),D=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},E=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on(\"elementMouseover.tooltip\",function(a){a.series.disableTooltip||j.data(a).hidden(!1)}),e.dispatch.on(\"elementMouseout.tooltip\",function(a){j.hidden(!0)}),b.dispatch=A,b.lines=e,b.legend=h,b.focus=k,b.xAxis=f,b.x2Axis=k.xAxis,b.yAxis=g,b.y2Axis=k.yAxis,\
b.interactiveLayer=i,b.tooltip=j,b.state=x,b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return q},set:function(a){q=a}},legendPosition:{get:function(){return r},set:function(a){r=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},focusEnable:{get:function(){return w},set:function(a){w=a}},focusHeight:{get:function(){return k.height()},set:function(a){k.height(a)}},focusShowAxisX:{get:function(){return k.showXAxis()},set:function(a){k.showXAxis(a)}},focusShowAxisY:{get:function(){return k.showYAxis()},set:function(a){k.showYAxis(a)}},brushExtent:{get:function(){return k.brushExtent()},set:function(a){k.brushExtent(a)}},focusMargin:{get:function(){return k.margin},set:function(a){void 0!==a.top&&(l.top=a.top,m=a.top),k.margin.right=void 0!==a.right?a.right:k.margin.right,k.margin.bottom=void 0!==a.bottom?a.bottom:k.margin.bottom,k.margin.left=void 0!==a.left?a.left:k.margin.left}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return B},set:function(a){B=a,C.reset(B),e.duration(B),k.duration(B),f.duration(B),g.duration(B)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n),e.color(n),k.color(n)}},interpolate:{get:function(){return e.interpolate()},set:function(a){e.interpolate(a),k.interpolate(a)}},xTickFormat:{get:function(){return f.tickFormat()},set:function(a){f.tickFormat(a),k.xTickFormat(a)}},yTickFormat:{get:function(){return g.tickFormat()},set:function(a){g.tickFormat(a),k.yTickFormat(a)}},x:{get:function(){return e.x()},set:function(a){e.x(a),k.x(a)}},\ b.interactiveLayer=i,b.tooltip=j,b.state=x,b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return q},set:function(a){q=a}},legendPosition:{get:function(){return r},set:function(a){r=a}},showXAxis:{get:function(){return s},set:function(a){s=a}},showYAxis:{get:function(){return t},set:function(a){t=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},focusEnable:{get:function(){return w},set:function(a){w=a}},focusHeight:{get:function(){return k.height()},set:function(a){k.height(a)}},focusShowAxisX:{get:function(){return k.showXAxis()},set:function(a){k.showXAxis(a)}},focusShowAxisY:{get:function(){return k.showYAxis()},set:function(a){k.showYAxis(a)}},brushExtent:{get:function(){return k.brushExtent()},set:function(a){k.brushExtent(a)}},focusMargin:{get:function(){return k.margin},set:function(a){void 0!==a.top&&(l.top=a.top,m=a.top),k.margin.right=void 0!==a.right?a.right:k.margin.right,k.margin.bottom=void 0!==a.bottom?a.bottom:k.margin.bottom,k.margin.left=void 0!==a.left?a.left:k.margin.left}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return B},set:function(a){B=a,C.reset(B),e.duration(B),k.duration(B),f.duration(B),g.duration(B)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n),e.color(n),k.color(n)}},interpolate:{get:function(){return e.interpolate()},set:function(a){e.interpolate(a),k.interpolate(a)}},xTickFormat:{get:function(){return f.tickFormat()},set:function(a){f.tickFormat(a),k.xTickFormat(a)}},yTickFormat:{get:function(){return g.tickFormat()},set:function(a){g.tickFormat(a),k.yTickFormat(a)}},x:{get:function(){return e.x()},set:function(a){e.x(a),k.x(a)}},\
y:{get:function(){return e.y()},set:function(a){e.y(a),k.y(a)}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,g.orient(u?\"right\":\"left\")}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,v&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){return a.models.lineChart().margin({bottom:30}).focusEnable(!0)},a.models.linePlusBarChart=function(){\"use strict\";function b(v){return v.each(function(v){function K(a){var b=+(\"e\"==a),c=b?1:-1,d=$/3;return\"M\"+.5*c+\",\"+d+\"A6,6 0 0 \"+b+\" \"+6.5*c+\",\"+(d+6)+\"V\"+(2*d-6)+\"A6,6 0 0 \"+b+\" \"+.5*c+\",\"+2*d+\"ZM\"+2.5*c+\",\"+(d+8)+\"V\"+(2*d-8)+\"M\"+4.5*c+\",\"+(d+8)+\"V\"+(2*d-8)}function S(){u.empty()||u.extent(J),na.data([u.empty()?e.domain():J]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(\".left\").attr(\"width\",0>c?0:c),d3.select(this).select(\".right\").attr(\"x\",e(a[1])).attr(\"width\",0>d?0:d)})}function T(){J=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),L.brush({extent:c,brush:u}),S(),l.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=ga.select(\".nv-focus .nv-barsWrap\").datum(aa.length?aa.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=ga.select(\".nv-focus .nv-linesWrap\").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}).map(function(a,b){return{area:a.area,fillOpacity:a.fillOpacity,strokeWidth:a.strokeWidth,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=aa.length&&!R?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-Z,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),ga.select(\".nv-x.nv-axis\").transition().duration(M).call(n),b.transition().duration(M).call(l),\ y:{get:function(){return e.y()},set:function(a){e.y(a),k.y(a)}},rightAlignYAxis:{get:function(){return u},set:function(a){u=a,g.orient(u?\"right\":\"left\")}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,v&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){return a.models.lineChart().margin({bottom:30}).focusEnable(!0)},a.models.linePlusBarChart=function(){\"use strict\";function b(v){return v.each(function(v){function K(a){var b=+(\"e\"==a),c=b?1:-1,d=$/3;return\"M\"+.5*c+\",\"+d+\"A6,6 0 0 \"+b+\" \"+6.5*c+\",\"+(d+6)+\"V\"+(2*d-6)+\"A6,6 0 0 \"+b+\" \"+.5*c+\",\"+2*d+\"ZM\"+2.5*c+\",\"+(d+8)+\"V\"+(2*d-8)+\"M\"+4.5*c+\",\"+(d+8)+\"V\"+(2*d-8)}function S(){u.empty()||u.extent(J),na.data([u.empty()?e.domain():J]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(\".left\").attr(\"width\",0>c?0:c),d3.select(this).select(\".right\").attr(\"x\",e(a[1])).attr(\"width\",0>d?0:d)})}function T(){J=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),L.brush({extent:c,brush:u}),S(),l.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(Y).height(Z).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=ga.select(\".nv-focus .nv-barsWrap\").datum(aa.length?aa.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=ga.select(\".nv-focus .nv-linesWrap\").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}).map(function(a,b){return{area:a.area,fillOpacity:a.fillOpacity,strokeWidth:a.strokeWidth,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=aa.length&&!R?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-Z,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),ga.select(\".nv-x.nv-axis\").transition().duration(M).call(n),b.transition().duration(M).call(l),\
") "
)
file(APPEND "${METABENCH_DIR}/nvd3.js" "\ file(APPEND "${METABENCH_DIR}/nvd3.js"
"\
h.transition().duration(M).call(j),ga.select(\".nv-focus .nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+f.range()[0]+\")\"),p.scale(f)._ticks(a.utils.calcTicksY(Z/36,v)).tickSize(-Y,0),q.scale(g)._ticks(a.utils.calcTicksY(Z/36,v)),R?q.tickSize(ba.length?0:-Y,0):q.tickSize(aa.length?0:-Y,0);var i=aa.length?1:0,k=ba.length&&!W(ba)?1:0,m=R?k:i,o=R?i:k;ga.select(\".nv-focus .nv-y1.nv-axis\").style(\"opacity\",m),ga.select(\".nv-focus .nv-y2.nv-axis\").style(\"opacity\",o).attr(\"transform\",\"translate(\"+d.range()[1]+\",0)\"),ga.select(\".nv-focus .nv-y1.nv-axis\").transition().duration(M).call(p),ga.select(\".nv-focus .nv-y2.nv-axis\").transition().duration(M).call(q)}var X=d3.select(this);a.utils.initSVG(X);var Y=a.utils.availableWidth(z,X,w),Z=a.utils.availableHeight(A,X,w)-(F?I:0),$=I-y.top-y.bottom;if(b.update=function(){X.transition().duration(M).call(b)},b.container=this,N.setter(V(v),b.update).getter(U(v)).update(),N.disabled=v.map(function(a){return!!a.disabled}),!O){var _;O={};for(_ in N)N[_]instanceof Array?O[_]=N[_].slice(0):O[_]=N[_]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,X),b;X.selectAll(\".nv-noData\").remove();var aa=v.filter(function(a){return!a.disabled&&a.bar}),ba=v.filter(function(a){return!a.bar});d=aa.length&&!R?l.xScale():j.xScale(),e=o.scale(),f=R?j.yScale():l.yScale(),g=R?l.yScale():j.yScale(),h=R?k.yScale():m.yScale(),i=R?m.yScale():k.yScale();var ca=v.filter(function(a){return!a.disabled&&(R?!a.bar:a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})}),da=v.filter(function(a){return!a.disabled&&(R?a.bar:!a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})});d.range([0,Y]),e.domain(d3.extent(d3.merge(ca.concat(da)),function(a){return a.x})).range([0,Y]);var ea=X.selectAll(\"g.nv-wrap.nv-linePlusBar\").data([v]),fa=ea.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-linePlusBar\").append(\"g\"),ga=ea.select(\"g\");fa.append(\"g\").attr(\"class\",\"nv-legendWrap\");var ha=fa.append(\"g\").attr(\"class\",\"nv-focus\");\ h.transition().duration(M).call(j),ga.select(\".nv-focus .nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+f.range()[0]+\")\"),p.scale(f)._ticks(a.utils.calcTicksY(Z/36,v)).tickSize(-Y,0),q.scale(g)._ticks(a.utils.calcTicksY(Z/36,v)),R?q.tickSize(ba.length?0:-Y,0):q.tickSize(aa.length?0:-Y,0);var i=aa.length?1:0,k=ba.length&&!W(ba)?1:0,m=R?k:i,o=R?i:k;ga.select(\".nv-focus .nv-y1.nv-axis\").style(\"opacity\",m),ga.select(\".nv-focus .nv-y2.nv-axis\").style(\"opacity\",o).attr(\"transform\",\"translate(\"+d.range()[1]+\",0)\"),ga.select(\".nv-focus .nv-y1.nv-axis\").transition().duration(M).call(p),ga.select(\".nv-focus .nv-y2.nv-axis\").transition().duration(M).call(q)}var X=d3.select(this);a.utils.initSVG(X);var Y=a.utils.availableWidth(z,X,w),Z=a.utils.availableHeight(A,X,w)-(F?I:0),$=I-y.top-y.bottom;if(b.update=function(){X.transition().duration(M).call(b)},b.container=this,N.setter(V(v),b.update).getter(U(v)).update(),N.disabled=v.map(function(a){return!!a.disabled}),!O){var _;O={};for(_ in N)N[_]instanceof Array?O[_]=N[_].slice(0):O[_]=N[_]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,X),b;X.selectAll(\".nv-noData\").remove();var aa=v.filter(function(a){return!a.disabled&&a.bar}),ba=v.filter(function(a){return!a.bar});d=aa.length&&!R?l.xScale():j.xScale(),e=o.scale(),f=R?j.yScale():l.yScale(),g=R?l.yScale():j.yScale(),h=R?k.yScale():m.yScale(),i=R?m.yScale():k.yScale();var ca=v.filter(function(a){return!a.disabled&&(R?!a.bar:a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})}),da=v.filter(function(a){return!a.disabled&&(R?a.bar:!a.bar)}).map(function(a){return a.values.map(function(a,b){return{x:B(a,b),y:C(a,b)}})});d.range([0,Y]),e.domain(d3.extent(d3.merge(ca.concat(da)),function(a){return a.x})).range([0,Y]);var ea=X.selectAll(\"g.nv-wrap.nv-linePlusBar\").data([v]),fa=ea.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-linePlusBar\").append(\"g\"),ga=ea.select(\"g\");fa.append(\"g\").attr(\"class\",\"nv-legendWrap\");var ha=fa.append(\"g\").attr(\"class\",\"nv-focus\");\
ha.append(\"g\").attr(\"class\",\"nv-x nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-y1 nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-y2 nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-barsWrap\"),ha.append(\"g\").attr(\"class\",\"nv-linesWrap\");var ia=fa.append(\"g\").attr(\"class\",\"nv-context\");if(ia.append(\"g\").attr(\"class\",\"nv-x nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-y1 nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-y2 nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-barsWrap\"),ia.append(\"g\").attr(\"class\",\"nv-linesWrap\"),ia.append(\"g\").attr(\"class\",\"nv-brushBackground\"),ia.append(\"g\").attr(\"class\",\"nv-x nv-brush\"),E){var ja=t.align()?Y/2:Y,ka=t.align()?ja:0;t.width(ja),ga.select(\".nv-legendWrap\").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,R?a.key=a.originalKey+(a.bar?Q:P):a.key=a.originalKey+(a.bar?P:Q),a})).call(t),x||t.height()===w.top||(w.top=t.height(),Z=a.utils.availableHeight(A,X,w)-I),ga.select(\".nv-legendWrap\").attr(\"transform\",\"translate(\"+ka+\",\"+-w.top+\")\")}else ga.select(\".nv-legendWrap\").selectAll(\"*\").remove();ea.attr(\"transform\",\"translate(\"+w.left+\",\"+w.top+\")\"),ga.select(\".nv-context\").style(\"display\",F?\"initial\":\"none\"),m.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var la=ga.select(\".nv-context .nv-barsWrap\").datum(aa.length?aa:[{values:[]}]),ma=ga.select(\".nv-context .nv-linesWrap\").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}));ga.select(\".nv-context\").attr(\"transform\",\"translate(0,\"+(Z+w.bottom+y.top)+\")\"),la.transition().call(m),ma.transition().call(k),H&&(o._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-$,0),ga.select(\".nv-context .nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+h.range()[0]+\")\"),ga.select(\".nv-context .nv-x.nv-axis\").transition().call(o)),G&&(r.scale(h)._ticks($/36).tickSize(-Y,0),s.scale(i)._ticks($/36).tickSize(aa.length?0:-Y,0),ga.select(\".nv-context \ ha.append(\"g\").attr(\"class\",\"nv-x nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-y1 nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-y2 nv-axis\"),ha.append(\"g\").attr(\"class\",\"nv-barsWrap\"),ha.append(\"g\").attr(\"class\",\"nv-linesWrap\");var ia=fa.append(\"g\").attr(\"class\",\"nv-context\");if(ia.append(\"g\").attr(\"class\",\"nv-x nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-y1 nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-y2 nv-axis\"),ia.append(\"g\").attr(\"class\",\"nv-barsWrap\"),ia.append(\"g\").attr(\"class\",\"nv-linesWrap\"),ia.append(\"g\").attr(\"class\",\"nv-brushBackground\"),ia.append(\"g\").attr(\"class\",\"nv-x nv-brush\"),E){var ja=t.align()?Y/2:Y,ka=t.align()?ja:0;t.width(ja),ga.select(\".nv-legendWrap\").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,R?a.key=a.originalKey+(a.bar?Q:P):a.key=a.originalKey+(a.bar?P:Q),a})).call(t),x||t.height()===w.top||(w.top=t.height(),Z=a.utils.availableHeight(A,X,w)-I),ga.select(\".nv-legendWrap\").attr(\"transform\",\"translate(\"+ka+\",\"+-w.top+\")\")}else ga.select(\".nv-legendWrap\").selectAll(\"*\").remove();ea.attr(\"transform\",\"translate(\"+w.left+\",\"+w.top+\")\"),ga.select(\".nv-context\").style(\"display\",F?\"initial\":\"none\"),m.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(Y).height($).color(v.map(function(a,b){return a.color||D(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var la=ga.select(\".nv-context .nv-barsWrap\").datum(aa.length?aa:[{values:[]}]),ma=ga.select(\".nv-context .nv-linesWrap\").datum(W(ba)?[{values:[]}]:ba.filter(function(a){return!a.disabled}));ga.select(\".nv-context\").attr(\"transform\",\"translate(0,\"+(Z+w.bottom+y.top)+\")\"),la.transition().call(m),ma.transition().call(k),H&&(o._ticks(a.utils.calcTicksX(Y/100,v)).tickSize(-$,0),ga.select(\".nv-context .nv-x.nv-axis\").attr(\"transform\",\"translate(0,\"+h.range()[0]+\")\"),ga.select(\".nv-context .nv-x.nv-axis\").transition().call(o)),G&&(r.scale(h)._ticks($/36).tickSize(-Y,0),s.scale(i)._ticks($/36).tickSize(aa.length?0:-Y,0),ga.select(\".nv-context \
.nv-y3.nv-axis\").style(\"opacity\",aa.length?1:0).attr(\"transform\",\"translate(0,\"+e.range()[0]+\")\"),ga.select(\".nv-context .nv-y2.nv-axis\").style(\"opacity\",ba.length?1:0).attr(\"transform\",\"translate(\"+e.range()[1]+\",0)\"),ga.select(\".nv-context .nv-y1.nv-axis\").transition().call(r),ga.select(\".nv-context .nv-y2.nv-axis\").transition().call(s)),u.x(e).on(\"brush\",T),J&&u.extent(J);var na=ga.select(\".nv-brushBackground\").selectAll(\"g\").data([J||u.extent()]),oa=na.enter().append(\"g\");oa.append(\"rect\").attr(\"class\",\"left\").attr(\"x\",0).attr(\"y\",0).attr(\"height\",$),oa.append(\"rect\").attr(\"class\",\"right\").attr(\"x\",0).attr(\"y\",0).attr(\"height\",$);var pa=ga.select(\".nv-x.nv-brush\").call(u);pa.selectAll(\"rect\").attr(\"height\",$),pa.selectAll(\".resize\").append(\"path\").attr(\"d\",K),t.dispatch.on(\"stateChange\",function(a){for(var c in a)N[c]=a[c];L.stateChange(N),b.update()}),L.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),N.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x=null,y={top:0,right:30,bottom:20,left:60},z=null,A=null,B=function(a){return a.x},C=function(a){return a.y},D=a.utils.defaultColor(),E=!0,F=!0,G=!1,H=!0,I=50,J=null,K=null,L=d3.dispatch(\"brush\",\"stateChange\",\"changeState\"),M=0,N=a.utils.state(),O=null,P=\" (left axis)\",Q=\" (right axis)\",R=!1;j.clipEdge(!0),k.interactive(!1),k.pointActive(function(a){return!1}),n.orient(\"bottom\").tickPadding(5),p.orient(\"left\"),q.orient(\"right\"),o.orient(\"bottom\").tickPadding(5),r.orient(\"left\"),s.orient(\"right\"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var S=function(){return R?{main:q,focus:s}:{main:p,focus:r}},T=function(){return R?{main:p,focus:r}:{main:q,focus:s}},U=function(a){return \ .nv-y3.nv-axis\").style(\"opacity\",aa.length?1:0).attr(\"transform\",\"translate(0,\"+e.range()[0]+\")\"),ga.select(\".nv-context .nv-y2.nv-axis\").style(\"opacity\",ba.length?1:0).attr(\"transform\",\"translate(\"+e.range()[1]+\",0)\"),ga.select(\".nv-context .nv-y1.nv-axis\").transition().call(r),ga.select(\".nv-context .nv-y2.nv-axis\").transition().call(s)),u.x(e).on(\"brush\",T),J&&u.extent(J);var na=ga.select(\".nv-brushBackground\").selectAll(\"g\").data([J||u.extent()]),oa=na.enter().append(\"g\");oa.append(\"rect\").attr(\"class\",\"left\").attr(\"x\",0).attr(\"y\",0).attr(\"height\",$),oa.append(\"rect\").attr(\"class\",\"right\").attr(\"x\",0).attr(\"y\",0).attr(\"height\",$);var pa=ga.select(\".nv-x.nv-brush\").call(u);pa.selectAll(\"rect\").attr(\"height\",$),pa.selectAll(\".resize\").append(\"path\").attr(\"d\",K),t.dispatch.on(\"stateChange\",function(a){for(var c in a)N[c]=a[c];L.stateChange(N),b.update()}),L.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),N.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x=null,y={top:0,right:30,bottom:20,left:60},z=null,A=null,B=function(a){return a.x},C=function(a){return a.y},D=a.utils.defaultColor(),E=!0,F=!0,G=!1,H=!0,I=50,J=null,K=null,L=d3.dispatch(\"brush\",\"stateChange\",\"changeState\"),M=0,N=a.utils.state(),O=null,P=\" (left axis)\",Q=\" (right axis)\",R=!1;j.clipEdge(!0),k.interactive(!1),k.pointActive(function(a){return!1}),n.orient(\"bottom\").tickPadding(5),p.orient(\"left\"),q.orient(\"right\"),o.orient(\"bottom\").tickPadding(5),r.orient(\"left\"),s.orient(\"right\"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var S=function(){return R?{main:q,focus:s}:{main:p,focus:r}},T=function(){return R?{main:p,focus:r}:{main:q,focus:s}},U=function(a){return \
@@ -866,9 +862,11 @@ D=C.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-ohlcBar\"),E=D.append
d[1]]);l[b.key].brush.y(f),v.push(b.key)}if(isNaN(a.values[b.key])||isNaN(parseFloat(a.values[b.key])))return[k(b.key),l[b.key](e)]}return void 0!==U&&(v.length>0||O?(U.style(\"display\",\"inline\"),V.style(\"display\",\"inline\")):(U.style(\"display\",\"none\"),V.style(\"display\",\"none\"))),[k(b.key),l[b.key](a.values[b.key])]}))}function B(a){s.forEach(function(b){var c=l[b.dimension].brush.y().domain();b.hasOnlyNaN&&(b.extent[1]=(l[b.dimension].domain()[1]-c[0])*(b.extent[1]-b.extent[0])/(N[b.dimension]-b.extent[0])+c[0]),b.hasNaN&&(b.extent[0]=c[0]),a&&l[b.dimension].brush.extent(b.extent)}),e.select(\".nv-brushBackground\").each(function(a){d3.select(this).call(l[a.key].brush)}).selectAll(\"rect\").attr(\"x\",-8).attr(\"width\",16),F()}function C(){q===!1&&(q=!0,B(!0))}function D(){$=p.filter(function(a){return!l[a].brush.empty()}),_=$.map(function(a){return l[a].brush.extent()}),s=[],$.forEach(function(a,b){s[b]={dimension:a,extent:_[b],hasNaN:!1,hasOnlyNaN:!1}}),t=[],c.style(\"display\",function(a){var b=$.every(function(b,c){return(isNaN(a.values[b])||isNaN(parseFloat(a.values[b])))&&_[c][0]==l[b].brush.y().domain()[0]?!0:_[c][0]<=a.values[b]&&a.values[b]<=_[c][1]&&!isNaN(parseFloat(a.values[b]))});return b&&t.push(a),b?null:\"none\"}),F(),z.brush({filters:s,active:t})}function E(){var a=$.length>0?!0:!1;s.forEach(function(a){a.extent[0]===l[a.dimension].brush.y().domain()[0]&&v.indexOf(a.dimension)>=0&&(a.hasNaN=!0),a.extent[1]<l[a.dimension].domain()[0]&&(a.hasOnlyNaN=!0)}),z.brushEnd(t,a)}function F(){e.select(\".nv-axis\").each(function(a,b){var c=s.filter(function(b){return b.dimension==a.key});P[a.key]=l[a.key].domain(),0!=c.length&&q&&(P[a.key]=[],c[0].extent[1]>l[a.key].domain()[0]&&(P[a.key]=[c[0].extent[1]]),c[0].extent[0]>=l[a.key].domain()[0]&&P[a.key].push(c[0].extent[0])),d3.select(this).call(y.scale(l[a.key]).tickFormat(a.format).tickValues(P[a.key]))})}function G(a){u[a.key]=this.parentNode.__origin__=k(a.key),d.attr(\"visibility\",\"hidden\")}function H(a){u[a.key]=Math.min(i,Math.max(0,this.parentNode.__origin__+=d3.event.x)),\ d[1]]);l[b.key].brush.y(f),v.push(b.key)}if(isNaN(a.values[b.key])||isNaN(parseFloat(a.values[b.key])))return[k(b.key),l[b.key](e)]}return void 0!==U&&(v.length>0||O?(U.style(\"display\",\"inline\"),V.style(\"display\",\"inline\")):(U.style(\"display\",\"none\"),V.style(\"display\",\"none\"))),[k(b.key),l[b.key](a.values[b.key])]}))}function B(a){s.forEach(function(b){var c=l[b.dimension].brush.y().domain();b.hasOnlyNaN&&(b.extent[1]=(l[b.dimension].domain()[1]-c[0])*(b.extent[1]-b.extent[0])/(N[b.dimension]-b.extent[0])+c[0]),b.hasNaN&&(b.extent[0]=c[0]),a&&l[b.dimension].brush.extent(b.extent)}),e.select(\".nv-brushBackground\").each(function(a){d3.select(this).call(l[a.key].brush)}).selectAll(\"rect\").attr(\"x\",-8).attr(\"width\",16),F()}function C(){q===!1&&(q=!0,B(!0))}function D(){$=p.filter(function(a){return!l[a].brush.empty()}),_=$.map(function(a){return l[a].brush.extent()}),s=[],$.forEach(function(a,b){s[b]={dimension:a,extent:_[b],hasNaN:!1,hasOnlyNaN:!1}}),t=[],c.style(\"display\",function(a){var b=$.every(function(b,c){return(isNaN(a.values[b])||isNaN(parseFloat(a.values[b])))&&_[c][0]==l[b].brush.y().domain()[0]?!0:_[c][0]<=a.values[b]&&a.values[b]<=_[c][1]&&!isNaN(parseFloat(a.values[b]))});return b&&t.push(a),b?null:\"none\"}),F(),z.brush({filters:s,active:t})}function E(){var a=$.length>0?!0:!1;s.forEach(function(a){a.extent[0]===l[a.dimension].brush.y().domain()[0]&&v.indexOf(a.dimension)>=0&&(a.hasNaN=!0),a.extent[1]<l[a.dimension].domain()[0]&&(a.hasOnlyNaN=!0)}),z.brushEnd(t,a)}function F(){e.select(\".nv-axis\").each(function(a,b){var c=s.filter(function(b){return b.dimension==a.key});P[a.key]=l[a.key].domain(),0!=c.length&&q&&(P[a.key]=[],c[0].extent[1]>l[a.key].domain()[0]&&(P[a.key]=[c[0].extent[1]]),c[0].extent[0]>=l[a.key].domain()[0]&&P[a.key].push(c[0].extent[0])),d3.select(this).call(y.scale(l[a.key]).tickFormat(a.format).tickValues(P[a.key]))})}function G(a){u[a.key]=this.parentNode.__origin__=k(a.key),d.attr(\"visibility\",\"hidden\")}function H(a){u[a.key]=Math.min(i,Math.max(0,this.parentNode.__origin__+=d3.event.x)),\
c.attr(\"d\",A),o.sort(function(a,b){return J(a.key)-J(b.key)}),o.forEach(function(a,b){return a.currentPosition=b}),k.domain(o.map(function(a){return a.key})),e.attr(\"transform\",function(a){return\"translate(\"+J(a.key)+\")\"})}function I(a,b){delete this.parentNode.__origin__,delete u[a.key],d3.select(this.parentNode).attr(\"transform\",\"translate(\"+k(a.key)+\")\"),c.attr(\"d\",A),d.attr(\"d\",A).attr(\"visibility\",null),z.dimensionsOrder(o)}function J(a){var b=u[a];return null==b?k(a):b}var K=d3.select(this);if(i=a.utils.availableWidth(g,K,f),j=a.utils.availableHeight(h,K,f),a.utils.initSVG(K),void 0===b[0].values){var L=[];b.forEach(function(a){var b={},c=Object.keys(a);c.forEach(function(c){\"name\"!==c&&(b[c]=a[c])}),L.push({key:a.name,values:b})}),b=L}var M=b.map(function(a){return a.values});0===t.length&&(t=b),p=n.sort(function(a,b){return a.currentPosition-b.currentPosition}).map(function(a){return a.key}),o=n.filter(function(a){return!a.disabled}),k.rangePoints([0,i],1).domain(o.map(function(a){return a.key}));var N={},O=!1,P=[];p.forEach(function(a){var b=d3.extent(M,function(b){return+b[a]}),c=b[0],d=b[1],e=!1;(isNaN(c)||isNaN(d))&&(e=!0,c=0,d=0),c===d&&(c-=1,d+=1);var f=s.filter(function(b){return b.dimension==a});0!==f.length&&(e?(c=l[a].domain()[0],d=l[a].domain()[1]):!f[0].hasOnlyNaN&&q?(c=c>f[0].extent[0]?f[0].extent[0]:c,d=d<f[0].extent[1]?f[0].extent[1]:d):f[0].hasNaN&&(d=d<f[0].extent[1]?f[0].extent[1]:d,N[a]=l[a].domain()[1],O=!0)),l[a]=d3.scale.linear().domain([c,d]).range([.9*(j-12),0]),v=[],l[a].brush=d3.svg.brush().y(l[a]).on(\"brushstart\",C).on(\"brush\",D).on(\"brushend\",E)});var Q=K.selectAll(\"g.nv-wrap.nv-parallelCoordinates\").data([b]),R=Q.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-parallelCoordinates\"),S=R.append(\"g\"),T=Q.select(\"g\");S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates background\"),S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates foreground\"),S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates missingValuesline\"),Q.attr(\"transform\",\"translate(\"+f.left+\",\"+f.top+\")\"),x.interpolate(\"cardinal\").tension(w),\ c.attr(\"d\",A),o.sort(function(a,b){return J(a.key)-J(b.key)}),o.forEach(function(a,b){return a.currentPosition=b}),k.domain(o.map(function(a){return a.key})),e.attr(\"transform\",function(a){return\"translate(\"+J(a.key)+\")\"})}function I(a,b){delete this.parentNode.__origin__,delete u[a.key],d3.select(this.parentNode).attr(\"transform\",\"translate(\"+k(a.key)+\")\"),c.attr(\"d\",A),d.attr(\"d\",A).attr(\"visibility\",null),z.dimensionsOrder(o)}function J(a){var b=u[a];return null==b?k(a):b}var K=d3.select(this);if(i=a.utils.availableWidth(g,K,f),j=a.utils.availableHeight(h,K,f),a.utils.initSVG(K),void 0===b[0].values){var L=[];b.forEach(function(a){var b={},c=Object.keys(a);c.forEach(function(c){\"name\"!==c&&(b[c]=a[c])}),L.push({key:a.name,values:b})}),b=L}var M=b.map(function(a){return a.values});0===t.length&&(t=b),p=n.sort(function(a,b){return a.currentPosition-b.currentPosition}).map(function(a){return a.key}),o=n.filter(function(a){return!a.disabled}),k.rangePoints([0,i],1).domain(o.map(function(a){return a.key}));var N={},O=!1,P=[];p.forEach(function(a){var b=d3.extent(M,function(b){return+b[a]}),c=b[0],d=b[1],e=!1;(isNaN(c)||isNaN(d))&&(e=!0,c=0,d=0),c===d&&(c-=1,d+=1);var f=s.filter(function(b){return b.dimension==a});0!==f.length&&(e?(c=l[a].domain()[0],d=l[a].domain()[1]):!f[0].hasOnlyNaN&&q?(c=c>f[0].extent[0]?f[0].extent[0]:c,d=d<f[0].extent[1]?f[0].extent[1]:d):f[0].hasNaN&&(d=d<f[0].extent[1]?f[0].extent[1]:d,N[a]=l[a].domain()[1],O=!0)),l[a]=d3.scale.linear().domain([c,d]).range([.9*(j-12),0]),v=[],l[a].brush=d3.svg.brush().y(l[a]).on(\"brushstart\",C).on(\"brush\",D).on(\"brushend\",E)});var Q=K.selectAll(\"g.nv-wrap.nv-parallelCoordinates\").data([b]),R=Q.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-parallelCoordinates\"),S=R.append(\"g\"),T=Q.select(\"g\");S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates background\"),S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates foreground\"),S.append(\"g\").attr(\"class\",\"nv-parallelCoordinates missingValuesline\"),Q.attr(\"transform\",\"translate(\"+f.left+\",\"+f.top+\")\"),x.interpolate(\"cardinal\").tension(w),\
y.orient(\"left\");var U,V,W=d3.behavior.drag().on(\"dragstart\",G).on(\"drag\",H).on(\"dragend\",I),X=k.range()[1]-k.range()[0];if(X=isNaN(X)?k.range()[0]:X,!isNaN(X)){var Y=[0+X/2,j-12,i-X/2,j-12];U=Q.select(\".missingValuesline\").selectAll(\"line\").data([Y]),U.enter().append(\"line\"),U.exit().remove(),U.attr(\"x1\",function(a){return a[0]}).attr(\"y1\",function(a){return a[1]}).attr(\"x2\",function(a){return a[2]}).attr(\"y2\",function(a){return a[3]}),V=Q.select(\".missingValuesline\").selectAll(\"text\").data([m]),V.append(\"text\").data([m]),V.enter().append(\"text\"),V.exit().remove(),V.attr(\"y\",j).attr(\"x\",i-92-X/2).text(function(a){return a})}d=Q.select(\".background\").selectAll(\"path\").data(b),d.enter().append(\"path\"),d.exit().remove(),d.attr(\"d\",A),c=Q.select(\".foreground\").selectAll(\"path\").data(b),c.enter().append(\"path\"),c.exit().remove(),c.attr(\"d\",A).style(\"stroke-width\",function(a,b){return isNaN(a.strokeWidth)&&(a.strokeWidth=1),a.strokeWidth}).attr(\"stroke\",function(a,b){return a.color||r(a,b)}),c.on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0).style(\"stroke-width\",a.strokeWidth+2+\"px\").style(\"stroke-opacity\",1),z.elementMouseover({label:a.name,color:a.color||r(a,b),values:a.values,dimensions:o})}),c.on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1).style(\"stroke-width\",a.strokeWidth+\"px\").style(\"stroke-opacity\",.7),z.elementMouseout({label:a.name,index:b})}),c.on(\"mousemove\",function(a,b){z.elementMousemove()}),c.on(\"click\",function(a){z.elementClick({id:a.id})}),e=T.selectAll(\".dimension\").data(o);var Z=e.enter().append(\"g\").attr(\"class\",\"nv-parallelCoordinates dimension\");e.attr(\"transform\",function(a){return\"translate(\"+k(a.key)+\",0)\"}),Z.append(\"g\").attr(\"class\",\"nv-axis\"),Z.append(\"text\").attr(\"class\",\"nv-label\").style(\"cursor\",\"move\").attr(\"dy\",\"-1em\").attr(\"text-anchor\",\"middle\").on(\"mouseover\",function(a,b){z.elementMouseover({label:a.tooltip||a.key,color:a.color})}).on(\"mouseout\",function(a,b){z.elementMouseout({label:a.tooltip})}).on(\"mousemove\",function(a,b){z.elementMousemove()}).call(W),\ y.orient(\"left\");var U,V,W=d3.behavior.drag().on(\"dragstart\",G).on(\"drag\",H).on(\"dragend\",I),X=k.range()[1]-k.range()[0];if(X=isNaN(X)?k.range()[0]:X,!isNaN(X)){var Y=[0+X/2,j-12,i-X/2,j-12];U=Q.select(\".missingValuesline\").selectAll(\"line\").data([Y]),U.enter().append(\"line\"),U.exit().remove(),U.attr(\"x1\",function(a){return a[0]}).attr(\"y1\",function(a){return a[1]}).attr(\"x2\",function(a){return a[2]}).attr(\"y2\",function(a){return a[3]}),V=Q.select(\".missingValuesline\").selectAll(\"text\").data([m]),V.append(\"text\").data([m]),V.enter().append(\"text\"),V.exit().remove(),V.attr(\"y\",j).attr(\"x\",i-92-X/2).text(function(a){return a})}d=Q.select(\".background\").selectAll(\"path\").data(b),d.enter().append(\"path\"),d.exit().remove(),d.attr(\"d\",A),c=Q.select(\".foreground\").selectAll(\"path\").data(b),c.enter().append(\"path\"),c.exit().remove(),c.attr(\"d\",A).style(\"stroke-width\",function(a,b){return isNaN(a.strokeWidth)&&(a.strokeWidth=1),a.strokeWidth}).attr(\"stroke\",function(a,b){return a.color||r(a,b)}),c.on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0).style(\"stroke-width\",a.strokeWidth+2+\"px\").style(\"stroke-opacity\",1),z.elementMouseover({label:a.name,color:a.color||r(a,b),values:a.values,dimensions:o})}),c.on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1).style(\"stroke-width\",a.strokeWidth+\"px\").style(\"stroke-opacity\",.7),z.elementMouseout({label:a.name,index:b})}),c.on(\"mousemove\",function(a,b){z.elementMousemove()}),c.on(\"click\",function(a){z.elementClick({id:a.id})}),e=T.selectAll(\".dimension\").data(o);var Z=e.enter().append(\"g\").attr(\"class\",\"nv-parallelCoordinates dimension\");e.attr(\"transform\",function(a){return\"translate(\"+k(a.key)+\",0)\"}),Z.append(\"g\").attr(\"class\",\"nv-axis\"),Z.append(\"text\").attr(\"class\",\"nv-label\").style(\"cursor\",\"move\").attr(\"dy\",\"-1em\").attr(\"text-anchor\",\"middle\").on(\"mouseover\",function(a,b){z.elementMouseover({label:a.tooltip||a.key,color:a.color})}).on(\"mouseout\",function(a,b){z.elementMouseout({label:a.tooltip})}).on(\"mousemove\",function(a,b){z.elementMousemove()}).call(W),\
") "
)
file(APPEND "${METABENCH_DIR}/nvd3.js" "\ file(APPEND "${METABENCH_DIR}/nvd3.js"
"\
Z.append(\"g\").attr(\"class\",\"nv-brushBackground\"),e.exit().remove(),e.select(\".nv-label\").text(function(a){return a.key}),B(q);var $=p.filter(function(a){return!l[a].brush.empty()}),_=$.map(function(a){return l[a].brush.extent()}),aa=t.slice(0);t=[],c.style(\"display\",function(a){var b=$.every(function(b,c){return(isNaN(a.values[b])||isNaN(parseFloat(a.values[b])))&&_[c][0]==l[b].brush.y().domain()[0]?!0:_[c][0]<=a.values[b]&&a.values[b]<=_[c][1]&&!isNaN(parseFloat(a.values[b]))});return b&&t.push(a),b?null:\"none\"}),(s.length>0||!a.utils.arrayEquals(t,aa))&&z.activeChanged(t)}),b}var c,d,e,f={top:30,right:0,bottom:10,left:0},g=null,h=null,i=null,j=null,k=d3.scale.ordinal(),l={},m=\"undefined values\",n=[],o=[],p=[],q=!0,r=a.utils.defaultColor(),s=[],t=[],u=[],v=[],w=1,x=d3.svg.line(),y=d3.svg.axis(),z=d3.dispatch(\"brushstart\",\"brush\",\"brushEnd\",\"dimensionsOrder\",\"stateChange\",\"elementClick\",\"elementMouseover\",\"elementMouseout\",\"elementMousemove\",\"renderEnd\",\"activeChanged\"),A=a.utils.renderWatch(z);return b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},dimensionData:{get:function(){return n},set:function(a){n=a}},displayBrush:{get:function(){return q},set:function(a){q=a}},filters:{get:function(){return s},set:function(a){s=a}},active:{get:function(){return t},set:function(a){t=a}},lineTension:{get:function(){return w},set:function(a){w=a}},undefinedValuesLabel:{get:function(){return m},set:function(a){m=a}},dimensions:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated(\"dimensions\",\"use dimensionData instead\"),0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionNames:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated(\"dimensionNames\",\"use dimensionData instead\"),p=[],0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionFormats:{get:function(){return \ Z.append(\"g\").attr(\"class\",\"nv-brushBackground\"),e.exit().remove(),e.select(\".nv-label\").text(function(a){return a.key}),B(q);var $=p.filter(function(a){return!l[a].brush.empty()}),_=$.map(function(a){return l[a].brush.extent()}),aa=t.slice(0);t=[],c.style(\"display\",function(a){var b=$.every(function(b,c){return(isNaN(a.values[b])||isNaN(parseFloat(a.values[b])))&&_[c][0]==l[b].brush.y().domain()[0]?!0:_[c][0]<=a.values[b]&&a.values[b]<=_[c][1]&&!isNaN(parseFloat(a.values[b]))});return b&&t.push(a),b?null:\"none\"}),(s.length>0||!a.utils.arrayEquals(t,aa))&&z.activeChanged(t)}),b}var c,d,e,f={top:30,right:0,bottom:10,left:0},g=null,h=null,i=null,j=null,k=d3.scale.ordinal(),l={},m=\"undefined values\",n=[],o=[],p=[],q=!0,r=a.utils.defaultColor(),s=[],t=[],u=[],v=[],w=1,x=d3.svg.line(),y=d3.svg.axis(),z=d3.dispatch(\"brushstart\",\"brush\",\"brushEnd\",\"dimensionsOrder\",\"stateChange\",\"elementClick\",\"elementMouseover\",\"elementMouseout\",\"elementMousemove\",\"renderEnd\",\"activeChanged\"),A=a.utils.renderWatch(z);return b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},dimensionData:{get:function(){return n},set:function(a){n=a}},displayBrush:{get:function(){return q},set:function(a){q=a}},filters:{get:function(){return s},set:function(a){s=a}},active:{get:function(){return t},set:function(a){t=a}},lineTension:{get:function(){return w},set:function(a){w=a}},undefinedValuesLabel:{get:function(){return m},set:function(a){m=a}},dimensions:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated(\"dimensions\",\"use dimensionData instead\"),0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionNames:{get:function(){return n.map(function(a){return a.key})},set:function(b){a.deprecated(\"dimensionNames\",\"use dimensionData instead\"),p=[],0===n.length?b.forEach(function(a){n.push({key:a})}):b.forEach(function(a,b){n[b].key=a})}},dimensionFormats:{get:function(){return \
n.map(function(a){return a.format})},set:function(b){a.deprecated(\"dimensionFormats\",\"use dimensionData instead\"),0===n.length?b.forEach(function(a){n.push({format:a})}):b.forEach(function(a,b){n[b].format=a})}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},color:{get:function(){return r},set:function(b){r=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinatesChart=function(){\"use strict\";function b(e){return s.reset(),s.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var p=a.utils.availableWidth(h,k,f),q=a.utils.availableHeight(i,k,f);if(b.update=function(){k.call(b)},b.container=this,l.setter(u(m),b.update).getter(t(m)).update(),l.disabled=m.map(function(a){return!!a.disabled}),m=m.map(function(a){return a.disabled=!!a.disabled,a}),m.forEach(function(a,b){a.originalPosition=isNaN(a.originalPosition)?b:a.originalPosition,a.currentPosition=isNaN(a.currentPosition)?b:a.currentPosition}),!o){var s;o={};for(s in l)l[s]instanceof Array?o[s]=l[s].slice(0):o[s]=l[s]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(\".nv-noData\").remove();var v=k.selectAll(\"g.nv-wrap.nv-parallelCoordinatesChart\").data([e]),w=v.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-parallelCoordinatesChart\").append(\"g\"),x=v.select(\"g\");w.append(\"g\").attr(\"class\",\"nv-parallelCoordinatesWrap\"),w.append(\"g\").attr(\"class\",\"nv-legendWrap\"),x.select(\"rect\").attr(\"width\",p).attr(\"height\",q>0?q:0),j?(d.width(p).color(function(a){return\"rgb(188,190,192)\"}),x.select(\".nv-legendWrap\").datum(m.sort(function(a,b){return a.originalPosition-b.originalPosition})).call(d),g||d.height()===f.top||(f.top=d.height(),q=a.utils.availableHeight(i,k,f)),v.select(\".nv-legendWrap\").attr(\"transform\",\"translate( 0 ,\"+-f.top+\")\")):x.select(\".nv-legendWrap\").selectAll(\"*\").remove(),v.attr(\"transform\",\"translate(\"+f.left+\",\"+f.top+\")\"),c.width(p).height(q).dimensionData(m).displayBrush(n);\ n.map(function(a){return a.format})},set:function(b){a.deprecated(\"dimensionFormats\",\"use dimensionData instead\"),0===n.length?b.forEach(function(a){n.push({format:a})}):b.forEach(function(a,b){n[b].format=a})}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},color:{get:function(){return r},set:function(b){r=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinatesChart=function(){\"use strict\";function b(e){return s.reset(),s.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var p=a.utils.availableWidth(h,k,f),q=a.utils.availableHeight(i,k,f);if(b.update=function(){k.call(b)},b.container=this,l.setter(u(m),b.update).getter(t(m)).update(),l.disabled=m.map(function(a){return!!a.disabled}),m=m.map(function(a){return a.disabled=!!a.disabled,a}),m.forEach(function(a,b){a.originalPosition=isNaN(a.originalPosition)?b:a.originalPosition,a.currentPosition=isNaN(a.currentPosition)?b:a.currentPosition}),!o){var s;o={};for(s in l)l[s]instanceof Array?o[s]=l[s].slice(0):o[s]=l[s]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(\".nv-noData\").remove();var v=k.selectAll(\"g.nv-wrap.nv-parallelCoordinatesChart\").data([e]),w=v.enter().append(\"g\").attr(\"class\",\"nvd3 nv-wrap nv-parallelCoordinatesChart\").append(\"g\"),x=v.select(\"g\");w.append(\"g\").attr(\"class\",\"nv-parallelCoordinatesWrap\"),w.append(\"g\").attr(\"class\",\"nv-legendWrap\"),x.select(\"rect\").attr(\"width\",p).attr(\"height\",q>0?q:0),j?(d.width(p).color(function(a){return\"rgb(188,190,192)\"}),x.select(\".nv-legendWrap\").datum(m.sort(function(a,b){return a.originalPosition-b.originalPosition})).call(d),g||d.height()===f.top||(f.top=d.height(),q=a.utils.availableHeight(i,k,f)),v.select(\".nv-legendWrap\").attr(\"transform\",\"translate( 0 ,\"+-f.top+\")\")):x.select(\".nv-legendWrap\").selectAll(\"*\").remove(),v.attr(\"transform\",\"translate(\"+f.left+\",\"+f.top+\")\"),c.width(p).height(q).dimensionData(m).displayBrush(n);\
var y=x.select(\".nv-parallelCoordinatesWrap \").datum(e);y.transition().call(c),c.dispatch.on(\"brushEnd\",function(a,b){b?(n=!0,r.brushEnd(a)):n=!1}),d.dispatch.on(\"stateChange\",function(a){for(var c in a)l[c]=a[c];r.stateChange(l),b.update()}),c.dispatch.on(\"dimensionsOrder\",function(a){m.sort(function(a,b){return a.currentPosition-b.currentPosition});var b=!1;m.forEach(function(a,c){a.currentPosition=c,a.currentPosition!==a.originalPosition&&(b=!0)}),r.dimensionsOrder(m,b)}),r.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(m.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),s.renderEnd(\"parraleleCoordinateChart immediate\"),b}var c=a.models.parallelCoordinates(),d=a.models.legend(),e=a.models.tooltip(),f=(a.models.tooltip(),{top:0,right:0,bottom:0,left:0}),g=null,h=null,i=null,j=!0,k=a.utils.defaultColor(),l=a.utils.state(),m=[],n=!0,o=null,p=null,q=\"undefined\",r=d3.dispatch(\"dimensionsOrder\",\"brushEnd\",\"stateChange\",\"changeState\",\"renderEnd\"),s=a.utils.renderWatch(r),t=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},u=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.contentGenerator(function(a){var b='<table><thead><tr><td class=\"legend-color-guide\"><div style=\"background-color:'+a.color+'\"></div></td><td><strong>'+a.key+\"</strong></td></tr></thead>\";return 0!==a.series.length&&(b+='<tbody><tr><td height =\"10px\"></td></tr>',a.series.forEach(function(a){b=b+'<tr><td class=\"legend-color-guide\"><div style=\"background-color:'+a.color+'\"></div></td><td class=\"key\">'+a.key+'</td><td class=\"value\">'+a.value+\"</td></tr>\"}),b+=\"</tbody>\"),b+=\"</table>\"}),c.dispatch.on(\"elementMouseover.tooltip\",function(a){var b={key:a.label,color:a.color,series:[]};a.values&&(Object.keys(a.values).forEach(function(c){var d=a.dimensions.filter(function(a){return a.key===c})[0];if(d){var e;e=isNaN(a.values[c])||isNaN(parseFloat(a.values[c]))?q:d.format(a.values[c]),b.series.push({idx:d.currentPosition,\ var y=x.select(\".nv-parallelCoordinatesWrap \").datum(e);y.transition().call(c),c.dispatch.on(\"brushEnd\",function(a,b){b?(n=!0,r.brushEnd(a)):n=!1}),d.dispatch.on(\"stateChange\",function(a){for(var c in a)l[c]=a[c];r.stateChange(l),b.update()}),c.dispatch.on(\"dimensionsOrder\",function(a){m.sort(function(a,b){return a.currentPosition-b.currentPosition});var b=!1;m.forEach(function(a,c){a.currentPosition=c,a.currentPosition!==a.originalPosition&&(b=!0)}),r.dimensionsOrder(m,b)}),r.on(\"changeState\",function(a){\"undefined\"!=typeof a.disabled&&(m.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),s.renderEnd(\"parraleleCoordinateChart immediate\"),b}var c=a.models.parallelCoordinates(),d=a.models.legend(),e=a.models.tooltip(),f=(a.models.tooltip(),{top:0,right:0,bottom:0,left:0}),g=null,h=null,i=null,j=!0,k=a.utils.defaultColor(),l=a.utils.state(),m=[],n=!0,o=null,p=null,q=\"undefined\",r=d3.dispatch(\"dimensionsOrder\",\"brushEnd\",\"stateChange\",\"changeState\",\"renderEnd\"),s=a.utils.renderWatch(r),t=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},u=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.contentGenerator(function(a){var b='<table><thead><tr><td class=\"legend-color-guide\"><div style=\"background-color:'+a.color+'\"></div></td><td><strong>'+a.key+\"</strong></td></tr></thead>\";return 0!==a.series.length&&(b+='<tbody><tr><td height =\"10px\"></td></tr>',a.series.forEach(function(a){b=b+'<tr><td class=\"legend-color-guide\"><div style=\"background-color:'+a.color+'\"></div></td><td class=\"key\">'+a.key+'</td><td class=\"value\">'+a.value+\"</td></tr>\"}),b+=\"</tbody>\"),b+=\"</table>\"}),c.dispatch.on(\"elementMouseover.tooltip\",function(a){var b={key:a.label,color:a.color,series:[]};a.values&&(Object.keys(a.values).forEach(function(c){var d=a.dimensions.filter(function(a){return a.key===c})[0];if(d){var e;e=isNaN(a.values[c])||isNaN(parseFloat(a.values[c]))?q:d.format(a.values[c]),b.series.push({idx:d.currentPosition,\
@@ -906,7 +904,8 @@ a.models.sunburst=function(){\"use strict\";function b(a){var b=c(a);return b>90
\"nvd3 nv-wrap nv-sunburst nv-chart-\"+u).attr(\"transform\",\"translate(\"+(m/2+p.left+p.right)+\",\"+(n/2+p.top+p.bottom)+\")\"),v.on(\"click\",function(a,b){E.chartClick({data:a,index:b,pos:d3.event,id:u})}),H.value(t[s]||t.count);var k=H.nodes(f[0]).reverse();i(k);var l=h.selectAll(\".arc-container\").data(k,B),z=l.enter().append(\"g\").attr(\"class\",\"arc-container\");z.append(\"path\").attr(\"d\",J).style(\"fill\",function(a){return a.color?a.color:w(C?(a.children?a:a.parent).name:a.name)}).style(\"stroke\",\"#FFF\").on(\"click\",function(a,b){j(a),E.elementClick({data:a,index:b})}).on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0).style(\"opacity\",.8),E.elementMouseover({data:a,color:d3.select(this).style(\"fill\"),percent:d(a)})}).on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1).style(\"opacity\",1),E.elementMouseout({data:a})}).on(\"mousemove\",function(a,b){E.elementMousemove({data:a})}),l.each(function(a){d3.select(this).select(\"path\").transition().duration(D).attrTween(\"d\",g)}),x&&(l.selectAll(\"text\").remove(),l.append(\"text\").text(function(a){return y(a)}).transition().duration(D).attr(\"opacity\",function(a){return e(a)?1:0}).attr(\"transform\",function(a){var d=this.getBBox().width;if(0===a.depth)return\"rotate(0)translate(\"+d/2*-1+\",0)\";var e=c(a),f=b(a);return 0===f?\"rotate(\"+e+\")translate(\"+(G(a.y)+5)+\",0)\":\"rotate(\"+e+\")translate(\"+(G(a.y)+d+5)+\",0)rotate(\"+f+\")\"})),j(k[k.length-1]),l.exit().transition().duration(D).attr(\"opacity\",0).each(\"end\",function(a){var b=B(a);I[b]=void 0}).remove()}),K.renderEnd(\"sunburst immediate\"),k}var l,m,n,o,p={top:0,right:0,bottom:0,left:0},q=600,r=600,s=\"count\",t={count:function(a){return 1},value:function(a){return a.value||a.size},size:function(a){return a.value||a.size}},u=Math.floor(1e4*Math.random()),v=null,w=a.utils.defaultColor(),x=!1,y=function(a){return\"count\"===s?a.name+\" #\"+a.value:a.name+\" \"+(a.value||a.size)},z=.02,A=function(a,b){return a.name>b.name},B=function(a,b){return a.name},C=!0,D=500,E=d3.dispatch(\"chartClick\",\"elementClick\",\"elementDblClick\",\"elementMousemove\",\ \"nvd3 nv-wrap nv-sunburst nv-chart-\"+u).attr(\"transform\",\"translate(\"+(m/2+p.left+p.right)+\",\"+(n/2+p.top+p.bottom)+\")\"),v.on(\"click\",function(a,b){E.chartClick({data:a,index:b,pos:d3.event,id:u})}),H.value(t[s]||t.count);var k=H.nodes(f[0]).reverse();i(k);var l=h.selectAll(\".arc-container\").data(k,B),z=l.enter().append(\"g\").attr(\"class\",\"arc-container\");z.append(\"path\").attr(\"d\",J).style(\"fill\",function(a){return a.color?a.color:w(C?(a.children?a:a.parent).name:a.name)}).style(\"stroke\",\"#FFF\").on(\"click\",function(a,b){j(a),E.elementClick({data:a,index:b})}).on(\"mouseover\",function(a,b){d3.select(this).classed(\"hover\",!0).style(\"opacity\",.8),E.elementMouseover({data:a,color:d3.select(this).style(\"fill\"),percent:d(a)})}).on(\"mouseout\",function(a,b){d3.select(this).classed(\"hover\",!1).style(\"opacity\",1),E.elementMouseout({data:a})}).on(\"mousemove\",function(a,b){E.elementMousemove({data:a})}),l.each(function(a){d3.select(this).select(\"path\").transition().duration(D).attrTween(\"d\",g)}),x&&(l.selectAll(\"text\").remove(),l.append(\"text\").text(function(a){return y(a)}).transition().duration(D).attr(\"opacity\",function(a){return e(a)?1:0}).attr(\"transform\",function(a){var d=this.getBBox().width;if(0===a.depth)return\"rotate(0)translate(\"+d/2*-1+\",0)\";var e=c(a),f=b(a);return 0===f?\"rotate(\"+e+\")translate(\"+(G(a.y)+5)+\",0)\":\"rotate(\"+e+\")translate(\"+(G(a.y)+d+5)+\",0)rotate(\"+f+\")\"})),j(k[k.length-1]),l.exit().transition().duration(D).attr(\"opacity\",0).each(\"end\",function(a){var b=B(a);I[b]=void 0}).remove()}),K.renderEnd(\"sunburst immediate\"),k}var l,m,n,o,p={top:0,right:0,bottom:0,left:0},q=600,r=600,s=\"count\",t={count:function(a){return 1},value:function(a){return a.value||a.size},size:function(a){return a.value||a.size}},u=Math.floor(1e4*Math.random()),v=null,w=a.utils.defaultColor(),x=!1,y=function(a){return\"count\"===s?a.name+\" #\"+a.value:a.name+\" \"+(a.value||a.size)},z=.02,A=function(a,b){return a.name>b.name},B=function(a,b){return a.name},C=!0,D=500,E=d3.dispatch(\"chartClick\",\"elementClick\",\"elementDblClick\",\"elementMousemove\",\
\"elementMouseover\",\"elementMouseout\",\"renderEnd\"),F=d3.scale.linear().range([0,2*Math.PI]),G=d3.scale.sqrt(),H=d3.layout.partition().sort(A),I={},J=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,G(a.y))}).outerRadius(function(a){return Math.max(0,G(a.y+a.dy))}),K=a.utils.renderWatch(E);return k.dispatch=E,k.options=a.utils.optionsFunc.bind(k),k._options=Object.create({},{width:{get:function(){return q},set:function(a){q=a}},height:{get:function(){return r},set:function(a){r=a}},mode:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return u},set:function(a){u=a}},duration:{get:function(){return D},set:function(a){D=a}},groupColorByParent:{get:function(){return C},set:function(a){C=!!a}},showLabels:{get:function(){return x},set:function(a){x=!!a}},labelFormat:{get:function(){return y},set:function(a){y=a}},labelThreshold:{get:function(){return z},set:function(a){z=a}},sort:{get:function(){return A},set:function(a){A=a}},key:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return p},set:function(a){p.top=void 0!=a.top?a.top:p.top,p.right=void 0!=a.right?a.right:p.right,p.bottom=void 0!=a.bottom?a.bottom:p.bottom,p.left=void 0!=a.left?a.left:p.left}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}}}),a.utils.initOptions(k),k},a.models.sunburstChart=function(){\"use strict\";function b(d){return n.reset(),n.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);return b.update=function(){0===l?h.call(b):h.transition().duration(l).call(b)},b.container=h,d&&d.length?(h.selectAll(\".nv-noData\").remove(),c.width(i).height(j).margin(e),void h.call(c)):(a.utils.noData(b,h),b)}),n.renderEnd(\"sunburstChart immediate\"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),\ \"elementMouseover\",\"elementMouseout\",\"renderEnd\"),F=d3.scale.linear().range([0,2*Math.PI]),G=d3.scale.sqrt(),H=d3.layout.partition().sort(A),I={},J=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,F(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,G(a.y))}).outerRadius(function(a){return Math.max(0,G(a.y+a.dy))}),K=a.utils.renderWatch(E);return k.dispatch=E,k.options=a.utils.optionsFunc.bind(k),k._options=Object.create({},{width:{get:function(){return q},set:function(a){q=a}},height:{get:function(){return r},set:function(a){r=a}},mode:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return u},set:function(a){u=a}},duration:{get:function(){return D},set:function(a){D=a}},groupColorByParent:{get:function(){return C},set:function(a){C=!!a}},showLabels:{get:function(){return x},set:function(a){x=!!a}},labelFormat:{get:function(){return y},set:function(a){y=a}},labelThreshold:{get:function(){return z},set:function(a){z=a}},sort:{get:function(){return A},set:function(a){A=a}},key:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return p},set:function(a){p.top=void 0!=a.top?a.top:p.top,p.right=void 0!=a.right?a.right:p.right,p.bottom=void 0!=a.bottom?a.bottom:p.bottom,p.left=void 0!=a.left?a.left:p.left}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}}}),a.utils.initOptions(k),k},a.models.sunburstChart=function(){\"use strict\";function b(d){return n.reset(),n.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);return b.update=function(){0===l?h.call(b):h.transition().duration(l).call(b)},b.container=h,d&&d.length?(h.selectAll(\".nv-noData\").remove(),c.width(i).height(j).margin(e),void h.call(c)):(a.utils.noData(b,h),b)}),n.renderEnd(\"sunburstChart immediate\"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),\
i=!1,j=(Math.round(1e5*Math.random()),null),k=null,l=250,m=d3.dispatch(\"stateChange\",\"changeState\",\"renderEnd\"),n=a.utils.renderWatch(m);return d.duration(0).headerEnabled(!1).valueFormatter(function(a){return a}),c.dispatch.on(\"elementMouseover.tooltip\",function(a){a.series={key:a.data.name,value:a.data.value||a.data.size,color:a.color,percent:a.percent},i||(delete a.percent,delete a.series.percent),d.data(a).hidden(!1)}),c.dispatch.on(\"elementMouseout.tooltip\",function(a){d.hidden(!0)}),c.dispatch.on(\"elementMousemove.tooltip\",function(a){d()}),b.dispatch=m,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return k},set:function(a){k=a}},defaultState:{get:function(){return j},set:function(a){j=a}},showTooltipPercent:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return l},set:function(a){l=a,n.reset(l),c.duration(l)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left,c.margin(e)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version=\"1.8.5\"}();\ i=!1,j=(Math.round(1e5*Math.random()),null),k=null,l=250,m=d3.dispatch(\"stateChange\",\"changeState\",\"renderEnd\"),n=a.utils.renderWatch(m);return d.duration(0).headerEnabled(!1).valueFormatter(function(a){return a}),c.dispatch.on(\"elementMouseover.tooltip\",function(a){a.series={key:a.data.name,value:a.data.value||a.data.size,color:a.color,percent:a.percent},i||(delete a.percent,delete a.series.percent),d.data(a).hidden(!1)}),c.dispatch.on(\"elementMouseout.tooltip\",function(a){d.hidden(!0)}),c.dispatch.on(\"elementMousemove.tooltip\",function(a){d()}),b.dispatch=m,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return k},set:function(a){k=a}},defaultState:{get:function(){return j},set:function(a){j=a}},showTooltipPercent:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return l},set:function(a){l=a,n.reset(l),c.duration(l)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left,c.margin(e)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version=\"1.8.5\"}();\
") "
)
################################################################################ ################################################################################
# end nvd3.js # end nvd3.js
################################################################################ ################################################################################
@@ -919,7 +918,8 @@ i=!1,j=(Math.round(1e5*Math.random()),null),k=null,l=250,m=d3.dispatch(\"stateCh
# parsing too long strings. # parsing too long strings.
# https://github.com/mbostock/d3 # https://github.com/mbostock/d3
################################################################################ ################################################################################
file(WRITE "${METABENCH_DIR}/d3.js" "\ file(WRITE "${METABENCH_DIR}/d3.js"
"\
!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+=\"\")===bo||n[0]===_o?_o+n:n}function s(n){return(n+=\"\")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,i){var u,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,u=e.indexOf(o)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function S(){ao.event.preventDefault()}function k(){for(var n,t=ao.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ao.event;\ !function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+=\"\")===bo||n[0]===_o?_o+n:n}function s(n){return(n+=\"\")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,i){var u,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,u=e.indexOf(o)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function S(){ao.event.preventDefault()}function k(){for(var n,t=ao.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ao.event;\
i.target=n,ao.event=i,t[i.type].apply(e,r)}finally{ao.event=u}}},t}function E(n){return ko(n,Co),n}function A(n){return\"function\"==typeof n?n:function(){return No(n,this)}}function C(n){return\"function\"==typeof n?n:function(){return Eo(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ao.ns.qualify(n),null==t?n.local?r:e:\"function\"==typeof t?n.local?a:o:n.local?u:i}function L(n){return n.trim().replace(/\\s+/g,\" \")}function q(n){return new RegExp(\"(?:^|\\\\s+)\"+ao.requote(n)+\"(?:\\\\s+|$)\",\"g\")}function T(n){return(n+\"\").trim().split(/^|\\s+/)}function R(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=T(n).map(D);var i=n.length;return\"function\"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute(\"class\")||\"\";r?(t.lastIndex=0,t.test(i)||e.setAttribute(\"class\",L(i+\" \"+n))):e.setAttribute(\"class\",L(i.replace(t,\" \")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:\"function\"==typeof t?u:i}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:\"function\"==typeof t?i:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e===zo&&t.documentElement.namespaceURI===zo?t.createElement(n):t.createElementNS(e,n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return\"function\"==typeof \ i.target=n,ao.event=i,t[i.type].apply(e,r)}finally{ao.event=u}}},t}function E(n){return ko(n,Co),n}function A(n){return\"function\"==typeof n?n:function(){return No(n,this)}}function C(n){return\"function\"==typeof n?n:function(){return Eo(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ao.ns.qualify(n),null==t?n.local?r:e:\"function\"==typeof t?n.local?a:o:n.local?u:i}function L(n){return n.trim().replace(/\\s+/g,\" \")}function q(n){return new RegExp(\"(?:^|\\\\s+)\"+ao.requote(n)+\"(?:\\\\s+|$)\",\"g\")}function T(n){return(n+\"\").trim().split(/^|\\s+/)}function R(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=T(n).map(D);var i=n.length;return\"function\"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute(\"class\")||\"\";r?(t.lastIndex=0,t.test(i)||e.setAttribute(\"class\",L(i+\" \"+n))):e.setAttribute(\"class\",L(i.replace(t,\" \")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:\"function\"==typeof t?u:i}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:\"function\"==typeof t?i:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e===zo&&t.documentElement.namespaceURI===zo?t.createElement(n):t.createElementNS(e,n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return\"function\"==typeof \
n?n:(n=ao.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ao(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t<l;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function i(){var i=l(t,co(arguments));r.call(this),this.addEventListener(n,this[o]=i,i.$=e),i._=t}function u(){var t,e=new RegExp(\"^__on([^.]+)\"+ao.requote(n)+\"$\");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1],i,i.$),delete this[r]}}var o=\"__on\"+n,a=n.indexOf(\".\"),l=$;a>0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=\".dragsuppress-\"+ ++Do,i=\"click\"+r,u=ao.select(t(e)).on(\"touchmove\"+r,S).on(\"dragstart\"+r,S).on(\"selectstart\"+r,S);if(null==Ro&&(Ro=\"onselectstart\"in e?!1:x(e.style,\"userSelect\")),Ro){var o=n(e).style,a=o[Ro];o[Ro]=\"none\"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select(\"body\").append(\"svg\").style({position:\"absolute\",top:0,left:0,margin:0,padding:0,border:\"none\"},\"important\");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,\ n?n:(n=ao.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ao(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t<l;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function i(){var i=l(t,co(arguments));r.call(this),this.addEventListener(n,this[o]=i,i.$=e),i._=t}function u(){var t,e=new RegExp(\"^__on([^.]+)\"+ao.requote(n)+\"$\");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1],i,i.$),delete this[r]}}var o=\"__on\"+n,a=n.indexOf(\".\"),l=$;a>0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=\".dragsuppress-\"+ ++Do,i=\"click\"+r,u=ao.select(t(e)).on(\"touchmove\"+r,S).on(\"dragstart\"+r,S).on(\"selectstart\"+r,S);if(null==Ro&&(Ro=\"onselectstart\"in e?!1:x(e.style,\"userSelect\")),Ro){var o=n(e).style,a=o[Ro];o[Ro]=\"none\"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select(\"body\").append(\"svg\").style({position:\"absolute\",top:0,left:0,margin:0,padding:0,border:\"none\"},\"important\");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,\
@@ -958,9 +958,11 @@ ao={version:\"3.5.17\"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.do
t){var u,o=[],a=n.length,l=-1;if(1===arguments.length)for(;++l<a;)i(u=r(n[l]))&&o.push(u);else for(;++l<a;)i(u=r(t.call(n,n[l],l)))&&o.push(u);return o.length?ao.quantile(o.sort(e),.5):void 0},ao.variance=function(n,t){var e,u,o=n.length,a=0,l=0,c=-1,f=0;if(1===arguments.length)for(;++c<o;)i(e=r(n[c]))&&(u=e-a,a+=u/++f,l+=u*(e-a));else for(;++c<o;)i(e=r(t.call(n,n[c],c)))&&(u=e-a,a+=u/++f,l+=u*(e-a));return f>1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t<e;)for(var i,u=-1,a=r[t]=new Array(i);++u<i;)a[u]=n[u][t];return r},ao.zip=function(){return ao.transpose(arguments)},ao.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ao.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ao.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ao.merge=function(n){for(var t,e,r,i=n.length,u=-1,o=0;++u<i;)o+=n[u].length;for(e=new Array(o);--i>=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error(\"infinite range\");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)<t;)i.push(r/u);return i},ao.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,i=-1,u=n.length;if(1===arguments.length)for(;\ t){var u,o=[],a=n.length,l=-1;if(1===arguments.length)for(;++l<a;)i(u=r(n[l]))&&o.push(u);else for(;++l<a;)i(u=r(t.call(n,n[l],l)))&&o.push(u);return o.length?ao.quantile(o.sort(e),.5):void 0},ao.variance=function(n,t){var e,u,o=n.length,a=0,l=0,c=-1,f=0;if(1===arguments.length)for(;++c<o;)i(e=r(n[c]))&&(u=e-a,a+=u/++f,l+=u*(e-a));else for(;++c<o;)i(e=r(t.call(n,n[c],c)))&&(u=e-a,a+=u/++f,l+=u*(e-a));return f>1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t<e;)for(var i,u=-1,a=r[t]=new Array(i);++u<i;)a[u]=n[u][t];return r},ao.zip=function(){return ao.transpose(arguments)},ao.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ao.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ao.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ao.merge=function(n){for(var t,e,r,i=n.length,u=-1,o=0;++u<i;)o+=n[u].length;for(e=new Array(o);--i>=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error(\"infinite range\");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)<t;)i.push(r/u);return i},ao.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,i=-1,u=n.length;if(1===arguments.length)for(;\
++i<u;)e.set(i,n[i]);else for(;++i<u;)e.set(t.call(n,r=n[i],i),r)}else for(var o in n)e.set(o,n[o]);return e};var bo=\"__proto__\",_o=\"\\x00\";l(c,{has:h,get:function(n){return this._[f(n)]},set:function(n,t){return this._[f(n)]=t},remove:p,keys:g,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:s(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t),this._[t])}}),ao.nest=function(){function n(t,o,a){if(a>=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p<g;)(h=d.get(l=v(f=o[p])))?h.push(f):d.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,a))}):(f={},s=function(e,r){f[e]=n(t,r,a)}),d.forEach(s),f}function t(n,e){if(e>=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+=\"\")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=M(n,t,t[e]);return n};var wo=[\"webkit\",\"ms\",\"moz\",\"Moz\",\"o\",\"O\"];ao.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf(\".\"),r=\"\";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return \ ++i<u;)e.set(i,n[i]);else for(;++i<u;)e.set(t.call(n,r=n[i],i),r)}else for(var o in n)e.set(o,n[o]);return e};var bo=\"__proto__\",_o=\"\\x00\";l(c,{has:h,get:function(n){return this._[f(n)]},set:function(n,t){return this._[f(n)]=t},remove:p,keys:g,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:s(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t),this._[t])}}),ao.nest=function(){function n(t,o,a){if(a>=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p<g;)(h=d.get(l=v(f=o[p])))?h.push(f):d.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,a))}):(f={},s=function(e,r){f[e]=n(t,r,a)}),d.forEach(s),f}function t(n,e){if(e>=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+=\"\")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=M(n,t,t[e]);return n};var wo=[\"webkit\",\"ms\",\"moz\",\"Moz\",\"o\",\"O\"];ao.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf(\".\"),r=\"\";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return \
n.replace(So,\"\\\\$&\")};var So=/[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,\"matchesSelector\")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};\"function\"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o<a;){u.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var l=-1,c=r.length;++l<c;)(i=r[l])?(t.push(e=n.call(i,i.__data__,l,o)),e&&\"__data__\"in i&&(e.__data__=i.__data__)):t.push(null)}return E(u)},Co.selectAll=function(n){var t,e,r=[];n=C(n);for(var i=-1,u=this.length;++i<u;)for(var o=this[i],a=-1,l=o.length;++a<l;)(e=o[a])&&(r.push(t=co(n.call(e,e.__data__,a,i))),t.parentNode=e);return E(r)};var zo=\"http://www.w3.org/1999/xhtml\",Lo={svg:\"http://www.w3.org/2000/svg\",xhtml:zo,xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"};ao.ns={prefix:Lo,qualify:function(n){var t=n.indexOf(\":\"),e=n;return t>=0&&\"xmlns\"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute(\"class\");++i<r;)if(!q(n[i]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Co.style=function(n,e,r){var i=arguments.length;if(3>i){if(\"string\"!=typeof n){2>i&&(e=\"\");\ n.replace(So,\"\\\\$&\")};var So=/[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,\"matchesSelector\")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};\"function\"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o<a;){u.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var l=-1,c=r.length;++l<c;)(i=r[l])?(t.push(e=n.call(i,i.__data__,l,o)),e&&\"__data__\"in i&&(e.__data__=i.__data__)):t.push(null)}return E(u)},Co.selectAll=function(n){var t,e,r=[];n=C(n);for(var i=-1,u=this.length;++i<u;)for(var o=this[i],a=-1,l=o.length;++a<l;)(e=o[a])&&(r.push(t=co(n.call(e,e.__data__,a,i))),t.parentNode=e);return E(r)};var zo=\"http://www.w3.org/1999/xhtml\",Lo={svg:\"http://www.w3.org/2000/svg\",xhtml:zo,xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"};ao.ns={prefix:Lo,qualify:function(n){var t=n.indexOf(\":\"),e=n;return t>=0&&\"xmlns\"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if(\"string\"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute(\"class\");++i<r;)if(!q(n[i]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Co.style=function(n,e,r){var i=arguments.length;if(3>i){if(\"string\"!=typeof n){2>i&&(e=\"\");\
") "
)
file(APPEND "${METABENCH_DIR}/d3.js" "\ file(APPEND "${METABENCH_DIR}/d3.js"
"\
for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=\"\"}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if(\"string\"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?\"\":t}:null==n?function(){this.textContent=\"\"}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?\"\":t}:null==n?function(){this.innerHTML=\"\"}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++r<o;)(i=n[r])&&(y.has(d=t.call(i,i.__data__,r))?v[r]=i:y.set(d,i),m[r]=d);for(r=-1;++r<s;)(i=y.get(d=t.call(e,u=e[r],r)))?i!==!0&&(p[r]=i,i.__data__=u):g[r]=H(u),y.set(d,!0);for(r=-1;++r<o;)r in m&&y.get(m[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],u=e[r],i?(i.__data__=u,p[r]=i):g[r]=H(u);for(;s>r;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++u<o;)(i=r[u])&&(n[u]=i.__data__);return n}var a=Z([]),l=E([]),f=E([]);if(\"function\"==typeof n)for(;++u<o;)e(r=this[u],n.call(r,r.parentNode.__data__,u));else for(;++u<o;)e(r=this[u],n);return l.enter=function(){return a},l.exit=function(){return \ for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=\"\"}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if(\"string\"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?\"\":t}:null==n?function(){this.textContent=\"\"}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each(\"function\"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?\"\":t}:null==n?function(){this.innerHTML=\"\"}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++r<o;)(i=n[r])&&(y.has(d=t.call(i,i.__data__,r))?v[r]=i:y.set(d,i),m[r]=d);for(r=-1;++r<s;)(i=y.get(d=t.call(e,u=e[r],r)))?i!==!0&&(p[r]=i,i.__data__=u):g[r]=H(u),y.set(d,!0);for(r=-1;++r<o;)r in m&&y.get(m[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],u=e[r],i?(i.__data__=u,p[r]=i):g[r]=H(u);for(;s>r;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++u<o;)(i=r[u])&&(n[u]=i.__data__);return n}var a=Z([]),l=E([]),f=E([]);if(\"function\"==typeof n)for(;++u<o;)e(r=this[u],n.call(r,r.parentNode.__data__,u));else for(;++u<o;)e(r=this[u],n);return l.enter=function(){return a},l.exit=function(){return \
f},l},Co.datum=function(n){return arguments.length?this.property(\"__data__\",n):this.property(\"__data__\")},Co.filter=function(n){var t,e,r,i=[];\"function\"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Co.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Co.call=function(n){var t=co(arguments);return n.apply(t[0]=this,t),this},Co.empty=function(){return!this.node()},Co.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++a<l;){r=(i=this[a]).update,o.push(t=[]),t.parentNode=i.parentNode;for(var c=-1,f=i.length;++c<f;)(u=i[c])?(t.push(r[c]=e=n.call(i.parentNode,u.__data__,c,a)),e.__data__=u.__data__):t.push(null)}return E(o)},qo.insert=function(n,t){return arguments.length<2&&(t=V(this)),Co.insert.call(this,n,t)},ao.select=function(t){var e;return\"string\"==typeof t?(e=[No(t,fo)],e.parentNode=fo.documentElement):(e=[t],e.parentNode=n(t)),E([e])},ao.selectAll=function(n){var t;return\"string\"==typeof n?(t=co(Eo(n,fo)),t.parentNode=fo.documentElement):(t=co(n),t.parentNode=null),E([t])},Co.on=function(n,t,e){var r=arguments.length;if(3>r){if(\"string\"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()[\"__on\"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:\"mouseover\",\ f},l},Co.datum=function(n){return arguments.length?this.property(\"__data__\",n):this.property(\"__data__\")},Co.filter=function(n){var t,e,r,i=[];\"function\"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Co.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Co.call=function(n){var t=co(arguments);return n.apply(t[0]=this,t),this},Co.empty=function(){return!this.node()},Co.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++a<l;){r=(i=this[a]).update,o.push(t=[]),t.parentNode=i.parentNode;for(var c=-1,f=i.length;++c<f;)(u=i[c])?(t.push(r[c]=e=n.call(i.parentNode,u.__data__,c,a)),e.__data__=u.__data__):t.push(null)}return E(o)},qo.insert=function(n,t){return arguments.length<2&&(t=V(this)),Co.insert.call(this,n,t)},ao.select=function(t){var e;return\"string\"==typeof t?(e=[No(t,fo)],e.parentNode=fo.documentElement):(e=[t],e.parentNode=n(t)),E([e])},ao.selectAll=function(n){var t;return\"string\"==typeof n?(t=co(Eo(n,fo)),t.parentNode=fo.documentElement):(t=co(n),t.parentNode=null),E([t])},Co.on=function(n,t,e){var r=arguments.length;if(3>r){if(\"string\"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()[\"__on\"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:\"mouseover\",\
mouseleave:\"mouseout\"});fo&&To.forEach(function(n){\"on\"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on(\"mousedown.drag\",u).on(\"touchstart.drag\",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:\"drag\",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:\"dragend\"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=\".drag\"+(null==v?\"\":\"-\"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:\"dragstart\"})}}var r=N(n,\"drag\",\"dragstart\",\"dragend\"),i=null,u=e(b,ao.mouse,t,\"mousemove\",\"mouseup\"),o=e(G,ao.touch,m,\"touchmove\",\"touchend\");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,\"on\")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+\".zoom\",p).on(\"dblclick.zoom\",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,\ mouseleave:\"mouseout\"});fo&&To.forEach(function(n){\"on\"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on(\"mousedown.drag\",u).on(\"touchstart.drag\",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:\"drag\",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:\"dragend\"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=\".drag\"+(null==v?\"\":\"-\"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:\"dragstart\"})}}var r=N(n,\"drag\",\"dragstart\",\"dragend\"),i=null,u=e(b,ao.mouse,t,\"mousemove\",\"mouseup\"),o=e(G,ao.touch,m,\"touchmove\",\"touchend\");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,\"on\")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+\".zoom\",p).on(\"dblclick.zoom\",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,\
@@ -999,7 +1001,8 @@ function(n){return/^[ns]/.test(n)?-3:null}).attr(\"width\",6).attr(\"height\",6)
d).on(\"mouseup.brush\",m),k.interrupt().selectAll(\"*\").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style(\"pointer-events\",\"none\").selectAll(\".resize\").style(\"display\",null),ao.select(\"body\").style(\"cursor\",_.style(\"cursor\")),w({type:\"brushstart\"}),d()}var o,a,l=N(n,\"brushstart\",\"brush\",\"brushend\"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each(\"start.brush\",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:\"brushstart\"})}).tween(\"brush:brush\",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:\"brush\",mode:\"resize\"})}}).each(\"end.brush\",function(){o=t.i,a=t.j,n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"})}):(n({type:\"brushstart\"}),n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,\"on\")};var $l={n:\"ns-resize\",e:\"ew-resize\",s:\"ns-resize\",w:\"ew-resize\",nw:\"nwse-resize\",\ d).on(\"mouseup.brush\",m),k.interrupt().selectAll(\"*\").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style(\"pointer-events\",\"none\").selectAll(\".resize\").style(\"display\",null),ao.select(\"body\").style(\"cursor\",_.style(\"cursor\")),w({type:\"brushstart\"}),d()}var o,a,l=N(n,\"brushstart\",\"brush\",\"brushend\"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each(\"start.brush\",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:\"brushstart\"})}).tween(\"brush:brush\",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:\"brush\",mode:\"resize\"})}}).each(\"end.brush\",function(){o=t.i,a=t.j,n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"})}):(n({type:\"brushstart\"}),n({type:\"brush\",mode:\"resize\"}),n({type:\"brushend\"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,\"on\")};var $l={n:\"ns-resize\",e:\"ew-resize\",s:\"ns-resize\",w:\"ew-resize\",nw:\"nwse-resize\",\
ne:\"nesw-resize\",se:\"nwse-resize\",sw:\"nesw-resize\"},Bl=[[\"n\",\"e\",\"s\",\"w\",\"nw\",\"ne\",\"se\",\"sw\"],[\"e\",\"w\"],[\"n\",\"s\"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl(\"%Y-%m-%dT%H:%M:%S.%LZ\");Wl.iso=Date.prototype.toISOString&&+new Date(\"2000-01-01T00:00:00.000Z\")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[\".%L\",function(n){return n.getMilliseconds()}],[\":%S\",function(n){return n.getSeconds()}],[\"%I:%M\",function(n){return n.getMinutes()}],[\"%I %p\",function(n){return n.getHours()}],[\"%a %d\",function(n){return n.getDay()&&1!=n.getDate()}],[\"%b %d\",function(n){return 1!=n.getDate()}],[\"%B\",function(n){return n.getMonth()}],[\"%Y\",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return \ ne:\"nesw-resize\",se:\"nwse-resize\",sw:\"nesw-resize\"},Bl=[[\"n\",\"e\",\"s\",\"w\",\"nw\",\"ne\",\"se\",\"sw\"],[\"e\",\"w\"],[\"n\",\"s\"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl(\"%Y-%m-%dT%H:%M:%S.%LZ\");Wl.iso=Date.prototype.toISOString&&+new Date(\"2000-01-01T00:00:00.000Z\")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[\".%L\",function(n){return n.getMilliseconds()}],[\":%S\",function(n){return n.getSeconds()}],[\"%I:%M\",function(n){return n.getMinutes()}],[\"%I %p\",function(n){return n.getHours()}],[\"%a %d\",function(n){return n.getDay()&&1!=n.getDate()}],[\"%b %d\",function(n){return 1!=n.getDate()}],[\"%B\",function(n){return n.getMonth()}],[\"%Y\",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return \
ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[\".%L\",function(n){return n.getUTCMilliseconds()}],[\":%S\",function(n){return n.getUTCSeconds()}],[\"%I:%M\",function(n){return n.getUTCMinutes()}],[\"%I %p\",function(n){return n.getUTCHours()}],[\"%a %d\",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],[\"%b %d\",function(n){return 1!=n.getUTCDate()}],[\"%B\",function(n){return n.getUTCMonth()}],[\"%Y\",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,\"application/json\",uo,t)},ao.html=function(n,t){return Cn(n,\"text/html\",oo,t)},ao.xml=An(function(n){return n.responseXML}),\"function\"==typeof define&&define.amd?(this.d3=ao,define(ao)):\"object\"==typeof module&&module.exports?module.exports=ao:this.d3=ao}(); ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[\".%L\",function(n){return n.getUTCMilliseconds()}],[\":%S\",function(n){return n.getUTCSeconds()}],[\"%I:%M\",function(n){return n.getUTCMinutes()}],[\"%I %p\",function(n){return n.getUTCHours()}],[\"%a %d\",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],[\"%b %d\",function(n){return 1!=n.getUTCDate()}],[\"%B\",function(n){return n.getUTCMonth()}],[\"%Y\",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,\"application/json\",uo,t)},ao.html=function(n,t){return Cn(n,\"text/html\",oo,t)},ao.xml=An(function(n){return n.responseXML}),\"function\"==typeof define&&define.amd?(this.d3=ao,define(ao)):\"object\"==typeof module&&module.exports?module.exports=ao:this.d3=ao}();
") "
)
################################################################################ ################################################################################
# end d3.js # end d3.js
################################################################################ ################################################################################

View File

@@ -24,8 +24,10 @@ cmake_minimum_required(VERSION 3.4)
function(ensure_entry_point) function(ensure_entry_point)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt' is meant to be used only " message(FATAL_ERROR
"'${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. " "as a CMake entry point and should not be included from other CMake files. "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead.") "Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt' directly instead."
)
endif() endif()
endfunction() endfunction()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -40,7 +40,7 @@ namespace {
using namespace units::aliases::isq::si; using namespace units::aliases::isq::si;
inline constexpr auto g = units::isq::si::si2019::standard_gravity<>; inline constexpr auto g = units::isq::si::si2019::standard_gravity<>; // NOLINT(readability-identifier-length)
inline constexpr auto air_density = kg_per_m3<>(1.225); inline constexpr auto air_density = kg_per_m3<>(1.225);
class Box { class Box {
@@ -48,7 +48,10 @@ class Box {
length::m<> height_; length::m<> height_;
density::kg_per_m3<> density_ = air_density; density::kg_per_m3<> density_ = air_density;
public: public:
constexpr Box(const length::m<>& length, const length::m<>& width, length::m<> height): base_(length * width), height_(std::move(height)) {} constexpr Box(const length::m<>& length, const length::m<>& width, length::m<> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr force::N<> filled_weight() const [[nodiscard]] constexpr force::N<> filled_weight() const
{ {

View File

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

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace units::aliases::isq::si; using namespace units::aliases::isq::si;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(km_per_h<>(83)), rate_of_climb(m_per_s<>(-0.7389))}}, glider{"SZD-30 Pirat", {velocity(km_per_h<>(83)), rate_of_climb(m_per_s<>(-0.7389))}},
glider{"SZD-51 Junior", {velocity(km_per_h<>(80)), rate_of_climb(m_per_s<>(-0.6349))}}, glider{"SZD-51 Junior", {velocity(km_per_h<>(80)), rate_of_climb(m_per_s<>(-0.6349))}},
glider{"SZD-48 Jantar Std 3", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.77355))}}, glider{"SZD-48 Jantar Std 3", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.77355))}},
glider{"SZD-56 Diana", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.63657))}}}; glider{"SZD-56 Diana", {velocity(km_per_h<>(110)), rate_of_climb(m_per_s<>(-0.63657))}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -76,7 +75,7 @@ auto get_waypoints()
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

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

View File

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

View File

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

View File

@@ -44,7 +44,8 @@ void example()
Time auto t1 = s<>(10); Time auto t1 = s<>(10);
Speed auto v1 = avg_speed(d1, t1); Speed auto v1 = avg_speed(d1, t1);
auto temp1 = v1 * m<>(50); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit' auto temp1 =
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 Speed auto v2 = temp1 / m<>(100); // back to known dimensions again
Length auto d2 = v2 * s<>(60); Length auto d2 = v2 * s<>(60);
@@ -62,11 +63,9 @@ int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,10 +31,7 @@
using namespace units::isq; using namespace units::isq;
constexpr Speed auto avg_speed(Length auto d, Time auto t) constexpr Speed auto avg_speed(Length auto d, Time auto t) { return d / t; }
{
return d / t;
}
int main() int main()
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -56,7 +56,10 @@ class Box {
si::length<m> height_; si::length<m> height_;
si::density<kgpm3> density_ = air_density; si::density<kgpm3> density_ = air_density;
public: public:
constexpr Box(const si::length<m>& length, const si::length<m>& width, si::length<m> height) : base_(length * width), height_(std::move(height)) {} constexpr Box(const si::length<m>& length, const si::length<m>& width, si::length<m> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr si::force<N> filled_weight() const [[nodiscard]] constexpr si::force<N> filled_weight() const
{ {

View File

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

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace si::literals; using namespace si::literals;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}}, glider{"SZD-30 Pirat", {velocity(83_q_km_per_h), rate_of_climb(-0.7389_q_m_per_s)}},
glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}}, glider{"SZD-51 Junior", {velocity(80_q_km_per_h), rate_of_climb(-0.6349_q_m_per_s)}},
glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}}, glider{"SZD-48 Jantar Std 3", {velocity(110_q_km_per_h), rate_of_climb(-0.77355_q_m_per_s)}},
glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}}; glider{"SZD-56 Diana", {velocity(110_q_km_per_h), rate_of_climb(-0.63657_q_m_per_s)}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -76,7 +75,7 @@ auto get_waypoints()
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -50,7 +50,10 @@ class Box {
si::length<si::metre> height_; si::length<si::metre> height_;
si::density<si::kilogram_per_metre_cub> density_ = air_density; si::density<si::kilogram_per_metre_cub> density_ = air_density;
public: public:
constexpr Box(const si::length<si::metre>& length, const si::length<si::metre>& width, si::length<si::metre> height) : base_(length * width), height_(std::move(height)) {} constexpr Box(const si::length<si::metre>& length, const si::length<si::metre>& width, si::length<si::metre> height) :
base_(length * width), height_(std::move(height))
{
}
[[nodiscard]] constexpr si::force<si::newton> filled_weight() const [[nodiscard]] constexpr si::force<si::newton> filled_weight() const
{ {

View File

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

View File

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

View File

@@ -25,7 +25,6 @@
#include <units/chrono.h> #include <units/chrono.h>
#include <units/generic/dimensionless.h> #include <units/generic/dimensionless.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -43,14 +42,14 @@ using namespace units::isq;
auto get_gliders() auto get_gliders()
{ {
using namespace si::references; using namespace si::references;
UNITS_DIAGNOSTIC_PUSH UNITS_DIAGNOSTIC_PUSH
UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = { static const std::array gliders = {
glider{"SZD-30 Pirat", {velocity(83 * (km / h)), rate_of_climb(-0.7389 * (m / s))}}, glider{"SZD-30 Pirat", {velocity(83 * (km / h)), rate_of_climb(-0.7389 * (m / s))}},
glider{"SZD-51 Junior", {velocity(80 * (km / h)), rate_of_climb(-0.6349 * (m / s))}}, glider{"SZD-51 Junior", {velocity(80 * (km / h)), rate_of_climb(-0.6349 * (m / s))}},
glider{"SZD-48 Jantar Std 3", {velocity(110 * (km / h)), rate_of_climb(-0.77355 * (m / s))}}, glider{"SZD-48 Jantar Std 3", {velocity(110 * (km / h)), rate_of_climb(-0.77355 * (m / s))}},
glider{"SZD-56 Diana", {velocity(110 * (km / h)), rate_of_climb(-0.63657 * (m / s))}}}; glider{"SZD-56 Diana", {velocity(110 * (km / h)), rate_of_climb(-0.63657 * (m / s))}}};
UNITS_DIAGNOSTIC_POP UNITS_DIAGNOSTIC_POP
return gliders; return gliders;
} }
@@ -76,7 +75,7 @@ auto get_waypoints()
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, glider> requires(std::same_as<std::ranges::range_value_t<R>, glider>)
void print(const R& gliders) void print(const R& gliders)
{ {
std::cout << "Gliders:\n"; std::cout << "Gliders:\n";
@@ -85,13 +84,14 @@ void print(const R& gliders)
std::cout << "- Name: " << g.name << "\n"; std::cout << "- Name: " << g.name << "\n";
std::cout << "- Polar:\n"; std::cout << "- Polar:\n";
for (const auto& p : g.polar) for (const auto& p : g.polar)
std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v, units::quantity_cast<units::one>(glide_ratio(g.polar[0]))); std::cout << STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q}\n", p.climb, p.v,
units::quantity_cast<units::one>(glide_ratio(g.polar[0])));
std::cout << "\n"; std::cout << "\n";
} }
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>> requires(std::same_as<std::ranges::range_value_t<R>, std::pair<const char*, weather>>)
void print(const R& conditions) void print(const R& conditions)
{ {
std::cout << "Weather:\n"; std::cout << "Weather:\n";
@@ -106,7 +106,7 @@ void print(const R& conditions)
} }
template<std::ranges::input_range R> template<std::ranges::input_range R>
requires std::same_as<std::ranges::range_value_t<R>, waypoint> requires(std::same_as<std::ranges::range_value_t<R>, waypoint>)
void print(const R& waypoints) void print(const R& waypoints)
{ {
std::cout << "Waypoints:\n"; std::cout << "Waypoints:\n";
@@ -125,7 +125,8 @@ void print(const task& t)
std::cout << "- Finish: " << t.get_finish().name << "\n"; std::cout << "- Finish: " << t.get_finish().name << "\n";
std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n"; std::cout << "- Length: " << STD_FMT::format("{:%.1Q %q}", t.get_length()) << "\n";
std::cout << "- Legs: " << "\n"; std::cout << "- Legs: "
<< "\n";
for (const auto& l : t.get_legs()) for (const auto& l : t.get_legs())
std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length()); std::cout << STD_FMT::format(" * {} -> {} ({:%.1Q %q})\n", l.begin().name, l.end().name, l.get_length());
std::cout << "\n"; std::cout << "\n";

View File

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

View File

@@ -94,11 +94,9 @@ int main()
try { try {
si_example(); si_example();
natural_example(); natural_example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

@@ -44,7 +44,8 @@ void example()
Time auto t1 = 10 * s; Time auto t1 = 10 * s;
Speed auto v1 = avg_speed(d1, t1); Speed auto v1 = avg_speed(d1, t1);
auto temp1 = v1 * (50 * m); // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit' auto temp1 =
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 Speed auto v2 = temp1 / (100 * m); // back to known dimensions again
Length auto d2 = v2 * (60 * s); Length auto d2 = v2 * (60 * s);
@@ -62,11 +63,9 @@ int main()
{ {
try { try {
example(); example();
} } catch (const std::exception& ex) {
catch (const std::exception& ex) {
std::cerr << "Unhandled std exception caught: " << ex.what() << '\n'; std::cerr << "Unhandled std exception caught: " << ex.what() << '\n';
} } catch (...) {
catch (...) {
std::cerr << "Unhandled unknown exception caught\n"; std::cerr << "Unhandled unknown exception caught\n";
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -48,7 +48,11 @@ using angle = quantity<dim_angle<>, U, Rep>;
inline namespace literals { inline namespace literals {
// rad // rad
constexpr auto operator"" _q_rad(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return angle<radian, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_rad(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return angle<radian, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_rad(long double l) { return angle<radian, long double>(l); } constexpr auto operator"" _q_rad(long double l) { return angle<radian, long double>(l); }
} // namespace literals } // namespace literals

View File

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

View File

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

View File

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

View File

@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.19)
# systems # systems
add_subdirectory(isq) add_subdirectory(isq)
@@ -38,7 +38,9 @@ add_subdirectory(si-uscs)
# wrapper for all the systems # wrapper for all the systems
add_library(mp-units-systems INTERFACE) add_library(mp-units-systems INTERFACE)
target_link_libraries(mp-units-systems INTERFACE target_link_libraries(
mp-units-systems
INTERFACE
mp-units::isq mp-units::isq
mp-units::isq-iec80000 mp-units::isq-iec80000
mp-units::isq-natural mp-units::isq-natural

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -57,15 +57,27 @@ using force = quantity<dim_force, U, Rep>;
inline namespace literals { inline namespace literals {
// poundal // poundal
constexpr auto operator"" _q_pdl(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<poundal, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_pdl(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<poundal, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_pdl(long double l) { return force<poundal, long double>(l); } constexpr auto operator"" _q_pdl(long double l) { return force<poundal, long double>(l); }
// pound force // pound force
constexpr auto operator"" _q_lbf(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<pound_force, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_lbf(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<pound_force, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_lbf(long double l) { return force<pound_force, long double>(l); } constexpr auto operator"" _q_lbf(long double l) { return force<pound_force, long double>(l); }
// kilopound force // kilopound force
constexpr auto operator"" _q_klbf(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return force<kilopound_force, std::int64_t>(static_cast<std::int64_t>(l)); } constexpr auto operator"" _q_klbf(unsigned long long l)
{
gsl_ExpectsAudit(std::in_range<std::int64_t>(l));
return force<kilopound_force, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_klbf(long double l) { return force<kilopound_force, long double>(l); } constexpr auto operator"" _q_klbf(long double l) { return force<kilopound_force, long double>(l); }
} // namespace literals } // namespace literals
@@ -96,9 +108,12 @@ using namespace force_references;
namespace units::aliases::isq::si::fps::inline force { namespace units::aliases::isq::si::fps::inline force {
template<Representation Rep = double> using pdl = units::isq::si::fps::force<units::isq::si::fps::poundal, Rep>; template<Representation Rep = double>
template<Representation Rep = double> using lbf = units::isq::si::fps::force<units::isq::si::fps::pound_force, Rep>; using pdl = units::isq::si::fps::force<units::isq::si::fps::poundal, Rep>;
template<Representation Rep = double> using klbf = units::isq::si::fps::force<units::isq::si::fps::kilopound_force, Rep>; template<Representation Rep = double>
using lbf = units::isq::si::fps::force<units::isq::si::fps::pound_force, Rep>;
template<Representation Rep = double>
using klbf = units::isq::si::fps::force<units::isq::si::fps::kilopound_force, Rep>;
} // namespace units::aliases::isq::si::fps::inline force } // namespace units::aliases::isq::si::fps::inline force

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -42,7 +42,11 @@ struct square_foot : derived_unit<square_foot, si::dim_area, si::international::
inline namespace literals { inline namespace literals {
// ft2 // ft2
constexpr auto operator"" _q_ft2(unsigned long long l) { gsl_ExpectsAudit(std::in_range<std::int64_t>(l)); return si::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 si::area<square_foot, std::int64_t>(static_cast<std::int64_t>(l));
}
constexpr auto operator"" _q_ft2(long double l) { return si::area<square_foot, long double>(l); } constexpr auto operator"" _q_ft2(long double l) { return si::area<square_foot, long double>(l); }
} // namespace literals } // namespace literals
@@ -71,7 +75,8 @@ using namespace area_references;
namespace units::aliases::isq::si::international::inline area { namespace units::aliases::isq::si::international::inline area {
template<Representation Rep = double> using ft2 = units::isq::si::area<units::isq::si::international::square_foot, Rep>; template<Representation Rep = double>
using ft2 = units::isq::si::area<units::isq::si::international::square_foot, Rep>;
} // namespace units::aliases::isq::si::international::inline area } // namespace units::aliases::isq::si::international::inline area

View File

@@ -23,9 +23,8 @@
#pragma once #pragma once
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/isq/si/international/length.h>
#include <units/isq/si/international/area.h> #include <units/isq/si/international/area.h>
#include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> #include <units/isq/si/international/speed.h>
#include <units/isq/si/international/volume.h> #include <units/isq/si/international/volume.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports

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