nholthaus / units

a compile-time, header-only, dimensional analysis and unit conversion library built on c++14 with no dependencies.
http://nholthaus.github.io/units/
MIT License
965 stars 137 forks source link

Support of data types other than double #175

Open mmoelle1 opened 6 years ago

mmoelle1 commented 6 years ago

I very much like the underlying concepts of units and investigate the possibilities to integrate it into our simulation codes, which make heavy use of expression template libraries like Eigen, blaze, vexcl etcetera. That said, I made a first start and changed UNIT_LIB_DEFAULT_TYPE from double to float. The following demo code:

#define UNIT_LIB_DEFAULT_TYPE float
#include <units.h>

using namespace units::literals;
using namespace units;
using namespace units::length;
using namespace units::time;
using namespace units::area;
using namespace units::velocity;

int main()
{
    square_meter_t  area = 15_m * 5_m + 10_m * 10_m;        // 175 m^2

    std::cout << area << std::endl;

    return 0;
}

yields the following compiler error (g++ 8.2):

include/units.h:4147:252:   in 'constexpr' expansion of 'units::math::cpow<4, units::unit_t<units::unit<std::ratio<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<-1>, std::ratio<0, 1>, std::ratio<0, 1> >, std::ratio<0, 1>, std::ratio<0, 1> > > >(units::constants::N_A)'
include/units.h:2779:17:   in 'constexpr' expansion of 'units::detail::pow((& value)->units::unit_t<units::unit<std::ratio<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<-1>, std::ratio<0, 1>, std::ratio<0, 1> >, std::ratio<0, 1>, std::ratio<0, 1> > >::<anonymous>.units::linear_scale<float>::operator()(), 4'
include/units.h:1511:33:   in 'constexpr' expansion of 'units::detail::pow(x, (y + 18446744073709551615))'
include/units.h:1511:33:   in 'constexpr' expansion of 'units::detail::pow(x, (y + 18446744073709551615))'
include/units.h:1511:28: error: '(6.022141e+23f * 6.022141e+23f)' is not a constant expression
    return y == 0 ? 1.0 : x * pow(x, y - 1);
                          ~~^~~~~~~~~~~~~~~

The same code compiled by Apple's clang++ yields

include/units.h:4147:140: error: constexpr variable 'sigma' must be initialized by a constant expression
  ...inverse<squared<squared<temperature::kelvin>>>>>   sigma((2 * math::cpow<5>(pi) * math::cpow<4>(R)) / (15 * math::cpow<3>(h) * math::cpow<2>(c) * math::cpow<4>(N_A)));    ///< Stefan-Boltz...
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/units.h:1511:28: note: floating point arithmetic produces an infinity
                        return y == 0 ? 1.0 : x * pow(x, y - 1);
                                                ^
include/units.h:1511:30: note: in call to 'pow(6.022141e+23, 2)'
                        return y == 0 ? 1.0 : x * pow(x, y - 1);
                                                  ^
include/units.h:1511:30: note: in call to 'pow(6.022141e+23, 3)'
include/units.h:2779:6: note: in call to 'pow(6.022141e+23, 4)'
                                (detail::pow(value(), power));
                                 ^
include/units.h:4147:235: note: in call to 'cpow(N_A)'
  ...inverse<squared<squared<temperature::kelvin>>>>>   sigma((2 * math::cpow<5>(pi) * math::cpow<4>(R)) / (15 * math::cpow<3>(h) * math::cpow<2>(c) * math::cpow<4>(N_A)));    ///< Stefan-Boltz...
                                                                                                                                                            ^
1 error generated.
nholthaus commented 6 years ago

So this is something that's been heavily worked in our soon-to-come version 3.0. In that version, units will natively support any arithmetic underlying type (including integral types) via normal template syntax, as well as mixing and matching underlying types in a non-lossy manner. You may be interested in trying out the v3.0-alpha2 build which contains that functionality.

This specific error looks like an ADL issue with pow (inside the library), probably fixed by namespacing it correctly.

mmoelle1 commented 6 years ago

Sounds very interesting. I’ll give it a try.

On 6 Sep 2018, at 16:12, Nic Holthaus notifications@github.com wrote:

So this is something that's been heavily worked in our soon-to-come version 3.0. In that version, units will natively support any arithmetic underlying type (including integral types) via normal template syntax, as well as mixing and matching underlying types in a non-lossy manner. You may be interested in trying out the v3.0-alpha2 build which contains that functionality.

This specific error looks like an ADL issue with pow (inside the library), probably fixed by namespacing it correctly.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nholthaus/units/issues/175#issuecomment-419108238, or mute the thread https://github.com/notifications/unsubscribe-auth/AB5no9Yrdq0kfXgOqYbhARqxfZaWqpYiks5uYS1NgaJpZM4Wc2eG.

mmoelle1 commented 6 years ago

Can you recommend me an example that illustrated the new functionality?

Am 07.09.2018 um 08:36 schrieb Matthias Möller mmoelle1@gmail.com:

Sounds very interesting. I’ll give it a try.

On 6 Sep 2018, at 16:12, Nic Holthaus notifications@github.com wrote:

So this is something that's been heavily worked in our soon-to-come version 3.0. In that version, units will natively support any arithmetic underlying type (including integral types) via normal template syntax, as well as mixing and matching underlying types in a non-lossy manner. You may be interested in trying out the v3.0-alpha2 build which contains that functionality.

This specific error looks like an ADL issue with pow (inside the library), probably fixed by namespacing it correctly.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

nholthaus commented 6 years ago

will do. I realized I need to release an alpha-3 with this functionality, probably this weekend sometime.

JohelEGP commented 6 years ago

Isn't the milestone for this issue wrong?

nholthaus commented 6 years ago

@johelegp indeed. Fixed.

mmoelle1 commented 6 years ago

Is there any example yet available that demonstrates the use of user-defined types, e.g. a vector from the Eigen library or an std::vector with overloaded +operator?

a-jp commented 5 years ago

I would be very keen to do dimensional analysis using this library with Eigen types: is there a working example that shows how to do this?

andipeer commented 1 year ago

@a-jp I think this is not possible with the current implementation. Problem is that it relies on std::is_arithmetic and std::is_floating_point traits to verify that the provided type is supported. One could be tempted to just add specializations to those traits for the custom types, but this would be undefined behavior. There has been some discussion in #138 (see this comment) about waiting for the standard committee to add more customization options for such traits, but unfortunately it seems that there hasn't been made any progress on this yet (there is a successor proposal P1841 for inclusion into C++23, but I'm not sure about the status of it).

For the time being, for our project we did the following to allow for user-defined types:

  1. Introduce a custom trait units::traits::is_arithmetic that defaults to std::is_arithmetic, and replace in units/core.h all occurrences of std::is_arithmetic by it (note that you also need to add/replace the is_arithmetic_v traits). Than, add specializations for units::traits::is_arithmetic for your custom data types.
  2. Do the same for std::is_floating_point.
  3. Add the required specializations of std::common_type (the compiler will tell which ones are missing). Adding specializations to this trait is valid according to the standard.

I'm not fully sure what unexpected consequences this may have, but it is working for our use case. @nholthaus what is your opinion on this? Would you accept a pull request with such (or similar) changes?

Just wanted to thank @nholthaus and all others for the great effort you put into v3. It is a real joy to work with this library!