units-2.3.3/000077500000000000000000000000001432004327300126575ustar00rootroot00000000000000units-2.3.3/.github/000077500000000000000000000000001432004327300142175ustar00rootroot00000000000000units-2.3.3/.github/issue_template.md000066400000000000000000000002471432004327300175670ustar00rootroot00000000000000Please include the following information in your issue: 1. Which version of `units` you are using 2. Which compiler exhibited the problem (including compiler version) units-2.3.3/.gitignore000066400000000000000000000075601432004327300146570ustar00rootroot00000000000000## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # gtags GPATH GRTAGS GSYMS GTAGS # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ #Cmake generated stuff [Gg]enerated/ [Bb]uild/ [Mm][Ss][Vv][Cc]* [Gg][Cc][Cc]* #Visual studio code .vscode # Visual Studio 2015 cache/options directory .vs/ CMakeSettings.json # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # DNX project.lock.json artifacts/ *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx *.sap # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/packages/repositories.config # NuGet v3's project.json files produces more ignoreable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Microsoft Azure ApplicationInsights config file ApplicationInsights.config # Windows Store app package directory AppPackages/ BundleArtifacts/ # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ orleans.codegen.cs # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe # FAKE - F# Make .fake/ /docs/html /docs/latex /msvc2013 /docs/man/man3 units-2.3.3/.travis.yml000066400000000000000000000043561432004327300150000ustar00rootroot00000000000000sudo: required dist: xenial language: cpp cache: ccache: true directories: - cmake-3.4.3-Linux-x86_64/bin - cmake-3.4.3-Linux-x86_64/plugins - cmake-3.4.3-Linux-x86_64/share os: - linux compiler: - gcc - clang addons: apt: sources: - ubuntu-toolchain-r-test packages: - gcc-5 - g++-5 - clang branches: except: - gh-pages - documentation env: global: - COVERALLS_SERVICE_NAME=travis-ci - secure: H8JjZT7juIz0CNHmV01gPLhTWPBjVV9RNCvSQtxtGxCn4y0GwsSFB7T3nFLw2cSYYjBNkcYsierIrPau68fV2B03cdr+9GnRM+eFFHbiLIzzvZoysfHTZvl2ElCLc96fS6bko++vPc7FQEdNAphvSKZSN05UbR5sFKtgeykViEEAdmFYPG+ZMex7Exq+2YUANjQxBVGhPQ4/t3FNhKc+ByvQzxlO8MfmxNVLUwJsW9W/wb0ruXl1CFc15bXBts/DBAn+voJpqvl7+1GtlvcahMiSbKBi0aiqihlAcohw6c6x7IYXFekO0cNcAhFNeF2VM6b2DBY8wFQ07K2o0tXKovBdSdxTSmmfAKlKyYXYdtI47vtF0mIcx08nkuPNEbzeWyPOgMxKd6Ffa9XMf2e9zN6+2XwjvoIb3SjPl0mz41pp0MRSSxkTQdifUfXQthMFYPPTq734O4J/aIpB4AygkqeGnZtg140erqSeUG2prVB4EekCZwPAqk/4LCA2VIGf+PtqrCZDFk0dRW1SXViz67/7GqyIu4dkOMitEOLtqjO09roQHK9TP/QuWtlGWtJ+oaANNK7D+ciCM3gP5FmH6Se/OrqyUgJN+LLI/wJscDSPgiXPXNs44d85tLdsbG+hzrvj0IaMR0anqT5pDqaHYlKRhfFHZbbJyQ+yeItWhk8= install: - sudo apt-get update -qq - sudo apt-get install -y -qq lcov curl language-pack-de - if [[ "$CXX" = "g++" ]]; then export CXX="g++-5" CC="gcc-5"; fi - pwd - ls - if [[ ! -f "cmake-3.4.3-Linux-x86_64/bin/cmake" ]]; then wget --no-check-certificate http://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz && tar -xvf cmake-3.4.3-Linux-x86_64.tar.gz; fi script: - mkdir build && cd build - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ../cmake-3.4.3-Linux-x86_64/bin/cmake .. ;fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ../cmake-3.4.3-Linux-x86_64/bin/cmake --build . --config Release ;fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ../cmake-3.4.3-Linux-x86_64/bin/cmake --build . --config Debug ;fi - cd .. && mkdir coverallsBuild && cd coverallsBuild - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ../cmake-3.4.3-Linux-x86_64/bin/cmake -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . && cmake --build . --target coveralls ;fi after_success: - cd test - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ../../cmake-3.4.3-Linux-x86_64/bin/ctest -C Release -V ;fi units-2.3.3/CMakeLists.txt000066400000000000000000000301671432004327300154260ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.2 FATAL_ERROR) PROJECT(units LANGUAGES CXX) set(units_VERSION 2.3.1) # check if this is the main project set(MAIN_PROJECT OFF) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(MAIN_PROJECT ON) endif() # cmake options OPTION(BUILD_TESTS "Build unit tests" ${MAIN_PROJECT}) OPTION(BUILD_DOCS "Build the documentation" OFF) OPTION(DISABLE_IOSTREAM "Disables (cout) support for embedded applications" OFF) # options to disable unit definitions. Turn these on for unused namespaces to improve compile speed OPTION(DISABLE_PREDEFINED_UNITS "Disables all library-defined units" OFF) # options to re-enable specific unit types. Only use these if DISABLE_PREDEFINED_UNITS is set to ON OPTION(ENABLE_PREDEFINED_LENGTH_UNITS "Enables library-defined units of LENGTH." OFF) OPTION(ENABLE_PREDEFINED_MASS_UNITS "Enables library-defined units of MASS." OFF) OPTION(ENABLE_PREDEFINED_TIME_UNITS "Enables library-defined units of TIME." OFF) OPTION(ENABLE_PREDEFINED_ANGLE_UNITS "Enables library-defined units of ANGLE." OFF) OPTION(ENABLE_PREDEFINED_CURRENT_UNITS "Enables library-defined units of CURRENT." OFF) OPTION(ENABLE_PREDEFINED_TEMPERATURE_UNITS "Enables library-defined units of TEMPERATURE." OFF) OPTION(ENABLE_PREDEFINED_SUBSTANCE_UNITS "Enables library-defined units of SUBSTANCE." OFF) OPTION(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS "Enables library-defined units of LUMINOUS INTENSITY." OFF) OPTION(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS "Enables library-defined units of SOLID ANGLE." OFF) OPTION(ENABLE_PREDEFINED_FREQUENCY_UNITS "Enables library-defined units of FREQUENCY." OFF) OPTION(ENABLE_PREDEFINED_VELOCITY_UNITS "Enables library-defined units of VELOCITY." OFF) OPTION(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS "Enables library-defined units of ANGULAR VELOCITY." OFF) OPTION(ENABLE_PREDEFINED_ACCELERATION_UNITS "Enables library-defined units of ACCELERATION." OFF) OPTION(ENABLE_PREDEFINED_FORCE_UNITS "Enables library-defined units of FORCE." OFF) OPTION(ENABLE_PREDEFINED_PRESSURE_UNITS "Enables library-defined units of PRESSURE." OFF) OPTION(ENABLE_PREDEFINED_CHARGE_UNITS "Enables library-defined units of CHARGE." OFF) OPTION(ENABLE_PREDEFINED_ENERGY_UNITS "Enables library-defined units of ENERGY." OFF) OPTION(ENABLE_PREDEFINED_POWER_UNITS "Enables library-defined units of POWER." OFF) OPTION(ENABLE_PREDEFINED_VOLTAGE_UNITS "Enables library-defined units of VOLTAGE." OFF) OPTION(ENABLE_PREDEFINED_CAPACITANCE_UNITS "Enables library-defined units of CAPACITANCE." OFF) OPTION(ENABLE_PREDEFINED_IMPEDANCE_UNITS "Enables library-defined units of IMPEDANCE." OFF) OPTION(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS "Enables library-defined units of MAGNETIC FLUX." OFF) OPTION(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS "Enables library-defined units of MAGNETIC FIELD STRENGTH." OFF) OPTION(ENABLE_PREDEFINED_INDUCTANCE_UNITS "Enables library-defined units of INDUCTANCE." OFF) OPTION(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS "Enables library-defined units of LUMINOUS FLUX." OFF) OPTION(ENABLE_PREDEFINED_ILLUMINANCE_UNITS "Enables library-defined units of ILLUMINANCE." OFF) OPTION(ENABLE_PREDEFINED_RADIATION_UNITS "Enables library-defined units of RADIATION." OFF) OPTION(ENABLE_PREDEFINED_TORQUE_UNITS "Enables library-defined units of TORQUE." OFF) OPTION(ENABLE_PREDEFINED_AREA_UNITS "Enables library-defined units of AREA." OFF) OPTION(ENABLE_PREDEFINED_VOLUME_UNITS "Enables library-defined units of VOLUME." OFF) OPTION(ENABLE_PREDEFINED_DENSITY_UNITS "Enables library-defined units of DENSITY." OFF) OPTION(ENABLE_PREDEFINED_CONCENTRATION_UNITS "Enables library-defined units of CONCENTRATION." OFF) OPTION(ENABLE_PREDEFINED_DATA_UNITS "Enables library-defined units of DATA." OFF) OPTION(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS "Enables library-defined units of DATA TRANSFER RATE." OFF) OPTION(ENABLE_PREDEFINED_CONSTANTS_UNITS "Enables library-defined units of CONSTANTS." OFF) SET(CMAKE_CXX_STANDARD 14) SET(CMAKE_CXX_STANDARD_REQUIRED TRUE) # header-only library target. To use this project as a subdirectory, # add the following to your code: # # add_subdirectory(units) # or whatever you named the directory # target_link_libraries(${PROJECT_NAME} units) add_library(${PROJECT_NAME} INTERFACE) add_library(units::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} INTERFACE $ $ ) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # enable parallel build set( ENV{CL} /MP ) target_compile_options(${PROJECT_NAME} INTERFACE /permissive-) elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # Increase warning levels add_compile_options(-Wall -Wextra -pedantic) endif() # Remove IOStream from the library (useful for embdedded development) if(DISABLE_IOSTREAM) target_compile_definitions(${PROJECT_NAME} INTERFACE -DUNIT_LIB_DISABLE_IOSTREAM) endif(DISABLE_IOSTREAM) # unit tests if(BUILD_TESTS) set(VERSION_GTEST "1.8.0" CACHE STRING "Google Test framework version") enable_testing() add_subdirectory(3rdParty/gtest) add_subdirectory(unitTests) endif(BUILD_TESTS) #enable specific unit definitions if(DISABLE_PREDEFINED_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DDISABLE_PREDEFINED_UNITS) endif(DISABLE_PREDEFINED_UNITS) if(ENABLE_PREDEFINED_LENGTH_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_LENGTH_UNITS) endif(ENABLE_PREDEFINED_LENGTH_UNITS) if(ENABLE_PREDEFINED_MASS_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_MASS_UNITS) endif(ENABLE_PREDEFINED_MASS_UNITS) if(ENABLE_PREDEFINED_TIME_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_TIME_UNITS) endif(ENABLE_PREDEFINED_TIME_UNITS) if(ENABLE_PREDEFINED_ANGLE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_ANGLE_UNITS) endif(ENABLE_PREDEFINED_ANGLE_UNITS) if(ENABLE_PREDEFINED_CURRENT_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_CURRENT_UNITS) endif(ENABLE_PREDEFINED_CURRENT_UNITS) if(ENABLE_PREDEFINED_TEMPERATURE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_TEMPERATURE_UNITS) endif(ENABLE_PREDEFINED_TEMPERATURE_UNITS) if(ENABLE_PREDEFINED_SUBSTANCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_SUBSTANCE_UNITS) endif(ENABLE_PREDEFINED_SUBSTANCE_UNITS) if(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS) endif(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS) if(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_SOLID_ANGLE_UNITS) endif(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS) if(ENABLE_PREDEFINED_FREQUENCY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_FREQUENCY_UNITS) endif(ENABLE_PREDEFINED_FREQUENCY_UNITS) if(ENABLE_PREDEFINED_VELOCITY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_VELOCITY_UNITS) endif(ENABLE_PREDEFINED_VELOCITY_UNITS) if(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS) endif(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS) if(ENABLE_PREDEFINED_ACCELERATION_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_ACCELERATION_UNITS) endif(ENABLE_PREDEFINED_ACCELERATION_UNITS) if(ENABLE_PREDEFINED_FORCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_FORCE_UNITS) endif(ENABLE_PREDEFINED_FORCE_UNITS) if(ENABLE_PREDEFINED_PRESSURE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_PRESSURE_UNITS) endif(ENABLE_PREDEFINED_PRESSURE_UNITS) if(ENABLE_PREDEFINED_CHARGE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_CHARGE_UNITS) endif(ENABLE_PREDEFINED_CHARGE_UNITS) if(ENABLE_PREDEFINED_ENERGY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_ENERGY_UNITS) endif(ENABLE_PREDEFINED_ENERGY_UNITS) if(ENABLE_PREDEFINED_POWER_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_POWER_UNITS) endif(ENABLE_PREDEFINED_POWER_UNITS) if(ENABLE_PREDEFINED_VOLTAGE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_VOLTAGE_UNITS) endif(ENABLE_PREDEFINED_VOLTAGE_UNITS) if(ENABLE_PREDEFINED_CAPACITANCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_CAPACITANCE_UNITS) endif(ENABLE_PREDEFINED_CAPACITANCE_UNITS) if(ENABLE_PREDEFINED_IMPEDANCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_IMPEDANCE_UNITS) endif(ENABLE_PREDEFINED_IMPEDANCE_UNITS) if(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS) endif(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS) if(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS) endif(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS) if(ENABLE_PREDEFINED_INDUCTANCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_INDUCTANCE_UNITS) endif(ENABLE_PREDEFINED_INDUCTANCE_UNITS) if(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS) endif(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS) if(ENABLE_PREDEFINED_ILLUMINANCE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_ILLUMINANCE_UNITS) endif(ENABLE_PREDEFINED_ILLUMINANCE_UNITS) if(ENABLE_PREDEFINED_RADIATION_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_RADIATION_UNITS) endif(ENABLE_PREDEFINED_RADIATION_UNITS) if(ENABLE_PREDEFINED_TORQUE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_TORQUE_UNITS) endif(ENABLE_PREDEFINED_TORQUE_UNITS) if(ENABLE_PREDEFINED_AREA_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_AREA_UNITS) endif(ENABLE_PREDEFINED_AREA_UNITS) if(ENABLE_PREDEFINED_VOLUME_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_VOLUME_UNITS) endif(ENABLE_PREDEFINED_VOLUME_UNITS) if(ENABLE_PREDEFINED_DENSITY_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_DENSITY_UNITS) endif(ENABLE_PREDEFINED_DENSITY_UNITS) if(ENABLE_PREDEFINED_CONCENTRATION_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_CONCENTRATION_UNITS) endif(ENABLE_PREDEFINED_CONCENTRATION_UNITS) if(ENABLE_PREDEFINED_DATA_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_DATA_UNITS) endif(ENABLE_PREDEFINED_DATA_UNITS) if(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS) target_compile_definitions(${PROJECT_NAME} INTERFACE -DENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS) endif(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS) # add a target to generate API documentation with Doxygen if(BUILD_DOCS) find_package(Doxygen) if(DOXYGEN_FOUND) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/docs COMMENT "Generating API documentation with Doxygen" VERBATIM ) endif(DOXYGEN_FOUND) endif(BUILD_DOCS) include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/unitsConfigVersion.cmake" VERSION ${units_VERSION} COMPATIBILITY SameMajorVersion ) install(TARGETS units EXPORT unitsConfig ) install(EXPORT unitsConfig NAMESPACE units:: DESTINATION share/units/cmake ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/unitsConfigVersion.cmake" DESTINATION share/units/cmake ) install(DIRECTORY include/ DESTINATION include ) units-2.3.3/CMakeSettings.json000066400000000000000000000017171432004327300162610ustar00rootroot00000000000000{ // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. "configurations": [ { "name": "Debug", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_x64_x64" ], "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "" }, { "name": "Release", "generator": "Ninja", "configurationType": "RelWithDebInfo", "inheritEnvironments": [ "msvc_x64_x64" ], "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "" } ] }units-2.3.3/LICENSE000066400000000000000000000020671432004327300136710ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2016 Nic Holthaus 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. units-2.3.3/README.md000066400000000000000000001124151432004327300141420ustar00rootroot00000000000000 # UNITS A compile-time, header-only, dimensional analysis library built on c++14 with no dependencies. [![Linux build](https://travis-ci.org/nholthaus/units.svg?branch=master)](https://travis-ci.org/nholthaus/units) [![Windows build](https://ci.appveyor.com/api/projects/status/github/nholthaus/units?svg=true&branch=master)](https://ci.appveyor.com/project/nholthaus/units) [![Coverage Status](https://coveralls.io/repos/github/nholthaus/units/badge.svg?branch=master)](https://coveralls.io/github/nholthaus/units?branch=master) ![license](https://img.shields.io/badge/license-MIT-orange.svg) ![copyright](https://img.shields.io/badge/%C2%A9-Nic_Holthaus-orange.svg) ![language](https://img.shields.io/badge/language-c++-blue.svg) ![c++](https://img.shields.io/badge/std-c++14-blue.svg)
![msvc2015](https://img.shields.io/badge/MSVC-2015-ff69b4.svg) ![msvc2017](https://img.shields.io/badge/MSVC-2017-ff69b4.svg) ![gcc-4.9.3](https://img.shields.io/badge/GCC-4.9.3-ff69b4.svg) ![gcc-5.4.0](https://img.shields.io/badge/GCC-5.4.0-ff69b4.svg) ![clang-3.4](https://img.shields.io/badge/CLANG-3.4-ff69b4.svg) # Get in touch If you are using `units.h` in production code, I'd love to hear from you via GitHub issues! # Latest Release - v2.3.1 ## Get it [![DOWNLOAD](https://img.shields.io/badge/Download-v2.3.1-green.svg)](https://github.com/nholthaus/units/releases/tag/v2.3.1) ## New in v2.3.1 **This version removes support for the Visual Studio 2013 compiler.** Features: - units now include constexpr `name()` and `abbreviation()` member functions, which do not really on string/iostream. - Builds with VS2017 Ninja generator out of the box - string conversions are now locale aware - added unary increment and decrement operators (`++`,`--`), as well as unary `+` operator. Bug fixs: - fixed compilation error when iostream was disabled ## New in v2.3.0 Features: - 5x compile time improvement on MSVC. - 1.5x compile time improvement on GCC. - Even more dramatic reductions in compile time can be achieved if you opt-in to specific unit definitions instead of using all the library-defined types (which is the default value). Check out [Enabling a subset of units to improve compilation time](#enabling-a-subset-of-units-to-improve-compilation-time) for instructions. - Adds std::cout support for units with no defined abbreviation (they show up as a combination of SI base units) - Support for `std::numeric_limits` of unit types. - Assignment operators for unit types: `-=`, `+=`, `/=`, `*=`. - Added `min` and `max` overloads for units types in `units::math`. - Added `to_string` function and `abbreviation` functions: ```cpp auto len = 3.5_m; auto str = units::length::to_string(len); auto abv = units::length::abbreviation(len); std::cout << str; // prints "3.5 m" std::cout << abv; // prints "m" ``` - Added units of data and data transfer: `bits`, `bytes`, `bits_per_second`, and `bytes_per_second`. - Adds `value()` member for accessing underlying type. - Adds `value_type` trait, as a synonym for `underlying_type`. - Adds definitions for Julian and Gregorian years. - Thanks to @dinocore1, `units` now supports cmake install and `find_packages`. From the [pull request](https://github.com/nholthaus/units/pull/84): ```cmake # To have cmake install units library to a local 'install' directory: mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX="install" .. cmake --build . --target install # The units library can then be used in some other cmake project using # the standard 'find_package' command. Like so: find_package(units) ``` Bug fixes: - Fixed singular name of `siemen` to be `siemens` (Thanks @Oxyd) - Fixed bug with `cubrt` operation (Thanks @PearCoding) - Fixed constexpr relational operators bug - Fixed exponential temperature conversions (Thanks @guarndt) ## Tested on - gcc-4.9.3 - gcc-5.4.0 - clang-3.4 - msvc2015 - msvc2017 Does this library work on your compiler? If so, let me know! # Contents - [UNITS](#units) - [Get in touch](#get-in-touch) - [Latest Release - v2.3.1](#latest-release---v231) - [Get it](#get-it) - [New in v2.3.1](#new-in-v231) - [New in v2.3.0](#new-in-v230) - [Tested on](#tested-on) - [Contents](#contents) - [Documentation](#documentation) - [Description](#description) - [Getting started guide](#getting-started-guide) - [Unit initialization](#unit-initialization) - [Unit tags](#unit-tags) - [Unit containers](#unit-containers) - [Unit Literals](#unit-literals) - [`` Functions](#cmath-functions) - [Exponentials and Square Roots](#exponentials-and-square-roots) - [Removing type safety](#removing-type-safety) - [Efficiency](#efficiency) - [Pure Compile-time Unit Manipulation](#pure-compile-time-unit-manipulation) - [Conversion without unit containers](#conversion-without-unit-containers) - [Namespaces](#namespaces) - [Defining new units](#defining-new-units) - [Unit definition macros](#unit-definition-macros) - [Unit Type Traits](#unit-type-traits) - [Changing the underlying type of `unit_t`](#changing-the-underlying-type-of-unit_t) - [Disabling IOStream](#disabling-iostream) - [Enabling a subset of units to improve compilation time](#enabling-a-subset-of-units-to-improve-compilation-time) - [Macro clashes](#macro-clashes) - [Windows macros](#windows-macros) - [ARM macros](#arm-macros) - [CMake Instructions](#cmake-instructions) - [Build Instructions](#build-instructions) - [Windows](#windows) - [Linux](#linux) - [Previous Releases](#previous-releases) # Documentation [The full documentation is available ***here***](http://nholthaus.github.io/units). # Description The library consists of a single file ([units.h](include/units.h)), plus unit tests. To incorporate the library into your project, simply copy the header into a location in your include path, or add the [included CMake project](#cmake-instructions) into your build. Using the CMake project, you can also build the unit tests and documentation if desired. The library provides a set of types, containers, and traits to solve dimensional analysis problems, that is, problems involving dimensioned physical quantities. The conversions between units are defined as ratios at compile time, making the library _incredibly_ fast. Additionally, specifying units as _types_, rather than variable suffixes (or not at all), provides complete type-safety within the compiler. This means that code that accidentally misuses units or which has errors in the dimensional analysis _will fail at compile-time, not at run-time_. The unit test file `unitTests/main.cpp` contains example usage of every type, trait, and function contained in the library, and while not exactly user-friendly, can be a valuable resource. # Getting started guide Add `units.h` to your project, along with the `using` directive for literals ```cpp #include using namespace units::literals; ``` Each "dimension" of unit is defined in its own namespace. See [the namespaces section](#namespaces) for a complete list. The rest of the guide assumes you've included the namespaces you plan to use: ```cpp using namespace units; using namespace units::length; using namespace units::time; using namespace units::area; using namespace units::velocity; ``` **The easiest way to get started with the `units` library is to think of unit containers as `double` values.** Unit containers are typically the units' non-plural name with the suffix `_t` (for type), e.g. `meter_t`. See [the documentation](http://nholthaus.github.io/units/namespaces.html) for a complete list. Units can (_and should!_) be used anywhere `double` values can be used: ```cpp double area = 15 * 5 + 10 * 10; // 175 m^2? square_meter_t area = 15_m * 5_m + 10_m * 10_m; // 175 m^2 ``` What makes unit types special is that unit conversions happen implicitly and automatically. Since unit conversions are evaluated at compile time, this means you can mix and match all the unit types you want with _no runtime penalty_. ```cpp foot_t len = 5_m; // simple implicit conversion meters_per_second_t speed = 60_mi / 1_hr; // more complex implicit conversion square_meter_t area = 15_m * 5_m + 1000_cm * 1000_cm; // previous example with mixed units ``` Note the return type has the correct dimensions of area, even though the source types were all units of length. `units.h` has powerful dimensional analysis capabilities. But what happens if we get the return type wrong? ```cpp meter_t area = 15_m * 5_m + 10_m * 10_m; // oops, m * m = m^2 ``` > E:/workspace/units/include/units.h(1405): error C2338: Units are not compatible. Your compiler will produce an "incompatible units" error if your dimensional analysis is incorrect. If your resulting unit types are complex, you could use `auto` for simplicity: ```cpp auto result = 15_m * 5_m + 10_m * 10_m; // m^2 auto speed = 60_mi / 1_hr; // 60 mph ``` ***NOTE: Think carefully about using `auto` for return types.*** When you explicitly declare the return type, the compiler can check the dimensional analysis for correctness, and produce errors at compile time if you make a mistake. When using `auto`, you are basically saying that whatever unit the right-hand side of the expression results to is correct (even if it's not). If you are only using `auto` because a complex unit type is not available in the library, try [defining a new unit](#defining-new-units) as a better alternative. More complex mathematical operations ([almost every `` operation actually](http://nholthaus.github.io/units/namespaceunits_1_1math.html)), including exponentials and square roots are possibe by using the `units::math` namespace . ```cpp using namespace units::math; meter_t a = 3_m; meter_t b = 4_m; meter_t c = sqrt(pow<2>(a) + pow<2>(b)); // Pythagorean threorem. std::cout << c << std::endl; // prints: "5 m" ``` # Unit initialization There are several ways to initialize unit values: - Explicit initialization ```cpp meter_t distance_m(10); // Explicit initialization from double meter_t distance(10_m); // Explicit initialization from unit literal meter_t dist(100_ft); // Explicit initialization from unit literal of a different type ``` - `make_unit<...>()` factory. The syntax is familiar to `boost::units` users, and allows explicit reference to the unit type for member variable initialization. ```cpp class myClass { public: myClass() : m_speed(make_unit(100)) {} private: miles_per_hour_t m_speed; }; ``` # Unit tags Unit tags are the foundation of the unit library. Unit tags are types which are never instantiated in user code, but which provide the meta-information about different units, including how to convert between them, and how to determine their compatibility for conversion. All unit tags are defined in namespaces under the `units` namespace, such as `units::length` or `units::angle`, to avoid name clashes between units of different physical quantities which share the same names (like pounds). SI base units are defined as "categories" in the `unit` namespace. Units are defined in terms of 1. A scale factor relative to a base unit type. 2. A base unit 3. [optionally] a scale factor of `pi` 4. [optionally] a datum translation (such as the +/- 32 required to convert between `fahrenheit` and `celsius`) All units have their origin in the Système International (SI) base unit system. A special exception is made for angle units, which are defined in SI as ( m * m^-1), and in this library they are treated as a basic unit type because of their important engineering applications. _Example_: the definitions of some common length units are: ```cpp namespace length { using meters = units::unit, units::category::length_unit>; // meters are (1) unit of length in the SI system. using feet = units::unit, meters>; // feet are 0.3048 meters. } ``` # Unit containers Unit containers are the primary classes which will be instantiated in user code. They can be thought of as essentially equivalent to a `double`, except that they have unit type tags associated with them. They can be used wherever a double would be used to store a dimensioned quantity. Containers are derived from the `unit_t` class, and have the form `[unitname]_t`, e.g. `meter_t` or `radian_t`. Unit containers are defined in terms of the units they represent, their underlying type, and an optional non-linear scale (think decibels or Richter scale). For example, `meter_t` would be defined: ```cpp using meter_t = units::unit_t ``` or simply ```cpp using meter_t = units::unit_t ``` since the underlying type and scale parameters default to `double` and `linear_scale` respectively. Units of compatible types (e.g length units) can be implicitly converted/assigned to one another. Units (with the exception of dimensionless types) cannot be implicitly converted to/from built-in types, such as `double`. Units are constructed from built-in types, and the `toDouble()` method (or `operator()`) can be used to retrieve a built-in type value. That said, the user should prefer to operate within the unit type-space as much as is practical, and wrappers of most `` functions are provided to enable operating solely in the `unit_t` domain. The primary purpose of unit containers is to provide type safety and dimensional analysis for mathematical operations. for instance, the velocity of an object can be calculated: ```cpp auto objectVelocity = meter_t(100.0) / second_t(2.0); ``` The resulting velocity type will be deduced to be `velocity::meters_per_second` with a value of 50.0. Additionally, if the return type if specified, the type system will verify that the units are compatible. For example, the following will fail to compile: ```cpp units::velocity::meters_per_second objectVelocity = square_meter_t(100.0) / second_t(2.0); // Error: Unit types are not compatible.` ``` Unit containers can (and should!) be used to perform implicit conversions: ```cpp units::time::second_t a; units::time::minute_t b(1.0); a = b; // a == 60.0 ``` Arithmetic can be performed on unit containers the same way it can for built-in types. However, unlike built-in types, the return value of unit-type arithmetic will be the proper unit to represent the resulting quantity. ```cpp using namespace units::length; using namespace units::area; meter_t a_m(1.0), b_m(2.0), c_m; foot_t a_ft(1.0), b_ft(2.0), c_ft; c_m = a_m + b_m; // OK. c == 3m c_ft = a_m + b_m; // OK. resulting 3m is converted to ft. auto result = a_m + b_ft; // OK. result is `meter_t` (left-most unit) auto result_sm = a_m * b_m; // OK. result_sm is `square_meter_t`. auto result_s = a_m / b_m; // OK. result_s is `dimensionless_t`. auto result = a_m * b_ft; // OK. result is `square_meter_t` (left-most unit) auto result = a_m * square_meter_t(1.0); // OK. units can always be multiplied. Result is `cubed`. auto result = a_m * scalar_t(1.0); // OK. units can always be multiplied. Result is `meter_t`. ``` Unsupported arithmetic, or improper return types will result in compiler errors: ```cpp c_m = a_m + 5.0; // Error. can't add scalars to dimensioned units. c_m = a_m + scalar_t(5.0); // Error. can't add scalars to dimensioned units. auto result = a_m + square_meter_t(1.0); // Error. Incompatible units. ``` By providing explicit return types for unit functions, the compiler can be used to verify the accuracy of the dimensional analysis, and thus avoiding costly errors. # Unit Literals If you are using a compiler which supports user-defined literals (e.g. not Visual Studio 2013), then unit literals can be a convenient way to initialize and work with unit values: ```cpp using namespace units::literals; meter_t dist = 10_m; // 10 m meter_t dist2 = 1_km; // 1000 m ``` Literals can also be used for any temporary values in calculations, making them more readable: ```cpp auto area = units::length::meter_t(5) * units::length::meter_t(10); // without literals auto area = 5_m * 10_m; // with literals ``` All literals* are defined by their SI abbreviation preceded by an underscore, e.g. `_m` for meter. "Square" units are preceded by `_sq`, e.g. `_sq_m` for square meters. Non SI units use their most common abbreviations. All literals can be used with a metric prefix as table shows: | Metric Prefix | Literal | Example | |:-------------:|:--------:|:---------:| | femto | f | `10_fm` | | pico | p | `10_pm` | | nano | n | `10_nm` | | micro | u | `10_um` | | milli | m | `10_mm` | | centi | c | `10_cm` | | deci | d | `10_dm` | | deca | da | `10_dam` | | hecto | h | `10_hm` | | kilo | k | `10_km` | | mega | M | `10_Mm` | | giga | G | `10_Gm` | | tera | T | `10_Tm` | | peta | P | `10_Pm` | All literals are defined in the `units::literals` namespace, and in order to use literals in your code ***you must include the line `using units::literals`*** (since there is no way to put a namespace on an operator). _* with the exception of `Teslas`, which use `_Te` for compatibility with MSVC compilers._ # `` Functions The `units` library include type-safe unit_t container wrappers for almost all of the `` functions, _including_ the c++11 extensions. These functions can be found in the `units::math` namespace. The `units` library versions don't conflict with ``, and it's possible to use both libraries in the same code. The overloaded functions ensure that only the proper unit types are accepted into the functions, and that the return value type matches the expected units, all without needing to result to the type-unsafe `toDouble()` member. In _rare_ cases, the overload resolution for a given type may be ambiguous. If so, simply prepend the function with the fully-qualified `units::math` prefix, e.g. ```cpp meter_t x(2.0); meter_t y(3.0); square_meter_t z(1.0); square_meter_t result; result = fma(x, y, z); // Error: ambiguous double result = fma(x.toDouble(), y.toDouble(), z.toDouble()); // Warning: Unsafe! result = math::fma(x, y, z); // OK. ``` # Exponentials and Square Roots Many functions require units to be raised to some power. This can be accomplished using the `units::math::pow` function: ```cpp square_meter_t m2 = units::math::pow<2>(meter_t(5.0)); // m2 == 25.0 ``` The only constraint is that the exponential power (given in the template argument) must be known at compile time, so that the type system can deduce the output type. This differs from the ` pow` implementation, which takes exponent values at runtime. Square roots are also provided with the `units::math::sqrt` function. Due to the nature of the `sqrt` operation, the units library can often provide exact conversions for square root operations, but _not in every case_. The rest of the time, the `sqrt` unit will be a _rational_approximation_ of the real value. These are guaranteed to be accurate to at least 10 decimal places. ```cpp meter_t m = units::math::sqrt(square_meter_t(4.0)); // m == 2.0 ``` # Removing type safety When interfacing with APIs, libraries, and frameworks which aren't `unit` enabled, it may be necessary (if regrettable) to remove the type-safety of a unit container and expose its underlying type. This is possible using the `unit_cast` function, or the `to<>` member function. ```cpp using namespace units; using namespace units::length; // Get double value from a unit container (double is the default underlying type of the units library) meter_t dist(10); double dval = unit_cast(dist); double dval2 = dist.to(); // Get integer value (potentially narrowing, be careful!) int ival = unit_cast(dist); int ival2 = dist.to(); ``` Both functions produce the same results, the choice of syntax is simply a user preference. To determine the underlying type of the unit container, the (verbose) trait `units::traits::unit_t_traits::underlying_type` could be used. # Efficiency Complex, recursively-defined conversions are performed in just 5 instructions: year_t twoYears(2.0); week_t twoYearsInWeeks = twoYears; 00007FF7BDB57FF6 xorps xmm9,xmm9 00007FF7BDB57FFA cvtsi2sd xmm9,rax 00007FF7BDB57FFF mulsd xmm9,mmword ptr [__real@4000000000000000 (07FF7BDBB31A0h)] 00007FF7BDB58008 divsd xmm9,mmword ptr [__real@401c000000000000 (07FF7BDBB33C0h)] 00007FF7BDB58011 movsd mmword ptr [rbp+6Fh],xmm9 EXPECT_EQ(week_t(104.286), twoYearsInWeeks); 00007FF7BDB58017 ... In the library, the year to week conversion is defined in terms of `years -> days -> hours -> minutes -> seconds -> minutes -> hours -> days -> weeks` but the total conversion ratio is computed at compile-time and the math is optimized to two floating-point operations. Unit conversions between equivalent types are optimized away completely, and generate _no machine code_. # Pure Compile-time Unit Manipulation In many cases, unit equations are used to determine derived values from a set of values which are known at compile-time. In these situations, it would be optimal to pre-compute the derived values _at compile time_, thus generating no machine code and incurring no run-time penalty. The `unit_value_t` class is the mechanism in the units library to perform compile-time arithmetic. The `unit_value_t` class functions exactly the same way as `std::ratio`, but with an associated unit tag and the ensuing type safety. For a simple example, let's define a right triangle whose hypotenuse is the sum of the squares of its side (a Pythagorean triple) ```cpp struct RightTriangle { using a = unit_value_t; using b = unit_value_t; using c = unit_value_sqrt, unit_value_power>>; }; ``` The definition above is perfectly efficient, as it generates _no run-time code_ whatsoever, and still provides all the type safety of unit containers. The values of `a`, `b`, and `c` can be accessed at runtime using the static `value()` method of `unit_value_t` ```cpp auto a = RightTriangle::a::value(); // a is `meter_t(3)` auto b = RightTriangle::b::value(); // b is `meter_t(4)` auto c = RightTriangle::c::value(); // c is `meter_t(5)` ``` The available compile-time operations are: - `units::unit_value_add` - `units::unit_value_subtract` - `units::unit_value_multiply` - `units::unit_value_divide` - `units::unit_value_power` - `units::unit_value_sqrt` # Conversion without unit containers The preferred method of conversion is implicitly though the use of unit containers, however unit conversion can be accomplished using `units::convert` for arithmetic types: ```cpp double val_in = convert(1.0); // val_in == 12.0 ``` For type-safe conversion, prefer implicit conversion via unit_t type containers.. # Namespaces Unit tags and containers are split into separate namespaces to avoid conflicting unit names which represent different physical quantities. Unit tag and `unit_t` container definitions are defined in the following namespaces: - units::length - units::mass - units::time - units::angle (plane) - units::current - units::temperature - units::substance (amount of, i.e. moles) - units::luminous_intensity - units::solid_angle - units::frequency - units::velocity - units::angular_velocity - units::acceleration - units::force - units::pressure - units::charge - units::energy - units::power - units::voltage - units::capacitance - units::impedance - units::magnetic_flux - units::magnetic_field_strength - units::inductance - units::luminous_flux - units::illuminance - units::radiation - units::torque - units::area - units::volume - units::density - units::concentration - units::data - units::data_transfer_rate - units::constants (scalar and non-scalar physical constants like Avogadro's number) Literal values for unit containers are defined in the `literals` namespace - units::literals Mathematical operations like `sin`, `log`, `floor`, etc are defined in the following namespaces: - units::math Type traits that you can use to test unit types are defined in the following namespaces: - units::traits # Defining new units The units library strives to provide built-in types for every conceivable unit, and before defining your own units you should double-check the namespaces to make sure it's not already included. That said, if you need to roll your own units, the library is extensible by design. Defining new units is simple, as they can be recursively defined as ratio of previously-defined units in a way that mimics natural language and is highly readable: ```cpp namespace time { using seconds = units::unit, units::category::time_unit>; using minutes = units::unit, seconds>; using hours = units::unit, minutes>; using days = units::unit, hours>; using weeks = units::unit, days>; using years = units::unit, days>; } ``` Units are defined in the form: `using [unit] = unit, [base unit]>;`, where: - the `[unit]` is what you are defining. - the `[base unit]` is the unit that `[unit]` will be defined in terms of, and - the `[number of base units per unit]` is the conversion ratio between the two, expressed as a `std::ratio` type. Compound units are defined in a similar manner, with additional helper functions for polynomials: using acceleration = compound_unit>>; // (m / s^2) The available helpers are: - `units::inverse<...>` (inverts the unit, e.g. meters becomes meters^-1, or 1 / meters) - `units::squared<...>` (squares the unit, e.g. meters becomes meters^2) - `units::cubed<...>` (cubes the unit, e.g. meters becomes meters^3) - `units::square_root<...>` (takes the square root of the unit, e.g meters^2 becomes meters) - `units::atto<...>` through `units::exa<...>` metric prefixes # Unit definition macros Version `2.1.0` of the units library simplifies the task of adding new units by introducing a set of macros for unit definitions: - `UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, definition)` This macro adds a single new unit to the given namespace, as well as a literal definition and `cout` support based on the given `abbreviation`. e.g. ```cpp UNIT_ADD(length, foot, feet, ft, unit, meters>) ``` Would create the `units::length::feet` tag, the `units::length::foot_t` container type, and the `_ft` literal. - `UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, definition)` This macro has the same functionality as `UNIT_ADD`, but additionally adds unit types with all metric prefixes from `femto` to `peta` (smaller and larger prefixes mostly result in arithmetic overflow). - `UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName, nameSingular, namePlural, abbreviation, underlyingType, definition)` This macro has the same functionality as `UNIT_ADD`, but additionally adds an `underlyingType` parameter, which can be used to create units with integral, or other underlying types. The library default underlying type is `double`. - `UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)` Adds the decibel representation for a previously-defined unit. e.g. ```cpp UNIT_ADD_DECIBEL(power, watt, dBW) ``` Adds the `dBW_t` container, and the `_dBW` literal. - `UNIT_ADD_CATEGORY_TRAIT(unitCategory, baseUnit)` This macro creates a type-trait to check whether a unit is of a certain category, e.g. length. This is only necessary if defining new categories of units which are not included in `units.h` at all. e.g. ```cpp UNIT_ADD_CATEGORY_TRAIT(length, meter) ``` Adds the `units::traits::is_length_unit` trait. # Unit Type Traits The units library provides a comprehensive set of type-traits, which can be used in templated user code to enforce that the unit types have certain properties. For example, let's say you want to write a function that validates that the square footage of an office (given in any units), meets the minimum size required by local ordinance. ```cpp template bool isMinimumSize(Units x) { return x >= square_feet_t(80.0); } ``` This function will fail to compile if `Units` is not a unit of area (since incompatible unit types are not comparable), but it will produce a series difficult-to-understand template errors. Type traits could be used to make the error message more friendly: ```cpp template bool isMinimumSize(Units x) { static_assert(units::traits::is_area_unit::value, "Input value x must represent an area quantity."); return x >= square_feet_t(80.0); } ``` See the `units::traits` namespace for a list of all the supported traits. # Changing the underlying type of `unit_t` The default underlying type for all unit containers is `double`. However, this can be overridden by providing a definition for `UNIT_LIB_DEFAULT_TYPE`, e.g. ```cpp // Use 64-bit integers as the underlying unit type #define UNIT_LIB_DEFAULT_TYPE int64_t #include ``` **_NOTE:_ changing the underlying type may result in unexpected behavior.** Unit conversion makes heavy use of division, which may make integral types unsuitable except for niche embedded applications. Using excessively large types may increase the number of arithmetic overflow errors. # Disabling IOStream For some embedded applications, it may be [desirable to remove all references to `` in order to reduce compiled binary size and RAM requirements](https://github.com/nholthaus/units/issues/32). There are two ways to accomplish this: 1. If you are copy/pasting `units.h` into your project include directory, then simply define `UNIT_LIB_DISABLE_IOSTREAM` before including the header. ```cpp #define UNIT_LIB_DISABLE_IOSTREAM #include ``` 2. If you are including `units` in your project as a `CMake` target (using `add_subdirectory`), then all you need to do is set the `DISABLE_IOSTREAM` cache option, either using the cmake-gui, or by adding the option to the cmake command line during configuration: ```bash cmake -DDISABLE_IOSTREAM=ON -DBUILD_TESTS=OFF .. cmake --build . --config Release ``` # Enabling a subset of units to improve compilation time If you know that you only need a subset of the unit namespaces for your application, you can dramatically improve compilation time by disabling the default definitions, and then only opting-in to the namespaces you want. For example: ```cpp // Only use length and time #define DISABLE_PREDEFINED_UNITS #define ENABLE_PREDEFINED_LENGTH_UNITS #define ENABLE_PREDEFINED_TIME_UNITS ``` The generic algorithm is 1. disable the pre-defined units using `#define DISABLE_PREDEFINED_UNITS` 2. opt-in to the namespaces you want using `#define ENABLE_PREDEFINED__UNITS` Additionally, for `CMake` users, there are equivalently-named cmake options defined which will automatically include the preprocessor definitions in your project. Alternatively, you can use `add_definitions()` in your cmake file to set macros globally:: ```cpp // Only use length and time add_definitions( -DDISABLE_PREDEFINED_UNITS -DENABLE_PREDEFINED_LENGTH_UNITS -DENABLE_PREDEFINED_TIME_UNITS ) ``` Be aware, some units depend on others. See the unit dependencies table bellow: | Unit | Dependencies | |:-----------------------:|:--------------------------------:| | ACCELERATION | LENGTH, TIME | | ANGULAR_VELOCITY | ANGLE, TIME | | AREA | LENGTH | | DENSITY | MASS, VOLUME | | FORCE | ACCELERATION, LENGTH, MASS, TIME | | ILLUMINANCE | LENGTH, LUMINOUS_FLUX | | MAGNETIC_FIELD_STRENGTH | MAGNETIC_FLUX | | PRESSURE | FORCE, LENGTH | | RADIATION | ENERGY, MASS | | SOLID_ANGLE | ANGLE | | TORQUE | FORCE, LENGTH | | VELOCITY | LENGTH, TIME | | VOLUME | LENGTH | # Macro clashes With certain compilers, it is possible that system header files like `` will define macros which conflict with the unit literals, which use SI abbreviations. In these cases, it is general safe and advisable to `#undef` the offending macros. ## Windows macros `_T` is known to conflict, but is hardcoded into the compiler and can't be disabled. For this reason, `Tesla` units use the `_Te` abbreviation. The following macros may need to be undefined on the Windows platform to use `units`: ```cpp #undef pascal #include ``` ## ARM macros The following macros may need to be undefined on the ARM platform to use `units::literals`: ```cpp #undef _U #undef _L #undef _N #undef _S #undef _P #undef _C #undef _X #undef _B #define UNIT_LIB_DISABLE_IOSTREAM // it's prudent to disable IOStream on embedded platforms as well. #include ``` It's best to undefine macros on an as-needed basis. # CMake Instructions There are several ways to incorporate `units.h` into your project. The simplest is to just copy `include/units.h` into your project include directory (which the licensing allows you to do). However, you'll have to properly set up the necessary compilation flags for C++14 (`-std=c++14` on gcc). However, if you are already using CMake as your build system, the recommended way to include `units` is to copy the entire `units` project as a subdirectory within your own top-level project folder. Then, in your CMakeLists.txt file add ```cmake add_subdirectory(units) add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} units) ``` Also, if you are distributing headers that depends on units.h, you shoud consider using cmake's `find_package` to check if the header is installed on the user's system: ```cmake find_package(units) add_library(${PROJECT_NAME} my_lib.cpp) target_link_libraries(${PROJECT_NAME} units::units) ``` The include path properties are part of the `units` target, so adding it as a subdirectory and linking against it is all you need to do, no need to worry about additional include directories. If you don't care about the unit tests, you can minimize compile time by invoking CMake with the following option: ```bash cmake -DBUILD_TESTS=OFF .. cmake -build . ``` # Build Instructions The library itself consists of a single header [units.h](include/units.h), and can be included into your project without being built. The unit tests and documentation can be built with CMake. A doxygen installation is required to generate the documentation, and a Tex install is needed if pdf documentation is desired. To build the tests: ## Windows 1. Ensure [`cmake`](https://cmake.org/download/) is installed, and that the `bin` directory is in your `%PATH%` variable, and that a compiler like [`Visual Studio 2015 Community Edition`](https://www.visualstudio.com/post-download-vs?sku=community&clcid=0x409&downloadrename=true#) is installed. 2. clone the repository or download the `.zip` package. 3. Open a `cmd` terminal and navigate to the source directory. 4. Type the following commands: - `md build` - `cd build` - `cmake -Wno-dev ..` - `cmake --build . --config Release` 5. The tests will be created in an executable called `unitLibTest.exe` in the folder `build/unitTests/Release`. ## Linux 1. Ensure you are using cmake 3.2 or later. You can verify this with `cmake --version`. 2. Ensure you are using gcc version 4.9 or greater. You can verify this with `gcc --version`. 3. clone the repository or download the `.tar.gz` package. 4. Open a terminal and navigate to the source directory. 5. Type the following commands: - `mkdir build` - `cd build` - `cmake -Wno-dev ..` - `cmake --build . --config Release` 6. The tests will be created in an executable called `unitLibTest` in the folder `build/unitTests`. # Previous Releases - [`v2.0.3`](https://github.com/nholthaus/units/releases/tag/v2.0.3) - `unit_t` types are now trivial types. - `unit_t` types support the unary minus (negation) operator. - Compile-time unit arithmetic via `unit_value_t`. - Unit-enabled ports of most `` functions, including c++11 extensions. - Square-root manipulators for `unit`, `unit_t`, and `unit_value_t`. - Improved documentation. - [`v1.3.0`](https://github.com/nholthaus/units/releases/tag/v1.3.0) - Adds ostream support. - bug fixes. - [`v1.2.2`](https://github.com/nholthaus/units/releases/tag/v1.2.2) - Bug fixes (#1) and namespace cleanup. - [`v1.2.0`](https://github.com/nholthaus/units/releases/tag/v1.2.0) - Adds angular velocity units. - [`v1.1.1`](https://github.com/nholthaus/units/releases/tag/v1.1.1) - Adds Doxygen and additional type traits. - [`v1.0.0`](https://github.com/nholthaus/units/releases/tag/v1.0.0) - Initial release. units-2.3.3/appveyor.yml000066400000000000000000000010201432004327300152400ustar00rootroot00000000000000clone_folder: c:/projects/units branches: except: - gh-pages - documentation platform: - x64 configuration: - Debug - Release environment: matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VS_GEN: Visual Studio 15 2017 Win64 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 VS_GEN: Visual Studio 16 2019 build_script: - md build - cd build - cmake -Wno-dev -G"%VS_GEN%" .. - cmake --build . --config %CONFIGURATION% test_script: - cmd: ctest -VV -C %CONFIGURATION% units-2.3.3/docs/000077500000000000000000000000001432004327300136075ustar00rootroot00000000000000units-2.3.3/docs/Doxyfile.in000066400000000000000000000310771432004327300157320ustar00rootroot00000000000000# Doxyfile 1.8.8 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Unit Conversion and Dimensional Analysis Library" PROJECT_NUMBER = 2.3.0 PROJECT_BRIEF = "A compile-time c++14 unit conversion library" PROJECT_LOGO = OUTPUT_DIRECTORY = @CMAKE_CURRENT_SOURCE_DIR@/docs CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = YES CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_PACKAGE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = @CMAKE_CURRENT_SOURCE_DIR@/README.md @CMAKE_CURRENT_SOURCE_DIR@/include INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf \ *.as \ *.js RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = README.md #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = YES CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO EXTERNAL_SEARCH = NO SEARCHENGINE_URL = SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = YES MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = MAN_LINKS = NO #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration options related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = PLANTUML_JAR_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES units-2.3.3/include/000077500000000000000000000000001432004327300143025ustar00rootroot00000000000000units-2.3.3/include/units.h000066400000000000000000007164151432004327300156330ustar00rootroot00000000000000//-------------------------------------------------------------------------------------------------- // // Units: A compile-time c++14 unit conversion library with no dependencies // //-------------------------------------------------------------------------------------------------- // // The MIT License (MIT) // // 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. // //-------------------------------------------------------------------------------------------------- // // Copyright (c) 2016 Nic Holthaus // //-------------------------------------------------------------------------------------------------- // // ATTRIBUTION: // Parts of this work have been adapted from: // http://stackoverflow.com/questions/35069778/create-comparison-trait-for-template-classes-whose-parameters-are-in-a-different // http://stackoverflow.com/questions/28253399/check-traits-for-all-variadic-template-arguments/28253503 // http://stackoverflow.com/questions/36321295/rational-approximation-of-square-root-of-stdratio-at-compile-time?noredirect=1#comment60266601_36321295 // //-------------------------------------------------------------------------------------------------- // /// @file units.h /// @brief Complete implementation of `units` - a compile-time, header-only, unit conversion /// library built on c++14 with no dependencies. // //-------------------------------------------------------------------------------------------------- #pragma once #ifndef units_h__ #define units_h__ #ifdef _MSC_VER # pragma push_macro("pascal") # undef pascal # if _MSC_VER <= 1800 # define _ALLOW_KEYWORD_MACROS # pragma warning(push) # pragma warning(disable : 4520) # pragma push_macro("constexpr") # define constexpr /*constexpr*/ # pragma push_macro("noexcept") # define noexcept throw() # endif // _MSC_VER < 1800 #endif // _MSC_VER #if !defined(_MSC_VER) || _MSC_VER > 1800 # define UNIT_HAS_LITERAL_SUPPORT # define UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT #endif #ifndef UNIT_LIB_DEFAULT_TYPE # define UNIT_LIB_DEFAULT_TYPE double #endif //-------------------- // INCLUDES //-------------------- #include #include #include #include #include #include #include #if !defined(UNIT_LIB_DISABLE_IOSTREAM) #include #include #include //------------------------------ // STRING FORMATTER //------------------------------ namespace units { namespace detail { template std::string to_string(const T& t) { std::string str{ std::to_string(t) }; int offset{ 1 }; // remove trailing decimal points for integer value units. Locale aware! struct lconv * lc; lc = localeconv(); char decimalPoint = *lc->decimal_point; if (str.find_last_not_of('0') == str.find(decimalPoint)) { offset = 0; } str.erase(str.find_last_not_of('0') + offset, std::string::npos); return str; } } } #endif namespace units { template inline constexpr const char* name(const T&); template inline constexpr const char* abbreviation(const T&); } //------------------------------ // MACROS //------------------------------ /** * @def UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, definition) * @brief Helper macro for generating the boiler-plate code generating the tags of a new unit. * @details The macro generates singular, plural, and abbreviated forms * of the unit definition (e.g. `meter`, `meters`, and `m`), as aliases for the * unit tag. * @param namespaceName namespace in which the new units will be encapsulated. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param namePlural - plural version of the unit name, e.g. 'meters' * @param abbreviation - abbreviated unit name, e.g. 'm' * @param definition - the variadic parameter is used for the definition of the unit * (e.g. `unit, units::category::length_unit>`) * @note a variadic template is used for the definition to allow templates with * commas to be easily expanded. All the variadic 'arguments' should together * comprise the unit definition. */ #define UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, /*definition*/...)\ namespace namespaceName\ {\ /** @name Units (full names plural) */ /** @{ */ typedef __VA_ARGS__ namePlural; /** @} */\ /** @name Units (full names singular) */ /** @{ */ typedef namePlural nameSingular; /** @} */\ /** @name Units (abbreviated) */ /** @{ */ typedef namePlural abbreviation; /** @} */\ } /** * @def UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular) * @brief Macro for generating the boiler-plate code for the unit_t type definition. * @details The macro generates the definition of the unit container types, e.g. `meter_t` * @param namespaceName namespace in which the new units will be encapsulated. * @param nameSingular singular version of the unit name, e.g. 'meter' */ #define UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\ namespace namespaceName\ {\ /** @name Unit Containers */ /** @{ */ typedef unit_t nameSingular ## _t; /** @} */\ } /** * @def UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular,underlyingType) * @brief Macro for generating the boiler-plate code for a unit_t type definition with a non-default underlying type. * @details The macro generates the definition of the unit container types, e.g. `meter_t` * @param namespaceName namespace in which the new units will be encapsulated. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param underlyingType the underlying type */ #define UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular, underlyingType)\ namespace namespaceName\ {\ /** @name Unit Containers */ /** @{ */ typedef unit_t nameSingular ## _t; /** @} */\ } /** * @def UNIT_ADD_IO(namespaceName,nameSingular, abbreviation) * @brief Macro for generating the boiler-plate code needed for I/O for a new unit. * @details The macro generates the code to insert units into an ostream. It * prints both the value and abbreviation of the unit when invoked. * @param namespaceName namespace in which the new units will be encapsulated. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param abbrev - abbreviated unit name, e.g. 'm' * @note When UNIT_LIB_DISABLE_IOSTREAM is defined, the macro does not generate any code */ #if defined(UNIT_LIB_DISABLE_IOSTREAM) #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev) #else #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)\ namespace namespaceName\ {\ inline std::ostream& operator<<(std::ostream& os, const nameSingular ## _t& obj) \ {\ os << obj() << " "#abbrev; return os; \ }\ inline std::string to_string(const nameSingular ## _t& obj)\ {\ return units::detail::to_string(obj()) + std::string(" "#abbrev);\ }\ } #endif /** * @def UNIT_ADD_NAME(namespaceName,nameSingular,abbreviation) * @brief Macro for generating constexpr names/abbreviations for units. * @details The macro generates names for units. E.g. name() of 1_m would be "meter", and * abbreviation would be "m". * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param abbreviation - abbreviated unit name, e.g. 'm' */ #define UNIT_ADD_NAME(namespaceName, nameSingular, abbrev)\ template<> inline constexpr const char* name(const namespaceName::nameSingular ## _t&)\ {\ return #nameSingular;\ }\ template<> inline constexpr const char* abbreviation(const namespaceName::nameSingular ## _t&)\ {\ return #abbrev;\ } /** * @def UNIT_ADD_LITERALS(namespaceName,nameSingular,abbreviation) * @brief Macro for generating user-defined literals for units. * @details The macro generates user-defined literals for units. A literal suffix is created * using the abbreviation (e.g. `10.0_m`). * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param abbreviation - abbreviated unit name, e.g. 'm' * @note When UNIT_HAS_LITERAL_SUPPORT is not defined, the macro does not generate any code */ #if defined(UNIT_HAS_LITERAL_SUPPORT) #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)\ namespace literals\ {\ inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation(long double d)\ {\ return namespaceName::nameSingular ## _t(static_cast(d));\ }\ inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation (unsigned long long d)\ {\ return namespaceName::nameSingular ## _t(static_cast(d));\ }\ } #else #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation) #endif /** * @def UNIT_ADD(namespaceName,nameSingular, namePlural, abbreviation, definition) * @brief Macro for generating the boiler-plate code needed for a new unit. * @details The macro generates singular, plural, and abbreviated forms * of the unit definition (e.g. `meter`, `meters`, and `m`), as well as the * appropriately named unit container (e.g. `meter_t`). A literal suffix is created * using the abbreviation (e.g. `10.0_m`). It also defines a class-specific * cout function which prints both the value and abbreviation of the unit when invoked. * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param namePlural - plural version of the unit name, e.g. 'meters' * @param abbreviation - abbreviated unit name, e.g. 'm' * @param definition - the variadic parameter is used for the definition of the unit * (e.g. `unit, units::category::length_unit>`) * @note a variadic template is used for the definition to allow templates with * commas to be easily expanded. All the variadic 'arguments' should together * comprise the unit definition. */ #define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\ UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\ UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\ UNIT_ADD_NAME(namespaceName,nameSingular, abbreviation)\ UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\ UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation) /** * @def UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName,nameSingular, namePlural, abbreviation, underlyingType, definition) * @brief Macro for generating the boiler-plate code needed for a new unit with a non-default underlying type. * @details The macro generates singular, plural, and abbreviated forms * of the unit definition (e.g. `meter`, `meters`, and `m`), as well as the * appropriately named unit container (e.g. `meter_t`). A literal suffix is created * using the abbreviation (e.g. `10.0_m`). It also defines a class-specific * cout function which prints both the value and abbreviation of the unit when invoked. * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param namePlural - plural version of the unit name, e.g. 'meters' * @param abbreviation - abbreviated unit name, e.g. 'm' * @param underlyingType - the underlying type, e.g. 'int' or 'float' * @param definition - the variadic parameter is used for the definition of the unit * (e.g. `unit, units::category::length_unit>`) * @note a variadic template is used for the definition to allow templates with * commas to be easily expanded. All the variadic 'arguments' should together * comprise the unit definition. */ #define UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName, nameSingular, namePlural, abbreviation, underlyingType, /*definition*/...)\ UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\ UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular,underlyingType)\ UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\ UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation) /** * @def UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation) * @brief Macro to create decibel container and literals for an existing unit type. * @details This macro generates the decibel unit container, cout overload, and literal definitions. * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the base unit name, e.g. 'watt' * @param abbreviation - abbreviated decibel unit name, e.g. 'dBW' */ #define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)\ namespace namespaceName\ {\ /** @name Unit Containers */ /** @{ */ typedef unit_t abbreviation ## _t; /** @} */\ }\ UNIT_ADD_IO(namespaceName, abbreviation, abbreviation)\ UNIT_ADD_LITERALS(namespaceName, abbreviation, abbreviation) /** * @def UNIT_ADD_CATEGORY_TRAIT(unitCategory, baseUnit) * @brief Macro to create the `is_category_unit` type trait. * @details This trait allows users to test whether a given type matches * an intended category. This macro comprises all the boiler-plate * code necessary to do so. * @param unitCategory The name of the category of unit, e.g. length or mass. */ #define UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\ namespace traits\ {\ /** @cond */\ namespace detail\ {\ template struct is_ ## unitCategory ## _unit_impl : std::false_type {};\ template\ struct is_ ## unitCategory ## _unit_impl> : std::is_same>::base_unit_type>, units::category::unitCategory ## _unit>::type {};\ template class N>\ struct is_ ## unitCategory ## _unit_impl> : std::is_same>::unit_type>, units::category::unitCategory ## _unit>::type {};\ }\ /** @endcond */\ } #if defined(UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT) #define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\ namespace traits\ {\ template struct is_ ## unitCategory ## _unit : std::integral_constant>::value...>::value> {};\ } #else #define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\ namespace traits\ {\ template\ struct is_ ## unitCategory ## _unit : std::integral_constant::type>::value &&\ units::traits::detail::is_ ## unitCategory ## _unit_impl::type>::value &&\ units::traits::detail::is_ ## unitCategory ## _unit_impl::type>::value>{};\ } #endif #define UNIT_ADD_CATEGORY_TRAIT(unitCategory)\ UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\ /** @ingroup TypeTraits*/\ /** @brief Trait which tests whether a type represents a unit of unitCategory*/\ /** @details Inherits from `std::true_type` or `std::false_type`. Use `is_ ## unitCategory ## _unit::value` to test the unit represents a unitCategory quantity.*/\ /** @tparam T one or more types to test*/\ UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory) /** * @def UNIT_ADD_WITH_METRIC_PREFIXES(nameSingular, namePlural, abbreviation, definition) * @brief Macro for generating the boiler-plate code needed for a new unit, including its metric * prefixes from femto to peta. * @details See UNIT_ADD. In addition to generating the unit definition and containers '(e.g. `meters` and 'meter_t', * it also creates corresponding units with metric suffixes such as `millimeters`, and `millimeter_t`), as well as the * literal suffixes (e.g. `10.0_mm`). * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'meter' * @param namePlural - plural version of the unit name, e.g. 'meters' * @param abbreviation - abbreviated unit name, e.g. 'm' * @param definition - the variadic parameter is used for the definition of the unit * (e.g. `unit, units::category::length_unit>`) * @note a variadic template is used for the definition to allow templates with * commas to be easily expanded. All the variadic 'arguments' should together * comprise the unit definition. */ #define UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\ UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\ UNIT_ADD(namespaceName, femto ## nameSingular, femto ## namePlural, f ## abbreviation, femto)\ UNIT_ADD(namespaceName, pico ## nameSingular, pico ## namePlural, p ## abbreviation, pico)\ UNIT_ADD(namespaceName, nano ## nameSingular, nano ## namePlural, n ## abbreviation, nano)\ UNIT_ADD(namespaceName, micro ## nameSingular, micro ## namePlural, u ## abbreviation, micro)\ UNIT_ADD(namespaceName, milli ## nameSingular, milli ## namePlural, m ## abbreviation, milli)\ UNIT_ADD(namespaceName, centi ## nameSingular, centi ## namePlural, c ## abbreviation, centi)\ UNIT_ADD(namespaceName, deci ## nameSingular, deci ## namePlural, d ## abbreviation, deci)\ UNIT_ADD(namespaceName, deca ## nameSingular, deca ## namePlural, da ## abbreviation, deca)\ UNIT_ADD(namespaceName, hecto ## nameSingular, hecto ## namePlural, h ## abbreviation, hecto)\ UNIT_ADD(namespaceName, kilo ## nameSingular, kilo ## namePlural, k ## abbreviation, kilo)\ UNIT_ADD(namespaceName, mega ## nameSingular, mega ## namePlural, M ## abbreviation, mega)\ UNIT_ADD(namespaceName, giga ## nameSingular, giga ## namePlural, G ## abbreviation, giga)\ UNIT_ADD(namespaceName, tera ## nameSingular, tera ## namePlural, T ## abbreviation, tera)\ UNIT_ADD(namespaceName, peta ## nameSingular, peta ## namePlural, P ## abbreviation, peta)\ /** * @def UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(nameSingular, namePlural, abbreviation, definition) * @brief Macro for generating the boiler-plate code needed for a new unit, including its metric * prefixes from femto to peta, and binary prefixes from kibi to exbi. * @details See UNIT_ADD. In addition to generating the unit definition and containers '(e.g. `bytes` and 'byte_t', * it also creates corresponding units with metric suffixes such as `millimeters`, and `millimeter_t`), as well as the * literal suffixes (e.g. `10.0_B`). * @param namespaceName namespace in which the new units will be encapsulated. All literal values * are placed in the `units::literals` namespace. * @param nameSingular singular version of the unit name, e.g. 'byte' * @param namePlural - plural version of the unit name, e.g. 'bytes' * @param abbreviation - abbreviated unit name, e.g. 'B' * @param definition - the variadic parameter is used for the definition of the unit * (e.g. `unit, units::category::data_unit>`) * @note a variadic template is used for the definition to allow templates with * commas to be easily expanded. All the variadic 'arguments' should together * comprise the unit definition. */ #define UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\ UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\ UNIT_ADD(namespaceName, kibi ## nameSingular, kibi ## namePlural, Ki ## abbreviation, kibi)\ UNIT_ADD(namespaceName, mebi ## nameSingular, mebi ## namePlural, Mi ## abbreviation, mebi)\ UNIT_ADD(namespaceName, gibi ## nameSingular, gibi ## namePlural, Gi ## abbreviation, gibi)\ UNIT_ADD(namespaceName, tebi ## nameSingular, tebi ## namePlural, Ti ## abbreviation, tebi)\ UNIT_ADD(namespaceName, pebi ## nameSingular, pebi ## namePlural, Pi ## abbreviation, pebi)\ UNIT_ADD(namespaceName, exbi ## nameSingular, exbi ## namePlural, Ei ## abbreviation, exbi) //-------------------- // UNITS NAMESPACE //-------------------- /** * @namespace units * @brief Unit Conversion Library namespace */ namespace units { //---------------------------------- // DOXYGEN //---------------------------------- /** * @defgroup UnitContainers Unit Containers * @brief Defines a series of classes which contain dimensioned values. Unit containers * store a value, and support various arithmetic operations. */ /** * @defgroup UnitTypes Unit Types * @brief Defines a series of classes which represent units. These types are tags used by * the conversion function, to create compound units, or to create `unit_t` types. * By themselves, they are not containers and have no stored value. */ /** * @defgroup UnitManipulators Unit Manipulators * @brief Defines a series of classes used to manipulate unit types, such as `inverse<>`, `squared<>`, and metric prefixes. * Unit manipulators can be chained together, e.g. `inverse>>` to * represent picoseconds^-2. */ /** * @defgroup CompileTimeUnitManipulators Compile-time Unit Manipulators * @brief Defines a series of classes used to manipulate `unit_value_t` types at compile-time, such as `unit_value_add<>`, `unit_value_sqrt<>`, etc. * Compile-time manipulators can be chained together, e.g. `unit_value_sqrt, unit_value_power>>` to * represent `c = sqrt(a^2 + b^2). */ /** * @defgroup UnitMath Unit Math * @brief Defines a collection of unit-enabled, strongly-typed versions of `` functions. * @details Includes most c++11 extensions. */ /** * @defgroup Conversion Explicit Conversion * @brief Functions used to convert values of one logical type to another. */ /** * @defgroup TypeTraits Type Traits * @brief Defines a series of classes to obtain unit type information at compile-time. */ //------------------------------ // FORWARD DECLARATIONS //------------------------------ /** @cond */ // DOXYGEN IGNORE namespace constants { namespace detail { static constexpr const UNIT_LIB_DEFAULT_TYPE PI_VAL = 3.14159265358979323846264338327950288419716939937510; } } /** @endcond */ // END DOXYGEN IGNORE //------------------------------ // RATIO TRAITS //------------------------------ /** * @ingroup TypeTraits * @{ */ /** @cond */ // DOXYGEN IGNORE namespace detail { /// has_num implementation. template struct has_num_impl { template static constexpr auto test(U*)->std::is_integral {return std::is_integral{}; } template static constexpr std::false_type test(...) { return std::false_type{}; } using type = decltype(test(0)); }; } /** * @brief Trait which checks for the existence of a static numerator. * @details Inherits from `std::true_type` or `std::false_type`. Use `has_num::value` to test * whether `class T` has a numerator static member. */ template struct has_num : units::detail::has_num_impl::type {}; namespace detail { /// has_den implementation. template struct has_den_impl { template static constexpr auto test(U*)->std::is_integral { return std::is_integral{}; } template static constexpr std::false_type test(...) { return std::false_type{}; } using type = decltype(test(0)); }; } /** * @brief Trait which checks for the existence of a static denominator. * @details Inherits from `std::true_type` or `std::false_type`. Use `has_den::value` to test * whether `class T` has a denominator static member. */ template struct has_den : units::detail::has_den_impl::type {}; /** @endcond */ // END DOXYGEN IGNORE namespace traits { /** * @brief Trait that tests whether a type represents a std::ratio. * @details Inherits from `std::true_type` or `std::false_type`. Use `is_ratio::value` to test * whether `class T` implements a std::ratio. */ template struct is_ratio : std::integral_constant::value && has_den::value> {}; } //------------------------------ // UNIT TRAITS //------------------------------ /** @cond */ // DOXYGEN IGNORE /** * @brief void type. * @details Helper class for creating type traits. */ template struct void_t { typedef void type; }; /** * @brief parameter pack for boolean arguments. */ template struct bool_pack {}; /** * @brief Trait which tests that a set of other traits are all true. */ template struct all_true : std::is_same, units::bool_pack> {}; /** @endcond */ // DOXYGEN IGNORE /** * @brief namespace representing type traits which can access the properties of types provided by the units library. */ namespace traits { #ifdef FOR_DOXYGEN_PURPOSES_ONLY /** * @ingroup TypeTraits * @brief Traits class defining the properties of units. * @details The units library determines certain properties of the units passed to * them and what they represent by using the members of the corresponding * unit_traits instantiation. */ template struct unit_traits { typedef typename T::base_unit_type base_unit_type; ///< Unit type that the unit was derived from. May be a `base_unit` or another `unit`. Use the `base_unit_of` trait to find the SI base unit type. This will be `void` if type `T` is not a unit. typedef typename T::conversion_ratio conversion_ratio; ///< `std::ratio` representing the conversion factor to the `base_unit_type`. This will be `void` if type `T` is not a unit. typedef typename T::pi_exponent_ratio pi_exponent_ratio; ///< `std::ratio` representing the exponent of pi to be used in the conversion. This will be `void` if type `T` is not a unit. typedef typename T::translation_ratio translation_ratio; ///< `std::ratio` representing a datum translation to the base unit (i.e. degrees C to degrees F conversion). This will be `void` if type `T` is not a unit. }; #endif /** @cond */ // DOXYGEN IGNORE /** * @brief unit traits implementation for classes which are not units. */ template struct unit_traits { typedef void base_unit_type; typedef void conversion_ratio; typedef void pi_exponent_ratio; typedef void translation_ratio; }; template struct unit_traits ::type> { typedef typename T::base_unit_type base_unit_type; ///< Unit type that the unit was derived from. May be a `base_unit` or another `unit`. Use the `base_unit_of` trait to find the SI base unit type. This will be `void` if type `T` is not a unit. typedef typename T::conversion_ratio conversion_ratio; ///< `std::ratio` representing the conversion factor to the `base_unit_type`. This will be `void` if type `T` is not a unit. typedef typename T::pi_exponent_ratio pi_exponent_ratio; ///< `std::ratio` representing the exponent of pi to be used in the conversion. This will be `void` if type `T` is not a unit. typedef typename T::translation_ratio translation_ratio; ///< `std::ratio` representing a datum translation to the base unit (i.e. degrees C to degrees F conversion). This will be `void` if type `T` is not a unit. }; /** @endcond */ // END DOXYGEN IGNORE } /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief helper type to identify base units. * @details A non-templated base class for `base_unit` which enables RTTI testing. */ struct _base_unit_t {}; } /** @endcond */ // END DOXYGEN IGNORE namespace traits { /** * @ingroup TypeTraits * @brief Trait which tests if a class is a `base_unit` type. * @details Inherits from `std::true_type` or `std::false_type`. Use `is_base_unit::value` to test * whether `class T` implements a `base_unit`. */ template struct is_base_unit : std::is_base_of {}; } /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief helper type to identify units. * @details A non-templated base class for `unit` which enables RTTI testing. */ struct _unit {}; template using meter_ratio = std::ratio; } /** @endcond */ // END DOXYGEN IGNORE namespace traits { /** * @ingroup TypeTraits * @brief Traits which tests if a class is a `unit` * @details Inherits from `std::true_type` or `std::false_type`. Use `is_unit::value` to test * whether `class T` implements a `unit`. */ template struct is_unit : std::is_base_of::type {}; } /** @} */ // end of TypeTraits //------------------------------ // BASE UNIT CLASS //------------------------------ /** * @ingroup UnitTypes * @brief Class representing SI base unit types. * @details Base units are represented by a combination of `std::ratio` template parameters, each * describing the exponent of the type of unit they represent. Example: meters per second * would be described by a +1 exponent for meters, and a -1 exponent for seconds, thus: * `base_unit, std::ratio<0>, std::ratio<-1>>` * @tparam Meter `std::ratio` representing the exponent value for meters. * @tparam Kilogram `std::ratio` representing the exponent value for kilograms. * @tparam Second `std::ratio` representing the exponent value for seconds. * @tparam Radian `std::ratio` representing the exponent value for radians. Although radians are not SI base units, they are included because radians are described by the SI as m * m^-1, which would make them indistinguishable from scalars. * @tparam Ampere `std::ratio` representing the exponent value for amperes. * @tparam Kelvin `std::ratio` representing the exponent value for Kelvin. * @tparam Mole `std::ratio` representing the exponent value for moles. * @tparam Candela `std::ratio` representing the exponent value for candelas. * @tparam Byte `std::ratio` representing the exponent value for bytes. * @sa category for type aliases for SI base_unit types. */ template, class Kilogram = std::ratio<0>, class Second = std::ratio<0>, class Radian = std::ratio<0>, class Ampere = std::ratio<0>, class Kelvin = std::ratio<0>, class Mole = std::ratio<0>, class Candela = std::ratio<0>, class Byte = std::ratio<0>> struct base_unit : units::detail::_base_unit_t { static_assert(traits::is_ratio::value, "Template parameter `Meter` must be a `std::ratio` representing the exponent of meters the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Kilogram` must be a `std::ratio` representing the exponent of kilograms the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Second` must be a `std::ratio` representing the exponent of seconds the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Ampere` must be a `std::ratio` representing the exponent of amperes the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Kelvin` must be a `std::ratio` representing the exponent of kelvin the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Candela` must be a `std::ratio` representing the exponent of candelas the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Mole` must be a `std::ratio` representing the exponent of moles the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Radian` must be a `std::ratio` representing the exponent of radians the unit has"); static_assert(traits::is_ratio::value, "Template parameter `Byte` must be a `std::ratio` representing the exponent of bytes the unit has"); typedef Meter meter_ratio; typedef Kilogram kilogram_ratio; typedef Second second_ratio; typedef Radian radian_ratio; typedef Ampere ampere_ratio; typedef Kelvin kelvin_ratio; typedef Mole mole_ratio; typedef Candela candela_ratio; typedef Byte byte_ratio; }; //------------------------------ // UNIT CATEGORIES //------------------------------ /** * @brief namespace representing the implemented base and derived unit types. These will not generally be needed by library users. * @sa base_unit for the definition of the category parameters. */ namespace category { // SCALAR (DIMENSIONLESS) TYPES typedef base_unit<> scalar_unit; ///< Represents a quantity with no dimension. typedef base_unit<> dimensionless_unit; ///< Represents a quantity with no dimension. // SI BASE UNIT TYPES // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY typedef base_unit> length_unit; ///< Represents an SI base unit of length typedef base_unit, std::ratio<1>> mass_unit; ///< Represents an SI base unit of mass typedef base_unit, std::ratio<0>, std::ratio<1>> time_unit; ///< Represents an SI base unit of time typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<1>> angle_unit; ///< Represents an SI base unit of angle typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> current_unit; ///< Represents an SI base unit of current typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> temperature_unit; ///< Represents an SI base unit of temperature typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> substance_unit; ///< Represents an SI base unit of amount of substance typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> luminous_intensity_unit; ///< Represents an SI base unit of luminous intensity // SI DERIVED UNIT TYPES // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>> solid_angle_unit; ///< Represents an SI derived unit of solid angle typedef base_unit, std::ratio<0>, std::ratio<-1>> frequency_unit; ///< Represents an SI derived unit of frequency typedef base_unit, std::ratio<0>, std::ratio<-1>> velocity_unit; ///< Represents an SI derived unit of velocity typedef base_unit, std::ratio<0>, std::ratio<-1>, std::ratio<1>> angular_velocity_unit; ///< Represents an SI derived unit of angular velocity typedef base_unit, std::ratio<0>, std::ratio<-2>> acceleration_unit; ///< Represents an SI derived unit of acceleration typedef base_unit, std::ratio<1>, std::ratio<-2>> force_unit; ///< Represents an SI derived unit of force typedef base_unit, std::ratio<1>, std::ratio<-2>> pressure_unit; ///< Represents an SI derived unit of pressure typedef base_unit, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<1>> charge_unit; ///< Represents an SI derived unit of charge typedef base_unit, std::ratio<1>, std::ratio<-2>> energy_unit; ///< Represents an SI derived unit of energy typedef base_unit, std::ratio<1>, std::ratio<-3>> power_unit; ///< Represents an SI derived unit of power typedef base_unit, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-1>> voltage_unit; ///< Represents an SI derived unit of voltage typedef base_unit, std::ratio<-1>, std::ratio<4>, std::ratio<0>, std::ratio<2>> capacitance_unit; ///< Represents an SI derived unit of capacitance typedef base_unit, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-2>> impedance_unit; ///< Represents an SI derived unit of impedance typedef base_unit, std::ratio<-1>, std::ratio<3>, std::ratio<0>, std::ratio<2>> conductance_unit; ///< Represents an SI derived unit of conductance typedef base_unit, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_flux_unit; ///< Represents an SI derived unit of magnetic flux typedef base_unit, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_field_strength_unit; ///< Represents an SI derived unit of magnetic field strength typedef base_unit, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-2>> inductance_unit; ///< Represents an SI derived unit of inductance typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> luminous_flux_unit; ///< Represents an SI derived unit of luminous flux typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> illuminance_unit; ///< Represents an SI derived unit of illuminance typedef base_unit, std::ratio<0>, std::ratio<-1>> radioactivity_unit; ///< Represents an SI derived unit of radioactivity // OTHER UNIT TYPES // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY typedef base_unit, std::ratio<1>, std::ratio<-2>> torque_unit; ///< Represents an SI derived unit of torque typedef base_unit> area_unit; ///< Represents an SI derived unit of area typedef base_unit> volume_unit; ///< Represents an SI derived unit of volume typedef base_unit, std::ratio<1>> density_unit; ///< Represents an SI derived unit of density typedef base_unit<> concentration_unit; ///< Represents a unit of concentration typedef base_unit, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> data_unit; ///< Represents a unit of data size typedef base_unit, std::ratio<0>, std::ratio<-1>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> data_transfer_rate_unit; ///< Represents a unit of data transfer rate } //------------------------------ // UNIT CLASSES //------------------------------ /** @cond */ // DOXYGEN IGNORE /** * @brief unit type template specialization for units derived from base units. */ template struct unit; template struct unit, PiExponent, Translation> : units::detail::_unit { static_assert(traits::is_ratio::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`."); static_assert(traits::is_ratio::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has."); static_assert(traits::is_ratio::value, "Template parameter `Translation` must be a `std::ratio` representing an additive translation required by the unit conversion."); typedef typename units::base_unit base_unit_type; typedef Conversion conversion_ratio; typedef Translation translation_ratio; typedef PiExponent pi_exponent_ratio; }; /** @endcond */ // END DOXYGEN IGNORE /** * @brief Type representing an arbitrary unit. * @ingroup UnitTypes * @details `unit` types are used as tags for the `conversion` function. They are *not* containers * (see `unit_t` for a container class). Each unit is defined by: * * - A `std::ratio` defining the conversion factor to the base unit type. (e.g. `std::ratio<1,12>` for inches to feet) * - A base unit that the unit is derived from (or a unit category. Must be of type `unit` or `base_unit`) * - An exponent representing factors of PI required by the conversion. (e.g. `std::ratio<-1>` for a radians to degrees conversion) * - a ratio representing a datum translation required for the conversion (e.g. `std::ratio<32>` for a fahrenheit to celsius conversion) * * Typically, a specific unit, like `meters`, would be implemented as a type alias * of `unit`, i.e. `using meters = unit, units::category::length_unit`, or * `using inches = unit, feet>`. * @tparam Conversion std::ratio representing scalar multiplication factor. * @tparam BaseUnit Unit type which this unit is derived from. May be a `base_unit`, or another `unit`. * @tparam PiExponent std::ratio representing the exponent of pi required by the conversion. * @tparam Translation std::ratio representing any datum translation required by the conversion. */ template, class Translation = std::ratio<0>> struct unit : units::detail::_unit { static_assert(traits::is_unit::value, "Template parameter `BaseUnit` must be a `unit` type."); static_assert(traits::is_ratio::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`."); static_assert(traits::is_ratio::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has."); typedef typename units::traits::unit_traits::base_unit_type base_unit_type; typedef typename std::ratio_multiply conversion_ratio; typedef typename std::ratio_add pi_exponent_ratio; typedef typename std::ratio_add, typename BaseUnit::translation_ratio> translation_ratio; }; //------------------------------ // BASE UNIT MANIPULATORS //------------------------------ /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief base_unit_of trait implementation * @details recursively seeks base_unit type that a unit is derived from. Since units can be * derived from other units, the `base_unit_type` typedef may not represent this value. */ template struct base_unit_of_impl; template struct base_unit_of_impl> : base_unit_of_impl {}; template struct base_unit_of_impl> { typedef base_unit type; }; template<> struct base_unit_of_impl { typedef void type; }; } /** @endcond */ // END DOXYGEN IGNORE namespace traits { /** * @brief Trait which returns the `base_unit` type that a unit is originally derived from. * @details Since units can be derived from other `unit` types in addition to `base_unit` types, * the `base_unit_type` typedef will not always be a `base_unit` (or unit category). * Since compatible */ template using base_unit_of = typename units::detail::base_unit_of_impl::type; } /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief implementation of base_unit_multiply * @details 'multiples' (adds exponent ratios of) two base unit types. Base units can be found * using `base_unit_of`. */ template struct base_unit_multiply_impl; template struct base_unit_multiply_impl, base_unit> { using type = base_unit...>; }; /** * @brief represents type of two base units multiplied together */ template using base_unit_multiply = typename base_unit_multiply_impl::type; /** * @brief implementation of base_unit_divide * @details 'dived' (subtracts exponent ratios of) two base unit types. Base units can be found * using `base_unit_of`. */ template struct base_unit_divide_impl; template struct base_unit_divide_impl, base_unit> { using type = base_unit...>; }; /** * @brief represents the resulting type of `base_unit` U1 divided by U2. */ template using base_unit_divide = typename base_unit_divide_impl::type; /** * @brief implementation of inverse_base * @details multiplies all `base_unit` exponent ratios by -1. The resulting type represents * the inverse base unit of the given `base_unit` type. */ template struct inverse_base_impl; template struct inverse_base_impl> { using type = base_unit>...>; }; /** * @brief represent the inverse type of `class U` * @details E.g. if `U` is `length_unit`, then `inverse` will represent `length_unit^-1`. */ template using inverse_base = typename inverse_base_impl::type; /** * @brief implementation of `squared_base` * @details multiplies all the exponent ratios of the given class by 2. The resulting type is * equivalent to the given type squared. */ template struct squared_base_impl; template struct squared_base_impl> { using type = base_unit>...>; }; /** * @brief represents the type of a `base_unit` squared. * @details E.g. `squared` will represent `length_unit^2`. */ template using squared_base = typename squared_base_impl::type; /** * @brief implementation of `cubed_base` * @details multiplies all the exponent ratios of the given class by 3. The resulting type is * equivalent to the given type cubed. */ template struct cubed_base_impl; template struct cubed_base_impl> { using type = base_unit>...>; }; /** * @brief represents the type of a `base_unit` cubed. * @details E.g. `cubed` will represent `length_unit^3`. */ template using cubed_base = typename cubed_base_impl::type; /** * @brief implementation of `sqrt_base` * @details divides all the exponent ratios of the given class by 2. The resulting type is * equivalent to the square root of the given type. */ template struct sqrt_base_impl; template struct sqrt_base_impl> { using type = base_unit>...>; }; /** * @brief represents the square-root type of a `base_unit`. * @details E.g. `sqrt` will represent `length_unit^(1/2)`. */ template using sqrt_base = typename sqrt_base_impl::type; /** * @brief implementation of `cbrt_base` * @details divides all the exponent ratios of the given class by 3. The resulting type is * equivalent to the given type's cube-root. */ template struct cbrt_base_impl; template struct cbrt_base_impl> { using type = base_unit>...>; }; /** * @brief represents the cube-root type of a `base_unit` . * @details E.g. `cbrt` will represent `length_unit^(1/3)`. */ template using cbrt_base = typename cbrt_base_impl::type; } /** @endcond */ // END DOXYGEN IGNORE //------------------------------ // UNIT MANIPULATORS //------------------------------ /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief implementation of `unit_multiply`. * @details multiplies two units. The base unit becomes the base units of each with their exponents * added together. The conversion factors of each are multiplied by each other. Pi exponent ratios * are added, and datum translations are removed. */ template struct unit_multiply_impl { using type = unit < std::ratio_multiply, base_unit_multiply , traits::base_unit_of>, std::ratio_add, std::ratio < 0 >> ; }; /** * @brief represents the type of two units multiplied together. * @details recalculates conversion and exponent ratios at compile-time. */ template using unit_multiply = typename unit_multiply_impl::type; /** * @brief implementation of `unit_divide`. * @details divides two units. The base unit becomes the base units of each with their exponents * subtracted from each other. The conversion factors of each are divided by each other. Pi exponent ratios * are subtracted, and datum translations are removed. */ template struct unit_divide_impl { using type = unit < std::ratio_divide, base_unit_divide, traits::base_unit_of>, std::ratio_subtract, std::ratio < 0 >> ; }; /** * @brief represents the type of two units divided by each other. * @details recalculates conversion and exponent ratios at compile-time. */ template using unit_divide = typename unit_divide_impl::type; /** * @brief implementation of `inverse` * @details inverts a unit (equivalent to 1/unit). The `base_unit` and pi exponents are all multiplied by * -1. The conversion ratio numerator and denominator are swapped. Datum translation * ratios are removed. */ template struct inverse_impl { using type = unit < std::ratio, inverse_base::base_unit_type>>, std::ratio_multiply::pi_exponent_ratio, std::ratio<-1>>, std::ratio < 0 >> ; // inverses are rates or change, the translation factor goes away. }; } /** @endcond */ // END DOXYGEN IGNORE /** * @brief represents the inverse unit type of `class U`. * @ingroup UnitManipulators * @tparam U `unit` type to invert. * @details E.g. `inverse` will represent meters^-1 (i.e. 1/meters). */ template using inverse = typename units::detail::inverse_impl::type; /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief implementation of `squared` * @details Squares the conversion ratio, `base_unit` exponents, pi exponents, and removes * datum translation ratios. */ template struct squared_impl { static_assert(traits::is_unit::value, "Template parameter `Unit` must be a `unit` type."); using Conversion = typename Unit::conversion_ratio; using type = unit < std::ratio_multiply, squared_base>, std::ratio_multiply>, typename Unit::translation_ratio > ; }; } /** @endcond */ // END DOXYGEN IGNORE /** * @brief represents the unit type of `class U` squared * @ingroup UnitManipulators * @tparam U `unit` type to square. * @details E.g. `square` will represent meters^2. */ template using squared = typename units::detail::squared_impl::type; /** @cond */ // DOXYGEN IGNORE namespace detail { /** * @brief implementation of `cubed` * @details Cubes the conversion ratio, `base_unit` exponents, pi exponents, and removes * datum translation ratios. */ template struct cubed_impl { static_assert(traits::is_unit::value, "Template parameter `Unit` must be a `unit` type."); using Conversion = typename Unit::conversion_ratio; using type = unit < std::ratio_multiply>, cubed_base>, std::ratio_multiply>, typename Unit::translation_ratio> ; }; } /** @endcond */ // END DOXYGEN IGNORE /** * @brief represents the type of `class U` cubed. * @ingroup UnitManipulators * @tparam U `unit` type to cube. * @details E.g. `cubed` will represent meters^3. */ template using cubed = typename units::detail::cubed_impl::type; /** @cond */ // DOXYGEN IGNORE namespace detail { //---------------------------------- // RATIO_SQRT IMPLEMENTATION //---------------------------------- using Zero = std::ratio<0>; using One = std::ratio<1>; template using Square = std::ratio_multiply; // Find the largest std::integer N such that Predicate::value is true. template