Coder Social home page Coder Social logo

bernedom / si Goto Github PK

View Code? Open in Web Editor NEW
486.0 13.0 40.0 59.27 MB

A header only C++ library that provides type safety and user defined literals for physical units

Home Page: https://si.dominikberner.ch/doc/

License: MIT License

CMake 1.44% C++ 96.55% Shell 2.00%
physical-units si-unit-conversion cplusplus-17 cplusplus-library cpp dimensional-analysis dimensions header-only physical-quantities units units-of-measure system-of-un

si's Introduction

-

Continuous Integration Codacy Badge API Documentation CodeQL

GitHub Releases GitHub license

SI - Type safety for physical units

A header only c++ library that provides type safety and user defined literals for handling physical values defined in the International System of Units regulated by the International Bureau of Weights and Measures (BIPM) and published in the SI brochure. For a quick start see the installation guide. Contributions and comments are welcome, please check the contribution guidelines for further information.

An illustrative example:

#include <SI/electric_charge.h>
#include <SI/mass.h>

using namespace SI::literals;

constexpr auto one_kilogram = 1.0_kg;
constexpr auto ten_coulomb = 5.0_A * 2.0_s;
constexpr auto half_an_ampere = ten_coulomb / 20.0_s;
constexpr auto thousand_grams = one_kilogram.as<SI::gram_t>();

void calculate_mass(const SI::kilo_gram_t<long double> &kg) {
  // do something meaningful here
}

int main(int, char **) {
  calculate_mass(one_kilogram);
  return 0;
}

SI provides conversions and arithmetic operations with values of any of the International System of Units with strong type safety at compile time. All units are special typedefs of the template struct SI::unit_t. Only the value of the unit is stored internally, the ratio (i.e. milli, micro, kilo...) is determined as a type trait to allow all units to have the same resolution across the whole implemented ratios. SI handles operations of units of the same ratios as well as when the ratios are different. See the documentation implementation details for further information. Operations between units of the same ratio are overhead-free, else there is an additional computation cost to adjust the values to the units. Passing the flag SI_DISABLE_IMPLICIT_RATIO_CONVERSION to the compiler implicit ratio conversion is not done and fails with a compiler error. See the continuous benchmark results for a comparison between the reference measurements and the implementation in SI.

It is possible to supply custom ratios to the built-in types and they are fully compatible for calculation with other units. However, the necessary literals or typedefs have to be supplied by the user. For instance SI::velocity_t<double, std::ratio<1000, 36>> would be "kilometre per one-hundredth-of-an-hour".

Converting between units is either done with the as<unit_t>() member function of unit_ or the free function SI::unit_cast<unit_t>(unit_t u). This will convert a value of the same type but a different ratio.

SI Base units

For each unit the available literals are the implemented ratios prefixed with an underscore. i.e. _mm. _km. Generally the ratios follow metric prefixes of the international system of units The typedefs are prefixed (or in rare cases interfixed) with the standard metric prefixes. i.e. metre_t, milli_metre_t, kilo_metre_t. The prefix or interfix is marked with an * in the tables below. Units that have defined typedefs and literals can be converted to strings using stream operators or the SI::to_string function. To use the stream operators, include the header file SI/stream.h

Unit Dimension Symbol Unit Symbol implemented ratios unit typedefs
Length L m 10-18 to 1018 *_metre_t
Time T s 10-18 to 100 and 60/1, 3600/1 *_seconds_t, minutes_t, hours_t
Mass* M kg 10-15 to 1018 *_gram_t, *_ton_t
Electric current I A 10-18 to 1018 *_ampere_t
Thermodynamic temperature** t K 10-18 to 1018 *_kelvin_t
Amount of substance N mol 10-18 to 1018 *_mol_t
Luminosity J cd 10-18 to 1018 *_candela_t

* for mass the base ratio is kg (not g) as defined in the SI unit table. So there is a mismatch between the literal prefix and the internal representation.

** The dimension symbol for thermodynamic temperature should be Θ (Theta), but the current implementation does not allow for non-ASCII symbols or multi-char symbols

Special Units

