ExprTk with increased precision
Asked Answered
N

2

15

I am trying to compile the ExprTk library with more precision than long double. I thought the simplist would be to try GCC's __float128 but I am getting the following compilation error and am not sure how to correct it.

exprtk.hpp: In instantiation of ‘static T exprtk::details::and_op<T>::process(exprtk::details::and_op<T>::Type, exprtk::details::and_op<T>::Type) [with T = __float128; exprtk::details::and_op<T>::Type = const __float128&]’:
exprtk.hpp:28439:10:   required from ‘void exprtk::parser<T>::load_binary_operations_map(exprtk::parser<T>::binary_op_map_t&) [with T = __float128; exprtk::parser<T>::binary_op_map_t = std::map<exprtk::details::operator_type, __float128 (*)(const __float128&, const __float128&), std::less<exprtk::details::operator_type>, std::allocator<std::pair<const exprtk::details::operator_type, __float128 (*)(const __float128&, const __float128&)> > >; typename exprtk::details::functor_t<T>::bfunc_t = __float128 (*)(const __float128&, const __float128&)]’
exprtk.hpp:15660:51:   required from ‘exprtk::parser<T>::parser(std::size_t) [with T = __float128; std::size_t = long unsigned int]’
mathtof.cpp:18:33:   required from here
exprtk.hpp:9923:105: error: call of overloaded ‘is_true(const __float128&)’ is ambiguous
          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
                                                                                                         ^
compilation terminated due to -Wfatal-errors.

EDIT:

I've tried implementing my own is_true

<typename T>
inline bool is_true(const T v)
{
    return std::not_equal_to<T>()(T(0),v);
}
Neoarsphenamine answered 24/9, 2015 at 16:23 Comment(8)
is_true vs is_true_impl? Also, based on the error, you need to put it inside the details namespace. is_true is called using a qualified name, so ADL won't trigger.Astylar
My mistake, it was is_true. I made it by copying that is_true_impl directly inline with the other definitions of is_true and is_ture_impl.Neoarsphenamine
Did your attempt to define is_true account for the namespace?Astylar
Yes, it was directly above their implementation inside the detail namespace.Neoarsphenamine
It looks like this effort is likely worthless because all math is done by casting to double.Neoarsphenamine
I see a lot of casts to double associate with int_type_tag, none for real_type_tag. But then, I only took a quick look.Astylar
@BenVoigt What I saw that made me think it was the exp routine calls std::expNeoarsphenamine
Note that adding a template definition make ambiguity worse. Add a special overload for exactly __float128Astylar
P
17

It is rather trivial to specialize ExprTk upon a custom numeric type. There are TWO examples found on the project's page that give a clear and concise means to introduce new numeric types within ExprTk.

The examples are:

  1. Custom Real Type Adaptor [link]
  2. MPFR Adaptor [link]

The real type example implements a simple real type using the double type. Furthermore it provides the necessary additions into the ExprTk namespace that needs to be included prior to including the actual ExprTk header.

The MPFR adaptor builds upon the previous example and shows how one can easily adapt the MPFR/GMP type for use in ExprTk.

Both examples come packaged with the full test suite and benchmark using the newly introduced types.


Here is an example where someone has adapted their own type called DScalar to ExprTk:

https://github.com/filiatra/gismo/blob/stable/external/exprtk_ad_adaptor.hpp

and here it is being used:

https://github.com/filiatra/gismo/blob/stable/src/gsCore/gsFunctionExpr.hpp#L146


It should be noted that one can simply take the "Custom Real Type Adaptor" and search-n-replace the string "real::type" with __float128 and some other minor replace changes and should be all good to go.

Peon answered 25/9, 2015 at 3:38 Comment(4)
My jar literally dropped. I promised I looked there before asking here.Neoarsphenamine
The provided adapter example doesn't actually compile for me. I haven't tried the MPFR one yet.Neoarsphenamine
@chewsocks redownload both again, there may have been an issue with printf - also make sure you copy exprtk.hpp to where its needed as both packages don't include the header as part of the download.Peon
Thanks for the update! It compiles and runs now. I would never have guessed printf was the cause of the errors I saw.Neoarsphenamine
T
1

It obviously doesn't support __float128 (gcc itself barely supports it, you need the Boost float128.h library to do anything remotely useful with it).

You can try to provide the missing is_true(__float128&) overload, it should be relatively trivial, but I'm willing to bet money that won't be the end of it.

Tiffin answered 24/9, 2015 at 16:50 Comment(5)
Note that my knowledge of gcc's support for __float128 is a few years old, maybe more recent versions got better -- though I doubt it. There isn't much of a market for software emulated floating point operations when you can do billions at once on your garden variety GPU :)Tiffin
Okay, so I changed it to using boost::multiprecision::cpp_dec_float_100 because I figured it would have a more complete set of overloads. Nope, same problem.Neoarsphenamine
I'm not sure what you mean about doing floating point calcs on a GPU. The benefit of a software implementation is high precision. Up until recently a GPU could only do 32-bit floats.Neoarsphenamine
I tried adding my own is_true and still no go. (see edit)Neoarsphenamine
I copied the existing implementation and pasted above it.Neoarsphenamine

© 2022 - 2024 — McMap. All rights reserved.