155 Commits

Author SHA1 Message Date
0xf00ff00f
8ad15eb7d7 Typo: rename astronicalUnit to astronomical_unit
Other than fixing the typo, use camel case for consistency with other
unit names.
2025-12-22 10:32:39 -03:00
Thomas Bleher
fb2a7ac1bc Spelling fixes (#349)
Found by codespell
2025-12-15 12:31:47 -05:00
Lewis Arias
011d34bae2 fix: define mil as 1/1000 of an inch and not 1000 inches (#348)
Closes #346
2025-09-25 11:46:50 -04:00
Nic Holthaus
e27eed9da9 fix: better conversion for inHg 2024-12-17 10:01:13 -05:00
Nic Holthaus
be28038213 feat: add unit test for mils conversion 2024-12-09 16:34:25 -05:00
Csaba Sipos
17b32745f2 - added missing numeric limits constants and functions
- added test for limits
2024-12-09 15:23:48 -05:00
ts826848
1ec32bebf5 Fix incorrect math function output for scaled dimensionless types (#288)
* Fix incorrect transcedental function output for scaled dimensionless types

As reported in issue #284, some functions produce incorrect results when
passed certain dimensionless quantites. For example, this program from
the issue, slightly modified for brevity and to try to make a later
point clearer:

    #include "units.h"
    #include <iostream>
    #include <cmath>
    using namespace units::literals;
    int main()
    {
        const auto c = 1.0_um * (-1 / 1.0_m);
        std::cout << "c                   : " << c << std::endl ;
        std::cout << "units::math::exp(c) : " << units::math::exp(c) << std::endl ;
        std::cout << "std::exp(c.value()) : " << std::exp(c.value()) << std::endl ;
        return EXIT_SUCCESS ;
    }

Outputs:

    c                   : -1e-06
    units::math::exp(c) : 0.367879
    std::exp(c.value()) : 0.999999

value() is basically to<>(), but with the template parameter hard-coded
to underlying_type, and to<>() is one of the documented ways to pass
something to a non-unit-enabled API, so getting different results this
way is rather surprising.

The proximate cause of this difference is the use of operator()()
instead of value() or to<>() by (some?) functions in units::math. In the
case of the example above:

    template<class ScalarUnit>
    dimensionless::scalar_t exp(const ScalarUnit x) noexcept
    {
        static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
        return dimensionless::scalar_t(std::exp(x()));
        // operator()() instead of value()/to()  ^^
    }

The use of operator()() means that std::exp() is fed a different input
than when value() is used, as demonstrated by the output from an
appropriately modified version of the example program:

    c                   : -1e-06
    c()                 : -1
    c.value()           : -1e-06
    units::math::exp(c) : 0.367879
    std::exp(c.value()) : 0.999999

However, this problem does not for all possible inputs. If the
expression for c is changed as such:

    // const auto c = 1.0_um * (-1 / 1.0_m);
    const auto c = -1.0_um / 1.0_m;

The issue appears to vanish:

    c                   : -1e-06
    c()                 : -1e-06
    c.value()           : -1e-06
    units::math::exp(c) : 0.999999
    std::exp(c.value()) : 0.999999

I believe this is because the different calculations result in objects
with different types:

    # const auto c = 1.0_um * (-1 / 1.0_m);
    (lldb) p c
    (const units::unit_t<units::unit<std::ratio<1, 1000000>, units::base_unit<std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1> >, std::ratio<0, 1>, std::ratio<0, 1> >, double, units::linear_scale>) $0 = {
      units::linear_scale<double> = (m_value = -1)
    }

    # const auto c = 1.0_um / 1.0_m;
    (lldb) p c
    (const units::dimensionless::scalar_t) $0 = {
      units::linear_scale<double> = (m_value = 9.9999999999999995E-7)
    }

Where the latter is equivalent to:

    # const auto c = 1.0_um / 1.0_m;
    (lldb) p c
    (const units::unit_t<units::unit<std::ratio<1, 1>, units::base_unit<std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1>, std::ratio<0, 1> >, std::ratio<0, 1>, std::ratio<0, 1> >, double, units::linear_scale>) $0 = {
      units::linear_scale<double> = (m_value = 9.9999999999999995E-7)
    }

The difference in the results amounts to the "new" calculation having
the "correct" value directly in m_value, whereas the "old" calculation
has some information in the type, which could be described as the
exponent in the type and the mantissa in m_value. Floating-point errors
aside, they are equal.

This points to the ultimate cause of the issue: operator()() and
value()/to<>() appear to consider different information when producing
their results. operator()() fully discards information encoded in the
type, directly returning the "raw" underlying value (modified for the
decibel scale if needed), while for dimensionless types value() and
to<>() account for both information encoded in the type and the "raw"
underlying value in their return values. This is apparent in their
implementations, where operator()() has no awareness of the units::unit
tag, but value()/to<>() delegate to the conversion operator for
dimensionless quantities, which explicitly "normalizes" the underlying
value using units::convert<>() before returning it:

    template<class Units, typename T = UNIT_LIBDEFAULT_TYPE, template<typename> class NonLinearScale = linear_scale>
    class unit_t : public NonLinearScale<T>, units::detail::_unit_t
    {
    public:
        typedef T underlying_type;

        inline constexpr underlying_type value() const noexcept
        {
            return static_cast<underlying_type>(*this);
        }

        template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
        inline constexpr Ty to() const noexcept
        {
            return static_cast<Ty>(*this);
        }

        template<class Ty, std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
        inline constexpr operator Ty() const noexcept
        {
            // this conversion also resolves any PI exponents, by converting from a non-zero PI ratio to a zero-pi ratio.
            return static_cast<Ty>(units::convert<Units, unit<std::ratio<1>, units::category::scalar_unit>>((*this)()));
        }
    };

    template<typename T>
    struct linear_scale
    {
        inline constexpr T operator()() const noexcept { return m_value; }
        T m_value;
    };

    template<typename T>
    struct decibel_scale
    {
        inline constexpr T operator()() const noexcept { return 10 * std::log10(m_value); }
        T m_value;
    };

As a result, the problem is clear: the functions using operator()() to
obtain a value to pass to std::math functions are incorrect and should
be changed to use value() so relevant information is not thrown away.

The functions changed in this commit are the functions grouped under the
"TRANSCEDENTAL FUNCTIONS" header in the header file. This is why modf()
is changed here despite not being a transcedental function. Some other
functions suffer from a similar issue, but those will be addressed in
different commits.

* Fix incorrect trig function output for scaled dimensionless types

Similar to the previous commit, but for certain trigonometric functions.
I don't think that explicitly using value() is strictly necessary for
the other trig functions since they already use convert<>() to
normalize, so I don't think normalization through value() is necessary.
I have not tested it, though.

Not entirely sure the modifications to the test cases are the best way
to make the desired changes. The idea is to use the same inputs/outputs,
but to change the unit type to have a conversion factor not equal to 1.

Co-authored-by: Alex Wang <ts826848@gmail.com>
2022-09-26 09:53:29 -04:00
Opportunity
ea6d126942 Support negative exponent in power_of_unit (#227)
* Update units.h

* Update main.cpp

* fix typo

Co-authored-by: Nic Holthaus <nholthaus@gmail.com>
2020-10-10 18:46:02 -04:00
Benjamin Füldner
665f296c25 Operator constexpr (#239)
* Remove spaces from line endings...

* Add constexpr to return value of arithmetic operators.

* Drop support for gcc-4.x and Visual Studio 14 because they not fully support C++14 standard.

Co-authored-by: Nic Holthaus <nholthaus@gmail.com>
2020-10-07 19:09:50 -04:00
Nic Holthaus
3252189fbe V2.3.x (#107)
* added compound assignment operators: +=, -=, *=, /=. Closes #44.

* print undefined unit types in SI base units. Closes #38. Update constants to NIST 2014 CODATA recommendations.

* Reduce metaprogramming boilerplate

* workaround for vs2013 internal compiler error

* added data and data transfer units. Closes #46.

* update doxyfile.in to v2.2.0

* add constexpr std::array test

* add julian and gregorian year definitions. Closes #29.

* added `value()` and `value_type` trait. Closes #56.

* fixes constexpr relational operator bug. Closes #63.

* improve compile time.

* removed some debug code.

* measure compile time

* Friend the linear scale units. Reduces compile time.

* add inline to pow() and abs() for being able to use units.h in different compilation units

* Revert "Friend the linear scale units. Reduces compile time."

This reverts commit e26fcd7d9b.

* Revert "add inline to pow() and abs() for being able to use units.h in different compilation units"

This reverts commit d42020e1de.

* add inline to pow() and abs() for being able to use units.h in different compilation units

* Test with Visual Studio 2017

* Another attempt at using Visual Studio 2017 in appveyor

* Build with VS2017

* add MSVC2017 badge

* started min/max

* fixes #65, fixes #71, fixes #76, fixes #79, fixes #80.  Adds documentation.

* fix for vs2013, gcc

* updated docs

* fix for vs2013

* remove gcc warnings, add prefined unit defines

* min/max shouldn't be constexpr

* fix cmake

* more cmake fixes

* numeric_limits namespace

* fixes #77.

* fixes #75 & documentation

* fixed merge issues

* for Morwenn

* Make the project work with both ninja and msvc generators on windows

* Fixes #106. Locale aware `to_string` conversions.

* Fixes #105. Unary operators. Also removes VS 2013 testing (and support)

* Fixes #87. Don't include `to_string()` when iostream is disabled.

* fix a mistake in the unary +/-

* Add constexpr name/abbreviation member functions which don't require iostream.

* Fixes for linux build
2018-04-21 15:59:22 -04:00
Nic Holthaus
a7d600aacd v2.3.x development
* added compound assignment operators: +=, -=, *=, /=. Closes #44.

* print undefined unit types in SI base units. Closes #38. Update constants to NIST 2014 CODATA recommendations.

* Reduce metaprogramming boilerplate

* workaround for vs2013 internal compiler error

* added data and data transfer units. Closes #46.

* update doxyfile.in to v2.2.0

* add constexpr std::array test

* add julian and gregorian year definitions. Closes #29.

* added `value()` and `value_type` trait. Closes #56.

* fixes constexpr relational operator bug. Closes #63.

* improve compile time.

* removed some debug code.

* measure compile time

* Friend the linear scale units. Reduces compile time.

* add inline to pow() and abs() for being able to use units.h in different compilation units

* Revert "Friend the linear scale units. Reduces compile time."

This reverts commit e26fcd7d9b.

* Revert "add inline to pow() and abs() for being able to use units.h in different compilation units"

This reverts commit d42020e1de.

* add inline to pow() and abs() for being able to use units.h in different compilation units

* Test with Visual Studio 2017

* Another attempt at using Visual Studio 2017 in appveyor

* Build with VS2017

* add MSVC2017 badge

* started min/max

* fixes #65, fixes #71, fixes #76, fixes #79, fixes #80.  Adds documentation.

* fix for vs2013, gcc

* updated docs

* fix for vs2013

* remove gcc warnings, add prefined unit defines

* min/max shouldn't be constexpr

* fix cmake

* more cmake fixes

* numeric_limits namespace

* fixes #77.

* fixes #75 & documentation

* fixed merge issues

* for Morwenn
2017-09-16 14:19:16 -05:00
Nic Holthaus
8ca281a03a another attempt at a coveralls fix. 2017-02-09 22:02:55 -05:00
Nic Holthaus
62e8a8e945 fix coveralls reporting of units.h 2017-02-09 21:53:05 -05:00
Nic Holthaus
fb44b11382 documentation/test updates. Closes #31. 2017-02-09 20:39:26 -05:00
Nic Holthaus
b4403dbe27 Add unit test to cover #41 2017-02-09 19:27:55 -05:00
Nic Holthaus
a8c0ee0da3 fix cmake options and add make_unit test. Closes #52. 2017-02-09 18:49:09 -05:00
Nic Holthaus
3c27bb1154 merge in pedantic fixes 2017-02-09 18:15:21 -05:00
Nic Holthaus
89a8ed1e5e merged PR #42 and made review changes. 2017-02-09 18:10:51 -05:00
Nic Holthaus
6be384c0de merged 2017-02-09 17:52:05 -05:00
Nic Holthaus
b5ade69ffd fixed remaining pedantic warnings. 2017-02-09 11:44:56 -05:00
Nic Holthaus
3ffcd48c4a add compile option to disable IOStream. This will start working when #42 is pulled. 2017-02-09 10:41:47 -05:00
Bastiaan Ober
3136398a4f Added comments to the MACROs and fixed a few minor glitches (restores constexpr of literals, fixed some comments) 2017-02-09 09:36:34 +01:00
Nic Holthaus
2c4790ce28 Added std::hypot wrapper. Closes #47. 2017-02-08 11:12:50 -05:00
Bastiaan Ober
0a7d4d4453 Change MACRO definitions to support adding units with/without IO/literals and unify VS versions 2017-02-06 17:06:09 +01:00
Nic Holthaus
520b3e9455 fixed scalar unit conversions 2016-10-15 10:24:14 -04:00
Nic Holthaus
3dd6ee3bca added some unit tests for concentration conversions 2016-10-14 17:32:50 -04:00
Nic Holthaus
37a28ee2ce Merge branch 'v2.2.x' of https://github.com/nholthaus/units.git 2016-10-11 12:48:18 -04:00
Nic Holthaus
527903d406 added constexpr test for cpow 2016-10-11 12:47:37 -04:00
Nic Holthaus
5cd7e8dfc7 chrono conversion. Replace alias templates w/ typedef for better error messages. 2016-10-10 20:16:53 -04:00
Nic Holthaus
45eefd0415 fixed on clang 2016-10-10 14:21:58 -04:00
Nic Holthaus
7666caec6f pi is working for linear scales 2016-10-10 12:32:15 -04:00
Nic Holthaus
b42ff5755d fixed pi to conversions 2016-10-10 12:19:19 -04:00
Nic Holthaus
d2c6a19a5a pi multiplication works 2016-10-10 11:54:56 -04:00
Nic Holthaus
6c75d68988 made unit arithmetic more readable 2016-10-10 09:41:35 -04:00
Nic Holthaus
f0c4eaf550 comment cleanup 2016-10-10 09:04:31 -04:00
Nic Holthaus
7b242f3df4 cmath doesn't support constexpr. 2016-10-09 15:43:59 -04:00
Nic Holthaus
5c6a8278e0 added some constexpr unit tests 2016-10-09 16:36:29 -04:00
Nic Holthaus
e18ae20d6c constexpr/constants mostly working. Need to fix pi. 2016-10-09 11:29:11 -04:00
Nic Holthaus
2920c32b45 added constexpr, need to fix pi/constants. 2016-10-08 12:35:23 -04:00
Nic Holthaus
f20b07e4a5 cmake improvements (#24)
- adds an `INTERFACE` cmake library for easier consumption as a subproject
- Removes GNU dependencies
- Updates google test to 1.8.0 and substantially simplifies the google test build
- adds caching to our CI system to improve build speed
- Add options to avoid building the unit tests/documentation (this will be helpful for subdirectories)
2016-10-07 09:27:45 -04:00
Nic Holthaus
d5df46732a removed unnecessary cmake code 2016-09-27 22:02:46 -04:00
Nic Holthaus
15058c7009 builds with clang++-3.8 2016-09-27 21:59:45 -04:00
Nic Holthaus
f4e977590b readme updates, added some literal testing 2016-09-25 08:51:37 -04:00
Nic Holthaus
51b5d2075f added unit_cast function. Closes #14. 2016-08-21 12:21:16 -04:00
Nic Holthaus
873c300bb3 all units converted to macro definitions. 2016-08-20 17:58:29 -04:00
Nic Holthaus
4ce0234ed4 units through inductance have been converted to macro definitions. 2016-08-20 16:45:41 -04:00
Nic Holthaus
d432559d43 units up to charge have been converted to macro definitions. 2016-08-20 15:13:36 -04:00
Nic Holthaus
e14c9460ee moved all unit literals to the units::literals namespace. Refactored the macros. 2016-08-20 12:05:54 -04:00
Nic Holthaus
f0799c9806 fix millisecond typo. Added some additional checks for unit_t that help with some esoteric build errors. 2016-08-12 15:06:44 -04:00
Nic Holthaus
b72cbbf007 macro-ify mass/time/angle units 2016-07-17 10:08:17 -04:00