Unit Dimension Symbol Exponent Unit Symbol implemented ratios unit typedefs
Area L 2 m2 10-18 to 1018 square_*_metre_t
Volume L 3 m3 10-18 to 1018 cubic_*_metre_t
Frequency T -1 Hz 10-18 to 1018 *_hertz_t
Angle* r 1 rad 10-18 to 1 *_radian_t
Angle (Degrees)* r 1 deg micro, milli, 1 *_radian_t
Solid Angle* R 1 sr 10-18 to 1 *_steradian_t

* Angle, Angle (degree) and solid angle are simple containers, not containing any functionality to do angle/solid-angle computation such as an overflow after 2*pi. Converting between radians and degree might lose precision, especially if working with long doubles because the ratios not precise enough, as they have to be represented as long ints

Derived units with special names

All units that can be built from other units decay to the respective units by inverting the mathematical operation. I.e if Q = I * T then Q / I = T and Q / T = I

Unit Dimension Symbol Unit Symbol buildable from implemented literals unit typedefs
Velocity v m/s L / T m_p_s, km_p_h, _c metre_per_second_t, kilometre_per_second_t, speed_of_light_t
Acceleration a m/s^2 v / T, v^2 / L none none
Electric charge Q C I * T aC to EC *_coulomb_t
Electric potential U V P / I, E/Q aV to EV *_volt_t
Electric resistance O* Ohm (Ω) U / I, 1/G aOhm to EOhm *_ohm_t
Electric conductance G S I / U, 1/R aS to ES *_siemens_t
Electric capacity C F Q / U aF to EF *_farad_t
Force F N M * a aN to EN *_newton_t
Pressure p pa F / L^2 apa to Epa *_pascal_t
Energy E J F * L, p * L^3 aJ to EJ *_joule_t
Power P W E/T aW to EW *_watt_t
Magnetic Flux f* Wb U * T aWb to EWb *_weber_t
Magnetic Field B T f/L^2 aT to ET *_tesla_t
Momentum o* kg⋅m/s M * v none none
Inductance l H f / I aH to EH *_henry_t
Luminous flux m* lm J * R alm to Elm *_lumen_t
Luminance i* lx m / a alx to Elx *_lux_t
Radioactivity A Bq aBq to EBq *_becquerel_t
Absorbed Dose D Gy aGy to EGy *_gray_t
Equivalent Dose H Sv aSv to ESv *_sievert_t
Catalytic activity K kat N / T akat to Ekat *_katal_t
Surface flow s m^2/s L^2 / T none
Volumetric flow V m^3/s L^3 / T none
Angular frequency w* rad/s r / T none

* These dimensions do not yet have the correct symbols, because the current implementation does not allow for non-ASCII symbols or multi-char symbols. The dimension symbol for electric resistance should be Ω (Ohm) and for magnetic flux Φ (Phi). Luminance should be Eb. Angular velocity should be ω (omega). Luminous flux should be Φv which is even less supported than Φ (Phi) itself.

Non-Standard Units

Non standard units are not regulated by the BIPM but are accepted for use with the SI standard.

Unit Dimension Symbol literals implemented ratios unit typedefs
Astronomic Units of length L AU, ly, pc 149597870691:1 (AU), 9460730777119564:1 (ly), 30856775814913700:1 (pc) astronomic_unit_t (_AU), lightyear_t (_ly), parsec_t (_pc)

Building & compatibility

SI is a header-only library that uses C++17 features. Building is tested using cmake > 3.23 and verified for g++7, g++8, clang5, clang6, clang7, msvc 19, and AppleClang 10.0. I recommend using conan 2.0 to download any dependencies for testing, but can be used without it, if the tests are not built.

SI uses CMakeDeps generator of conan to find dependencies. To install the dependencies use

conan install . --output-folder=build --build=missing --settings=build_type=Debug

substitute --settings=build_type=Debug with --settings=build_type=Release to switch between debug and release builds.

By using the CMAkeDeps generator, you can either build manually or use the CMake presets provided.

cmake --preset=ci-ninja-debug
cmake --build build

Installing

The default installation location for SI is /usr/local/lib/SI. SI can be installed using raw cmake, cpack (cmakes package mechanism), or as a conan.io package provided from conan center

See the installation guide for detailed instructions

Including with FetchContent

Note: Getting SI as a conan package is preferred.

To install with CMake's FetchContent, add the following to your CMakeLists.txt

include(FetchContent)

