Boost logo

Boost :

Subject: Re: [boost] [Math.Constants] Help needed with the preprocessor
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-12-16 18:33:18


On Fri, Dec 16, 2011 at 3:26 PM, Jeffrey Lee Hellrung, Jr.
<jeffrey.hellrung_at_[hidden]> wrote:
> On Fri, Dec 16, 2011 at 10:23 AM, John Maddock <boost.regex_at_[hidden]>wrote:
>
>> Folks we have a problem: rather late in the day I've discovered that our
>> Math.Constants code doesn't compile on anything except VC++, and the
>> problem is preprocessor token pasting.  So I'm hoping we have some experts
>> around here that can help!
>>
>> The issue is we currently construct the constants from a macro invocation
>> such as:
>>
>>  BOOST_DEFINE_MATH_CONSTANT(**half, 5.**000000000000000000000000000000**000000,
>> 000000000000000000000000000000**000000000000000000000000000000**00000000000000,
>>  -01);
>>
>> But the "-01" part (the exponent) isn't a valid pp-token, so trying to
>> token-paste it fails on GCC (compiler error).
>>
>> Does anyone know if there's a way to overcome this?
>>
>
> Maybe include the "e" in that 4th argument?  E.g., "e-01". If you actually
> need to recover the "-01" without the e, I'm pretty sure you can do
> something like

  #define BOOST_DEFINE_MATH_CONSTANT(name, x, y, exp)

Yes, as indicated by Jeff, you can have your users to always prefix
exp with e (I looked at your macro and you always CAT(e, exp)). BTW,
can x ever start with a symbol (-)?

BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000,
00000000000000000000000000000000000000000000000000000000000000000000000000,
e-01); // OK

Otherwise it seems you can use PP_SEQ_CAT:

#include <boost/preprocessor/seq/cat.hpp>
#include <boost/preprocessor/stringize.hpp>

  #define BOOST_DEFINE_MATH_CONSTANT(name, x, y, exp)\
   template <class T> inline T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))\
   {\
      static const T result = ::boost::lexical_cast<T>(BOOST_PP_STRINGIZE( \
            BOOST_PP_SEQ_CAT( (x) (y) (e) (exp) )));\
      return result;\
   }\
   template <> inline float
name<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))\
   { return BOOST_PP_SEQ_CAT( (x) (e) (exp) (F)); }\
   template <> inline double
name<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))\
   { return BOOST_PP_SEQ_CAT( (x) (e) (exp) ); }\
   template <> inline long double name<long
double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))\
   { return BOOST_PP_SEQ_CAT( (x) (e) (exp) (L) ); }

BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000,
00000000000000000000000000000000000000000000000000000000000000000000000000,
-01); // ok but no e

This seems to work even with x = -1.0:

BOOST_PP_SEQ_CAT( (-1.0) (123) (e) (-10) ) // -1.0123e- 10

But I'm not sure how this actually works inside Boost.Preprocessor...

HTH,
--Lorenzo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk