14

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);
}
schoetbi
  • 12,009
  • 10
  • 54
  • 72
chew socks
  • 1,406
  • 2
  • 17
  • 37
  • `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. – Ben Voigt Sep 24 '15 at 18:55
  • 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`. – chew socks Sep 24 '15 at 20:34
  • Did your attempt to define `is_true` account for the namespace? – Ben Voigt Sep 24 '15 at 20:35
  • Yes, it was directly above their implementation inside the `detail` namespace. – chew socks Sep 24 '15 at 20:39
  • It looks like this effort is likely worthless because all math is done by casting to `double`. – chew socks Sep 24 '15 at 20:40
  • 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. – Ben Voigt Sep 24 '15 at 20:44
  • @BenVoigt What I saw that made me think it was the `exp` routine calls `std::exp` – chew socks Sep 24 '15 at 21:15
  • Note that adding a template definition make ambiguity worse. Add a special overload for exactly `__float128` – Ben Voigt Sep 24 '15 at 21:17

2 Answers2

16

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.

  • My jar literally dropped. I promised I looked there before asking here. – chew socks Sep 25 '15 at 07:25
  • The provided adapter example doesn't actually compile for me. I haven't tried the MPFR one yet. – chew socks Sep 25 '15 at 07:49
  • 3
    @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. –  Sep 25 '15 at 09:01
  • Thanks for the update! It compiles and runs now. I would never have guessed printf was the cause of the errors I saw. – chew socks Sep 28 '15 at 21:43
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.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • 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 :) – Blindy Sep 24 '15 at 16:52
  • 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. – chew socks Sep 24 '15 at 18:30
  • 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. – chew socks Sep 24 '15 at 18:31
  • I tried adding my own `is_true` and still no go. (see edit) – chew socks Sep 24 '15 at 18:41
  • I copied the existing implementation and pasted above it. – chew socks Sep 24 '15 at 21:16