FetchContent_Declare(
  SI
  GIT_REPOSITORY https://gitlab.com/bernedom/SI.git
  # This will get the latest version
  # To pin to a specific version or hash, add the version/hash here instead
  # (e.g. 2.5.1 or 63b267211a6f256f7ba8d5a26e17138bbcf95ba8)
  GIT_TAG main
)

FetchContent_MakeAvailable(SI)

# ...

# Link the library to your target. Change this as needed!
target_link_libraries(${PROJECT_NAME} PUBLIC SI::SI)

Packaging

SI is available as 'raw' download from this repository but also as conan package. Getting SI from conan-center is the preferred way.

Implementation details

For further information and deeper technical details refer to the implementation details document

Breaking changes between versions 1.x.x and versions 2.x.x

Versions above 2.0.0 will not be fully compatible with older versions because of the breaking changes mentioned in the changelog. From version 2.0.0 on the conan package is named lower case si to conform to the conan naming convention.

si's People

Contributors

abelfodil avatar bernedom avatar bladan-stag avatar clausklein avatar dependabot[bot] avatar jwillemsen avatar kicer86 avatar lgtm-migrator avatar matthewtolman avatar melg8 avatar timofurrer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

si's Issues

Getting inverse units

#include <SI/length.h>

using namespace SI::literals;
constexpr auto pitch = 2 / 1_mm; // OK, without constexpr, but need it

Expected behavior
I expected to pitch to be of type 2 mm exp -1 (2 per millimeter) ratio of -1

I/include/SI/detail/unit.h:474:33: error: ‘(2 / 0)’ is not a constant expression

Add a=v^2/s derived type

Acceleration derived from squared speed divided by length could be added as often used to calculate braking distances.

include/SI/acceleration.h:
BUILD_UNIT_FROM_DIVISON(acceleration_t, velocity_squared_t, length_t)

include/SI/velocity.h:

template <typename _type, typename _ratio>
using velocity_squared_t = detail::unit_t<'v', 2, _type, _ratio>;

Unable to build code from instructions: broken recipe (conan 2.0 issue?)

Describe the bug
I checked out the repo and tried to build the code and tests, so I could start playing with the library.

To Reproduce
Steps to reproduce the behavior:

  1. On a clean system, install conan: pip install conan
  2. Follow these instructions (https://github.com/bernedom/SI#building--compatibility)
  3. The cmake .. step fails, complaining about missing CMAKE_BUILD_TYPE setting
  4. Run cmake -DCMAKE_BUILD_TYPE=Debug .. instead. Now it complains about not having a conan profile.
  5. Create a conan profile: conan profile detect --force
  6. Re-run the command in step 4. Now it complains the recipe is broken

Error message from step 3:

-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Downloading conan.cmake from https://github.com/bernedom/cmake-conan
-- Conan: Automatic detection of conan settings from cmake
CMake Error at build/test/conan.cmake:82 (message):
  Please specify in command line CMAKE_BUILD_TYPE
  (-DCMAKE_BUILD_TYPE=Release)
Call Stack (most recent call first):
  build/test/conan.cmake:496 (conan_cmake_settings)
  test/CMakeLists.txt:21 (conan_cmake_run)


-- Configuring incomplete, errors occurred!
See also "/home/chogg/github/SI/build/CMakeFiles/CMakeOutput.log".

Error message from step 4:

-- Conan: Automatic detection of conan settings from cmake
-- Conan: Settings= -s;build_type=Debug;-s;compiler=gcc;-s;compiler.version=11;-s;compiler.libcxx=libstdc++11
-- Conan: checking conan executable
-- Conan: Found program /home/chogg/.local/bin/conan
-- Conan: Version found Conan version 2.0.7

-- Conan executing: /home/chogg/.local/bin/conan install /home/chogg/github/SI/test/conanfile.txt -s build_type=Debug -s compiler=gcc -s compiler.version=11 -s compiler.libcxx=libstdc++11 -g=cmake --build=missing
ERROR: The default build profile '/home/chogg/.conan2/profiles/default' doesn't exist.
You need to create a default profile (type 'conan profile detect' command)
or specify your own profile with '--profile:build=<myprofile>'
CMake Error at build/test/conan.cmake:402 (message):
  Conan install failed='1'
Call Stack (most recent call first):
  build/test/conan.cmake:497 (conan_cmake_install)
  test/CMakeLists.txt:21 (conan_cmake_run)


-- Configuring incomplete, errors occurred!
See also "/home/chogg/github/SI/build/CMakeFiles/CMakeOutput.log".

Subset of error message from step 6:

======== Computing dependency graph ========
catch2/2.13.6: Not found in local cache, looking in remotes...
catch2/2.13.6: Checking remote: conancenter
catch2/2.13.6: Downloaded recipe revision 83b861708ded6e779474712fec3c9382
Graph root
    conanfile.txt: /home/chogg/github/SI/test/conanfile.txt
*********************************************************
Recipe 'catch2/2.13.6' seems broken.
It is possible that this recipe is not Conan 2.0 ready
If the recipe comes from ConanCenter check: https://conan.io/cci-v2.html
If it is your recipe, check if it is updated to 2.0
*********************************************************

ERROR: Package 'catch2/2.13.6' not resolved: catch2/2.13.6: Cannot load recipe.
Error loading conanfile at '/home/chogg/.conan2/p/catchc541e95bb045a/e/conanfile.py': Unable to load conanfile in /home/chogg/.conan2/p/catchc541e95bb045a/e/conanfile.py
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/chogg/.conan2/p/catchc541e95bb045a/e/conanfile.py", line 3, in <module>
    from conans import ConanFile, CMake, tools
ImportError: cannot import name 'ConanFile' from 'conans' (/home/chogg/.local/lib/python3.10/site-packages/conans/__init__.py)
.
CMake Error at build/test/conan.cmake:402 (message):
  Conan install failed='1'
Call Stack (most recent call first):
  build/test/conan.cmake:497 (conan_cmake_install)
  test/CMakeLists.txt:21 (conan_cmake_run)


-- Configuring incomplete, errors occurred!
See also "/home/chogg/github/SI/build/CMakeFiles/CMakeOutput.log".

Expected behavior
I expected the step to succeed, so I could run the following command and run the tests.

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Ubuntu 22.04
  • Browser chrome

Smartphone (please complete the following information):
N/A

Additional context
I am not well versed in conan and cmake; I'm rather spoiled by bazel. It's possible that I'm making some basic mistake. However, it looks like this could be consistent with the upgrade to conan 2, which I know has broken a bunch of other packages, including mp-units.

Some remarks and issues

Hi ! Nice API that seems more user-friendly than boost. I'm testing it.

1/ Could be nice to add in your documentation ::value() how to cast a SI type to a type such a float. This is somewhat needed. I had to find it back from the code source.

auto a = 1.5_km;
std::cout << a.value() << std::endl;

Why not to add something like this ::to<T>() { return T(value()); } ? for example, a.to<int>() will return 1.

2/ Why degree_t is missing and how to write code such as 1.0_rad + 1.0_deg or degree_t d = 1.0_rad ?
I tried this but does not compile:

using degree_t = SI::radian_t<double, std::ratio<10000, 572958>>;
degree_t a = 1.0_rad;
std::cout << a.value() << std::endl;

But only this odd code works:

using degree_t = SI::velocity_t<double, std::ratio<10000, 572958>>;
degree_t a = 1.0_m_p_s;
std::cout << a.value() << std::endl;

3/ You have types such as velocity and acceleration, we have to include the specific header files, but you have not jerk, jounce, crackle, pop (https://en.wikipedia.org/wiki/Fourth,_fifth,_and_sixth_derivatives_of_position), maybe is there a more generic way to generate them?

4/ Why I cannot display velocities ? The follow code

#include <SI/length.h>
#include <SI/time.h>
#include <SI/velocity.h>
#include <SI/stream.h>

auto a = 1.0_km / 1.0_s;
std::cout << a << std::endl;

will produce this error:

/usr/local/include/SI/stream.h: In instantiation of ‘std::ostream& operator<<(std::ostream&, const SI::detail::unit_t<_symbol, _exponent, _type, _ratio>&) [with char _symbol = 'v'; _exponent = std::ratio<1>; _type = long double; _ratio = std::ratio<1000, 1>; std::ostream = std::basic_ostream<char>]’:
main.cpp:17:17:   required from here
/usr/local/include/SI/stream.h:23:26: error: ‘str’ is not a member of ‘SI::unit_symbol<'v', std::ratio<1000, 1>, std::ratio<1> >’
   stream << unit.value() << SI::unit_symbol<_symbol, _ratio, _exponent>::str;

Have I missed an include (same for acceleration) ?

5/ This code works:

SI::metre_t<float> a = 1.5_km;
SI::seconds_t<float> s = 1.0_s;
SI::metre_per_second_t<float> c = a / s;

But this one fails to compile (because of the double to float conversion):

SI::metre_t<float> a = 1.5_km;
SI::metre_per_second_t<float> c = a / 1.0_s;

6/ I'm on the HEAD and not have conan but compilation will fail

 cmake ..
-- The CXX compiler identification is GNU 8.3.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Warning at test/CMakeLists.txt:24 (message):
  Conan not found.  Trying to find Catch2 without it.


-- Found Doxygen: /usr/local/bin/doxygen (found version "1.8.17 (d4a0825b1d00ead2ce441c3407d1983f80401353*)") found components: doxygen dot 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/qq/SI/build

Then:

/home/qq/SI/test/src/benchmarks/unit_assignment_benchmarks.cc: In lambda function:
/home/qq/SI/test/src/benchmarks/unit_assignment_benchmarks.cc:18:37: error: ‘storage_for’ is not a member of ‘Catch::Benchmark’
       std::vector<Catch::Benchmark::storage_for<ratio_one_unit>> storage(

Default compile should work without conan

It would be nice to be able to compile and run the tests without conan if catch2 is already 'find' able, thru cmake find package.

Also default make,build, install cycle should work, without conan which is only used for test

mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=~/somewhere
make -j
make install

testing out of the box

Is your feature request related to a problem? Please describe.

Dear

I would like test your library, however I have problem with run unit tests "out of the box".
I think the instructions:
mkdir build cd build cmake .. cmake --build . --config Debug -- -j $(nproc)

does not cover unit tests because unit test are not build.

  1. Did I missed understand something? (I use cmake 3.17 VS2017, gcc 9.2, windows host)
  2. I also do not understand installing instruction since it is header library.

/Greg

Unitless types

centi_metre_t a = 15;
square_metre_t c = a / a; // This is not square meters!!!
CHECK_ALMOST_EQUAL(c.value(), 1.0F, 1E-6);

The units of 'c' are not square metres! In fact 'c' does not have units. So why does this compile?

Angular velocity

Would it be a good idea to implement angular velocity? That is, rad/s, deg/s etc?

I/O functions implementation from/to console and file

Obviously, the users of SI library, needs to input values at runtime and view outputs from applications

In my opinion, if I use a certain physical unit in a determinate scale, I want to see (for default) the variable's value in the scale I chose, with the related symbol

I am a C ++ amateur and certainly I cannot afford to offer you solutions, especially about generic programming, with extensive use of templates

Add support for "no unit" type

Altough we could use standard C++ variable types such as double or int, a "no unit" type could be useful:

  • To show the user we are using SI for a given class/calculation
  • For "unitless" constants, often seen in physics formulas
  • Literals for % or ‰ with <ratio>

documentation

Dear Dominik

I am evaluating your great work.
Before it may be used, it is always good idea to understand how it works. I wonder if you may add to documentation some details how the architecture works, how dimensions analyse works in your implementation, some very basic, may be few words.
I suppose detail::unit_t is a most important class.

So far from documentation I know that it is: "type safety at compile time".

Return value with known magnitude

If you have an Length object and you call obj.value() it may not be clear what unit it returns eg.
// somewhere in the code
SI::milli_metre_t<long double> x{100};
//somewhere else in the code
x.value(); // is this in millimeter or meter?

Provide a way to clearly describe what magnitude the raw value should represent
eg.
constexpr long double value_as(const Length u) {
return (*this/u).value()}
//usage
long double m = x.value_as(meter); // m=0.1
long double mm = x.value_as(millimeter); // mm=100

Describe alternatives you've considered
Use value() and track base unit in comments or notes

Integer reps perform truncating conversions without warning

Describe the bug
Unit conversions which divide the underlying value by some integer are accepted without complaint for integer reps.

To Reproduce
Steps to reproduce the behavior:

SI::length_t<int, std::ratio<1>> x{3};
SI::length_t<int, std::ratio<12>> y = x;
std::cout << "x = " << x << "; y = " << y << "!\n";

For me, this prints:

x = 3 m; y = 0 m!

Expected behavior
This should be a compiler error. If the rep is integral, we should only permit conversions which multiply by an integer, since these will stay in the domain of the integers.

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Linux
  • Browser: chrome
  • Version: 22.04

Smartphone (please complete the following information):
N/A

Additional context
N/A

a=F/m compile error

Trying to calculate acceleration from force divided by mass (Newton's second law), but it gives me a compile error.

When I try to add:
BUILD_UNIT_FROM_DIVISON(acceleration_t, force_t, mass_t)
...in acceleration.h, I get even more compiler errors, looks like an issue where header include orders.

Reproduced in "SI" version 1.4.1, using clang 7.0.1-8, gcc 8.3.0 and VS2019 16.4.3

CMAKE option to prevent installing

When including SI with CMAKEs add_subdirectory() all SI files are installed on make install.

Sometimes this is not desired, especially when when add_subdirectory() is called from an application CMAKE project that is using the SI:SI alias. The SI library will directly be compiled into the application and there is no need to install the whole library into the destination directory.

A CMAKE option to prevent installing the SI files in such a case could be useful, such as:

set(SI_INSTALL_LIBRARY OFF)
add_subdirectory(extern/SI)

The workaround below shows possible modifications of the CMakeLists.txt when using commenting instead of the proposed CMAKE options:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6fe812c..c34fa4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,18 +46,18 @@ configure_package_config_file(
   "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION
   ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
 
-install(
-  EXPORT ${PROJECT_NAME}_Targets
-  FILE ${PROJECT_NAME}Targets.cmake
-  NAMESPACE ${PROJECT_NAME}::
-  DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
+#install(
+#  EXPORT ${PROJECT_NAME}_Targets
+#  FILE ${PROJECT_NAME}Targets.cmake
+#  NAMESPACE ${PROJECT_NAME}::
+#  DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
 
-install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
-              "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
-        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
+#install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+#              "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
+#        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
 
-install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/SI
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+#install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/SI
+#        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 
 set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
 

Documentation, overloaded operations, compilation issue

Is your feature request related to a problem? Please describe.

Hi sir ! Make a long time since #93 I still have not yet converted my float into SI in my personal project :( I'm currently testing your library back and at the same time testing this one https://github.com/nholthaus/units.

To help beginners starting with your lib, I think you could add some concrete some basic examples in your documentation. Here is an attempt of mine concerning tricycle kinematics. https://github.com/Lecrapouille/BacASable/tree/master/LawControl/SI

The code using your lib is here https://github.com/Lecrapouille/BacASable/blob/master/LawControl/SI/si.cpp and the code using units is here https://github.com/Lecrapouille/BacASable/blob/master/LawControl/SI/units.cpp (feel free to use this code).

I'm sorry, time is currently missing for me for writing this ticket (I do it anyway else I'll forget to write it), as well for making a C++ class of si.cpp like done in units.cpp, but currently si.cpp does note compile because (speed / wheelbase) fails compiling (I hope the issue does not come from me). In addition, I noticed some weak points compared to the other lib:

Operators that could be overloaded:

  • The x += dt * ... does not compile, we have to write x = x + dt * ... instead.
  • The << speed does not compile. We have to write << speed.value() instead (same for x, heading). In the other lib the unit is also displayed (like 2 mps).
  • Less important but si::cos(heading) does not exist, we have to write instead std::cos(heading.value()) this just make the code more compact but let possible mistake like std::cos(x.value()) with x typed of metre_t.

Describe the solution you'd like

  • Implement overloading operators such as +=, <<, cos() ...
  • Add some basic examples using your lib.
  • In your documentation, you are using auto but it is better to give the real type like SI::metre_t<double> because we have to find their type back when passing them as function arguments.

Describe alternatives you've considered
Implemented in https://github.com/nholthaus/units.

Additional context
n/a

Unable to define unit symbol for length_t in miles

Describe the bug
Terrific library, by the way. This could be user error, however I am unable to define a unit symbol for miles (mi), even though miles per hour (mph) works.

To Reproduce
Steps to reproduce the behavior:

With the following header file, I am unable to produce a SI::to_string() output that has mi units.

#pragma once

#include <SI/length.h>
#include <SI/velocity.h>

#include <ratio>

namespace SI
{

template <typename _type>
using miles_t = SI::length_t<_type, std::ratio<1609344l, 1000l>>;

template <>
struct unit_symbol<'L', std::ratio<1609344l, 1000l>::type>
    : SI::detail::unit_symbol_impl<'m', 'i'> {};

template <typename _type>
using miles_per_hour_t = SI::velocity_t<_type, std::ratio<1397l, 3125l>>;

template <>
struct unit_symbol<'v', std::ratio<1397l, 3125l>::type>
    : SI::detail::unit_symbol_impl<'m', 'p', 'h'> {};

}

Expected behavior

The follow should produce the str value "1.000000 mi". Instead, it produces "1.000000 \000m".

constexpr auto miles = SI::miles_t<double>(1);
auto str = SI::to_string(miles);

However, the following works fine and produces "1.000000 mph".

constexpr auto miles_per_hour = SI::miles_per_hour_t<double>(1);
auto str = SI::to_string(miles_per_hour);

Desktop:

  • Ubuntu 22.04
  • Clang 14

Handle implicit and intermediate dimensions

Hello,

First, thank you for this great library :)

Maybe I miss some point here but, is there an easy way to handle these two cases:

SI::metre_t<double> dx;
SI::metre_t<double> dy;
SI::seconds_t<double> dt;
SI::seconds_t<double> total_duration;
auto surface_flow = dx * dy / dt;  // compile error because there is no type for m^2/s
auto total_surface = dx * dy / dt * total_duration;  // compile error but there is a type for m^2

Regards and thank you.

Implicit type conversion

Would be happy to allow some of the most basic implicit type conversions, such as int -> double. Often, we go into a calculation with a integer constant but end of with a double.

// Example 1
auto massTest1 = 1_kg;
auto massTest2 = 1.0_kg;
auto massTest3 = massTest1 + massTest2;

// Example 2
SI::kilo_gram_t<long double> massTest4 = 1_kg;

Wrong implementation of comparison operators > and <

There seems to be an issue with comparison operators. Following code runs into else() clause.

    auto _SPEED_10_KM_H = 10.0_km / 1.0_h;
    auto _SPEED_80_KM_H = 80.0_km / 1.0_h;
    if (_SPEED_10_KM_H < _SPEED_80_KM_H)
    {
        std::cout << "10 km/h < 80 km/h";
    }
    else
    {
        std::cout << "10 km/h >= 80 km/h";
    }

Reproduced in "SI" version 1.4.1, using clang 7.0.1-8, gcc 8.3.0 and VS2019 16.4.3

Update README

  • Hello ! First line:
A header only c++ library that provides type safety

Could be nice to explicitly say it is C++17 directly on the 1st line (else said on section "building & compat" which is far away).

  • The illustrative example does not compile (g++ --std=c++17 foo.cpp). I git cloned the HEAD:
foo.cpp:9:46: error: ‘const struct SI::detail::unit_t<'M', std::ratio<1>, long double, std::ratio<1> >’ has no member named ‘as’
    9 | constexpr auto thousand_grams = one_kilogram.as<SI::gram_t>();
      |                                              ^~
foo.cpp:9:59: error: missing template arguments before ‘>’ token
    9 | constexpr auto thousand_grams = one_kilogram.as<SI::gram_t>();
      |                                                           ^
foo.cpp:9:61: error: expected primary-expression before ‘)’ token
    9 | constexpr auto thousand_grams = one_kilogram.as<SI::gram_t>();
      |  

Unit test typo

TEST_CASE("GIVEN a value WHEN constructed with literal _pm THEN result is a "

I assume the comment should say _fm checking for femtometers. Here the whole block as a reference:

TEST_CASE("GIVEN a value WHEN constructed with literal _pm THEN result is a "
"length type AND ratio 1 to 10^15") {
constexpr auto one = 1_fm;
STATIC_REQUIRE(std::is_same<decltype(one),
const SI::length_t<int64_t, std::femto>>::value);
constexpr auto one_f = 1.0_fm;
STATIC_REQUIRE(
std::is_same<decltype(one_f),
const SI::length_t<long double, std::femto>>::value);
}

I really like your use of compile-time unit testing!

Add .str() to avoid using <<

As we use a formatting libary with { }, we would like to avoid the SI stream operator <<. Adding a .str() function might be useful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.