[Boost] Compile-time power of a run-time base

Hello, I have written for the need of a coworker a function template that computes the compile-time power of a base that is known only at runtime. The original need was just to avoid having to write things like "value*value*value*value*value". Before doing this, I've been searching for such a thing in the Boost documentation and mailing lists, but could only find discussions about an entierely compile-time version (compile-time exponent of compile-time base) intended for use in metaprograms. Is there any reason why the "semi-compile-time" version I describe here hasn't been discussed? Even though it can be viewed as a mere syntactic sugar, it can be very practical when it comes to write by hand a power with a big exponent. In case of interest, here is my code : template <int N> struct positive_power { template <typename T> static float result(T base) { return base*positive_power<N-1>::result(base); } }; template <> struct positive_power<0> { template <typename T> static float result(T) { return 1; } }; template <int N, bool> struct power_if_positive { template <typename T> static float result(T base) { return positive_power<N>::result(base); } }; template <int N> struct power_if_positive<N, false> { template <typename T> static float result(T base) { return 1/positive_power<-N>::result(base); } }; template <int N, typename T> float power(T base) { return power_if_positive < N, boost::mpl::greater_equal < boost::mpl::int_<N>, boost::mpl::int_<0> >::type::value >::result(base); } It supports positive, null and negative integer exponents. Some improvements can surely be done, like allowing to specify the desired return type. Examples of use : power<3>(myValue); power<0>(myValue); power<-5>(myValue); Thanks Bruno

----- Mensaje original ----- De: Bruno Lalande <bruno.lalande@gmail.com> Fecha: Sábado, Febrero 2, 2008 12:18 pm Asunto: [boost] [Boost] Compile-time power of a run-time base Para: boost@lists.boost.org
Hello,
I have written for the need of a coworker a function template that computesthe compile-time power of a base that is known only at runtime. The original need was just to avoid having to write things like "value*value*value*value*value".
Before doing this, I've been searching for such a thing in the Boost documentation and mailing lists, but could only find discussions about an entierely compile-time version (compile-time exponent of compile- time base) intended for use in metaprograms. Is there any reason why the "semi-compile-time" version I describe here hasn't been discussed? Eventhough it can be viewed as a mere syntactic sugar, it can be very practical when it comes to write by hand a power with a big exponent.
In case of interest, here is my code :
template <int N> struct positive_power { template <typename T> static float result(T base) { return base*positive_power<N-1>::result(base); } };
I think this is suboptimal: you need only log(N) multiplications to get positive_power<N>::result(base): template <int N> struct positive_power { template <typename T> static float result(T base) { float aux=positive_power<N/2>::result(base); return (N%2)?base*aux*aux:aux*aux; } }; HTH, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Hi Joaquin, Yes you're right, thanks for the advice. I really thought that an optimizing compiler was able to figure out this by itself, that is, transform things like n*n*n*n into (n*n)*(n*n). But a few tests shew me I was wrong. I have tested your version and indeed, it's much faster in most cases. However, the gain of performance was not present in all cases until I add a specialization for the exponent 3: template <> struct positive_power<3> { template <typename T> static float result(T base) { return base*base*base; } }; An example of problematic case is power<12>(anyvalue). Good performances are only achieved with this specialization. I think this is due to useless temporaries that the optimizer can't get to remove (I tested with GCC 4.1.3, with -O3 optimization). With your modification the function is finally much more than a syntactic helper since it runs faster than what an average programmer would type by hand. Shouldn't it be integrated somewhere into Boost ? Thanks Bruno On Feb 2, 2008 1:57 PM, "JOAQUIN LOPEZ MU?Z" <joaquin@tid.es> wrote:
----- Mensaje original ----- De: Bruno Lalande <bruno.lalande@gmail.com> Fecha: Sábado, Febrero 2, 2008 12:18 pm Asunto: [boost] [Boost] Compile-time power of a run-time base Para: boost@lists.boost.org
Hello,
I have written for the need of a coworker a function template that computesthe compile-time power of a base that is known only at runtime. The original need was just to avoid having to write things like "value*value*value*value*value".
Before doing this, I've been searching for such a thing in the Boost documentation and mailing lists, but could only find discussions about an entierely compile-time version (compile-time exponent of compile- time base) intended for use in metaprograms. Is there any reason why the "semi-compile-time" version I describe here hasn't been discussed? Eventhough it can be viewed as a mere syntactic sugar, it can be very practical when it comes to write by hand a power with a big exponent.
In case of interest, here is my code :
template <int N> struct positive_power { template <typename T> static float result(T base) { return base*positive_power<N-1>::result(base); } };
I think this is suboptimal: you need only log(N) multiplications to get positive_power<N>::result(base):
template <int N> struct positive_power { template <typename T> static float result(T base) { float aux=positive_power<N/2>::result(base); return (N%2)?base*aux*aux:aux*aux; } };
HTH,
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

AMDG Bruno Lalande wrote:
Hi Joaquin,
Yes you're right, thanks for the advice. I really thought that an optimizing compiler was able to figure out this by itself, that is, transform things like n*n*n*n into (n*n)*(n*n). But a few tests shew me I was wrong.
<snip> With your modification the function is finally much more than a syntactic helper since it runs faster than what an average programmer would type by hand. Shouldn't it be integrated somewhere into Boost ?
There's such a function in Boost.Units. It was originally needed because the the result type depends on the exponent which must therefore be known at compile time. boost::units::quantity<boost::units::SI::area> area = boost::units::pow<2>(3.0 * boost::units::SI::meters); Note that this is not in the trunk yet. In Christ, Steven Watanabe

Bruno Lalande wrote:
With your modification the function is finally much more than a syntactic helper since it runs faster than what an average programmer would type by hand. Shouldn't it be integrated somewhere into Boost ?
It sounds pretty useful to me too: indeed I was just wondering the other day why C++ doesn't have functions for squares and cubes (they're handy if you want to square or cube some other - maybe complex - expression). If someone would like to package it up with tests and docs, I'd be happy to integrate this into Boost.Math. Regards, John.

If someone would like to package it up with tests and docs, I'd be happy to integrate this into Boost.Math.
Yes I think Boost.Math is the right place for this too. And Boost.Unit will be able to take it there instead of having it confined in a "units::details" or something, this way everybody can benefit of this useful thing. I can write tests and docs for you, as well as study the different performance / optimization aspects with some other compilers. As I've never done this before, I'll have to read the different guidelines describing the way in which such contributions have to be made, so it can take a few days. But I think we're not in a hurry. Steven, could you tell me if some aspects of the implementation you made for Boost.Unit are better than mine? This would permit to be sure to have the best implementation in Boost.Math. Bruno

On Feb 3, 2008 1:28 PM, Bruno Lalande <bruno.lalande@gmail.com> wrote:
I can write tests and docs for you, as well as study the different performance / optimization aspects with some other compilers. As I've never done this before, I'll have to read the different guidelines describing the way in which such contributions have to be made, so it can take a few days. But I think we're not in a hurry.
Steven, could you tell me if some aspects of the implementation you made for Boost.Unit are better than mine? This would permit to be sure to have the best implementation in Boost.Math.
I've usually seen it described like this: template <int N> struct positive_power { template <typename T> static float result(T base) { return (N%2) ? positive_power<1>::result(base) * positive_power<N-1>::result(base) : positive_power<2>::result( positive_power<N/2>::result(base) ); } }; I have no idea whether that would work better or not. It would mean more template instantiations, of course, but avoiding storing it in a named temporary might make the optimizer happier. (Are there provisions for allowing different temporary sizes in floating point math? I seem to recall a flag for gcc that forces storing all the intermediate results to prevent this, so there might be.) I'd also wonder whether -ffast-math or similar flags make a difference.

template <int N> struct positive_power { template <typename T> static float result(T base) { return (N%2) ? positive_power<1>::result(base) * positive_power<N-1>::result(base) : positive_power<2>::result( positive_power<N/2>::result(base) ); } };
I have no idea whether that would work better or not.
Basically, it gives the same performance without the need of a specialization with 3. But this time you have to specialize with 2 if you don't want your code to enter into an infinite loop in that case (power<2>(n) = power<2>(power<1>(n)) = power<2>(power<1>(power<1>(n))), etc....). My tests show that your solution is better for some exponents and less good for some others, so I don't really know which one to choose. I will do the same analysis on a few other platforms to make a decision. I'd also
wonder whether -ffast-math or similar flags make a difference.
Nope, there's no difference with this additional flag on my computer. Thanks Bruno

AMDG Bruno Lalande wrote:
Yes I think Boost.Math is the right place for this too. And Boost.Unit will be able to take it there instead of having it confined in a "units::details" or something, this way everybody can benefit of this useful thing.
I can write tests and docs for you, as well as study the different performance / optimization aspects with some other compilers. As I've never done this before, I'll have to read the different guidelines describing the way in which such contributions have to be made, so it can take a few days. But I think we're not in a hurry.
Steven, could you tell me if some aspects of the implementation you made for Boost.Unit are better than mine? This would permit to be sure to have the best implementation in Boost.Math.
Your implementation seems to be faster in the few tests I ran on msvc 9.0. It would be nice if boost::units::pow could be completely replaced by this utility, so here are the issues that would need to the covered: * The result type is not necessarily going to be the same as the arguments so it would need to use Boost.Typeof or some such. * Rational exponents need to work, so I would need a way to specialize the function to work with boost::units::static_rational. I would expect the customization mechanism to look something like this: struct default_value_tag; template<class T> struct pow_value_tag { typedef default_value_tag tag; }; template<class Exp> struct pow_exponent_tag { typedef typename Exp::tag type; }; template<class ValueTag, class ExponentTag> struct pow_impl; template<class Value, class Exponent> struct pow { typedef typename pow_impl< typename pow_value_tag<Value>::type, typename pow_exponent_tag<Exponent>::type >::template apply<Value, Exponent> impl; typedef typename impl::type type; static type call(const Value& v) { return(impl::call(v)); } }; In Christ, Steven Watanabe

* The result type is not necessarily going to be the same as the arguments so it would need to use Boost.Typeof or some such.
Yep, I had already thought about this improvement.
* Rational exponents need to work, so I would need a way to specialize the function to work with boost::units::static_rational. I would expect the customization mechanism to look something like this:
struct default_value_tag;
template<class T> struct pow_value_tag { typedef default_value_tag tag; };
template<class Exp> struct pow_exponent_tag { typedef typename Exp::tag type; };
template<class ValueTag, class ExponentTag> struct pow_impl;
template<class Value, class Exponent> struct pow { typedef typename pow_impl< typename pow_value_tag<Value>::type, typename pow_exponent_tag<Exponent>::type
::template apply<Value, Exponent> impl; typedef typename impl::type type; static type call(const Value& v) { return(impl::call(v)); } };
OK I will consider this need and find a way to satisfy it. I'm going to write a first version of tests and docs with the implementation we have for now, and then I'll add those additional functionalities. Thanks Bruno

Bruno Lalande wrote:
* The result type is not necessarily going to be the same as the arguments so it would need to use Boost.Typeof or some such.
Yep, I had already thought about this improvement.
The only use case I can think of is where the argument is an integer rather than a real number (and the result is therefore a double), if that's the case then typename boost::math::tools::promote_args<T>::type would provide what's needed.
* Rational exponents need to work, so I would need a way to specialize the function to work with boost::units::static_rational. I would expect the customization mechanism to look something like this:
struct default_value_tag;
template<class T> struct pow_value_tag { typedef default_value_tag tag; };
template<class Exp> struct pow_exponent_tag { typedef typename Exp::tag type; };
template<class ValueTag, class ExponentTag> struct pow_impl;
template<class Value, class Exponent> struct pow { typedef typename pow_impl< typename pow_value_tag<Value>::type, typename pow_exponent_tag<Exponent>::type
::template apply<Value, Exponent> impl; typedef typename impl::type type; static type call(const Value& v) { return(impl::call(v)); } };
OK I will consider this need and find a way to satisfy it.
I'm going to write a first version of tests and docs with the implementation we have for now, and then I'll add those additional functionalities.
I'm a bit concerned about this interface: my guess is that 90% or more of users would just want integer exponents, and these should be very easy to use, preferably simply: pow<2>(val) Hmmm, I wonder if we can define an overload such that: pow<2,3>(val) is also valid? Regards, John.

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock Sent: 05 February 2008 10:26 To: boost@lists.boost.org Subject: Re: [boost] [Boost] Compile-time power of a run-time base
Bruno Lalande wrote:
* The result type is not necessarily going to be the same as the arguments so it would need to use Boost.Typeof or some such.
Yep, I had already thought about this improvement.
The only use case I can think of is where the argument is an integer rather than a real number (and the result is therefore a double),
boost.units: pow<3>( length ) is going to have units of volume.
* Rational exponents need to work, so I would need a way to specialize the function to work with boost::units::static_rational. I would expect the customization
I'm a bit concerned about this interface: my guess is that 90% or more of users would just want integer exponents, and these should be very easy to use, preferably simply:
pow<2>(val)
Hmmm, I wonder if we can define an overload such that:
pow<2,3>(val)
is also valid?
... and I /believe/ that boost.units only needs half powers. So (modulu units) template<class T1, class T2, int N> T2 pow<N,2>(T1 val) { return sqrt(pow<N>(val)); } should do it. ... in fact, I suspect that boost.math pow should /only/ offer the integral powers, and boost.units should wrap it to add the rational support. -- Martin Bonner Senior Software Engineer/Team Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com disclaimer

Martin Bonner wrote:
The only use case I can think of is where the argument is an integer rather than a real number (and the result is therefore a double),
boost.units: pow<3>( length ) is going to have units of volume.
Ah yes, forgot that. My gut feeling is that Boost.Math should concentrate on the um... math: provide a nice simple implementation that's reasonably efficient too. And libraries like Boost.Units can overload it for dimentioned-quantities, and use the Boost.Math version for the internal calculation. Does this make sense?
... and I /believe/ that boost.units only needs half powers. So (modulu units)
template<class T1, class T2, int N> T2 pow<N,2>(T1 val) { return sqrt(pow<N>(val)); }
should do it.
... in fact, I suspect that boost.math pow should /only/ offer the integral powers, and boost.units should wrap it to add the rational support.
I guess the question is can we evaluate half-powers more efficiently than just using pow? Maybe, but it's not so obvious to me as it is for smallish integer powers. John.

AMDG John Maddock wrote:
Ah yes, forgot that. My gut feeling is that Boost.Math should concentrate on the um... math: provide a nice simple implementation that's reasonably efficient too. And libraries like Boost.Units can overload it for dimentioned-quantities, and use the Boost.Math version for the internal calculation. Does this make sense?
Unfortunately, calls like pow<1>(x) will not use ADL. So it becomes difficult to write generic functions.
I guess the question is can we evaluate half-powers more efficiently than just using pow? Maybe, but it's not so obvious to me as it is for smallish integer powers.
Not that I know of. I'm more interested in polymorphism than performance. In Christ, Steven Watanabe

From: John Maddock
Martin Bonner wrote:
The only use case I can think of is where the argument is an integer rather than a real number (and the result is therefore a double),
boost.units: pow<3>( length ) is going to have units of volume.
Ah yes, forgot that. My gut feeling is that Boost.Math should concentrate on the um... math: provide a nice simple implementation that's reasonably efficient too. And libraries like Boost.Units can overload it for dimentioned-quantities, and use the Boost.Math version for the internal calculation. Does this make sense? In principle yes, but in practise, I think Boost.Units will need to calculate the result type via the * operator, so it might as well calculate the result value at the same time. Of course, that doesn't mean Boost.Units can't copy the implementation mechanism but then the advantage of having "pow" in a single location is lost.
If double + Boost.Units can be supported without too much complexity, then I think it should be. Otherwise, just handle double.
... and I /believe/ that boost.units only needs half powers. So (modulu units)
template<class T1, class T2, int N> T2 pow<N,2>(T1 val) { return sqrt(pow<N>(val)); }
should do it.
... in fact, I suspect that boost.math pow should /only/ offer the integral powers, and boost.units should wrap it to add the rational support.
I guess the question is can we evaluate half-powers more efficiently than just using pow? Maybe, but it's not so obvious to me as it is
smallish integer powers. I would expect that a general purpose pow would internally involve a logarithm, a multiplication, and an exponentiation (not necessarily to
for base e). My gut reaction is that will be slower than a few multiplications and a sqrt (but gut reaction is a pessimal way of optimizing). -- Martin Bonner Senior Software Engineer/Team Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com disclaimer

Hello,
boost.units: pow<3>( length ) is going to have units of volume.
Ah yes, forgot that. My gut feeling is that Boost.Math should concentrate on the um... math: provide a nice simple implementation that's reasonably efficient too. And libraries like Boost.Units can overload it for dimentioned-quantities, and use the Boost.Math version for the internal calculation. Does this make sense? In principle yes, but in practise, I think Boost.Units will need to calculate the result type via the * operator, so it might as well calculate the result value at the same time. Of course, that doesn't mean Boost.Units can't copy the implementation mechanism but then the advantage of having "pow" in a single location is lost.
About the result type issue, my original think was just a chain of type deductions that would have looked like this: positive_power<0, T> returns a int (the scalar 1) positive_power<1, T> returns a T positive_power<N, T> returns the type of operator*(T, type of positive_power<N-1>) power_if_positive<N, T, true> returns the type of positive_power<N> power_if_positive<N, T, false> returns the type of operator/(double, type of positive_power<N>) power<N, T> returns the type of power_if_positive<N> But I haven't dug yet about the possible implementation of this approach. The two questions that come to my mind are : - are all those type deductions even possible with Boost.Typeof? (I know about the main principle of Boost.Typeof but have never really used it before) - is this approach going to return the right type in all cases for Boost.Units? (that is, for instance, does operator*(length, length) return an area, does operator*(length, operator*(length, length)) return a volume, etc...) And what about power<0>? Is there a "scalar" type in Boost.Units? For now I continue to concentrate on the first general solution we already have and performance-test the different approaches on several platforms. Regards Bruno

Hi, You will find attached to this mail the header file of the pow function, a cpp test file and the documentation in .qbk format. I tried to write docs and tests in accordance to those found in the math library. The files are ready for integration since I placed them respectively into boost/math, libs/math/test and libs/math/doc in my own environment. Let me know if anything has to be changed or added. I passed the tests on : - gcc-2.95 (debian) - gcc-3.3 (debian) - gcc-3.4 (debian) - gcc-4.1 (kubuntu) - icc-10.1 (debian) - msvc-8.0 (XP SP2) - msvc-9.0 (XP SP2) It didn't compile with msvc-6.5. It's not surprising since, if I remember well, this compiler doesn't handle partial template specialization even with SP5. Is this compiler still officially supported by Boost? There is one case for which I don't know what to do : the pow<negative value>(0) case, which obviously crashes since it consists of computing 1/0. Should I check it and throw something, or let the platform's division by 0 behavior (if any) do its effect? I personally think the first approach is better since it ensures an uniform behavior accross platforms. The return type is a double. Now I'm going to study the possibility of having different possible return types. Regards Bruno

Bruno Lalande wrote:
Hi,
You will find attached to this mail the header file of the pow function, a cpp test file and the documentation in .qbk format. I tried to write docs and tests in accordance to those found in the math library. The files are ready for integration since I placed them respectively into boost/math, libs/math/test and libs/math/doc in my own environment. Let me know if anything has to be changed or added.
I passed the tests on : - gcc-2.95 (debian) - gcc-3.3 (debian) - gcc-3.4 (debian) - gcc-4.1 (kubuntu) - icc-10.1 (debian) - msvc-8.0 (XP SP2) - msvc-9.0 (XP SP2)
It didn't compile with msvc-6.5. It's not surprising since, if I remember well, this compiler doesn't handle partial template specialization even with SP5. Is this compiler still officially supported by Boost?
There is one case for which I don't know what to do : the pow<negative value>(0) case, which obviously crashes since it consists of computing 1/0. Should I check it and throw something, or let the platform's division by 0 behavior (if any) do its effect? I personally think the first approach is better since it ensures an uniform behavior accross platforms.
Can you follow the error handling policies for overflow here: http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too... ? You will need to overload pow like this: template <int N, class T, class Policy> typename tools::promote_args<T>::type pow(T, const Policy&) { // Actual implementation goes here: uses the specified policy to handle errors. } template <int N, class T> inline typename tools::promote_args<T>::type pow(T x) { return pow<N>(x, policies::policy<>()); }
The return type is a double. Now I'm going to study the possibility of having different possible return types.
Using boost::math::tools::promote_args<T>::type to calculate the result type based on the argument type will work for integer and floating point args: not sure how this integrates with Boost.Units though. Keep up the good work! John.

Hi John,
Can you follow the error handling policies for overflow here:
http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too...
OK, this is done. Using boost::math::tools::promote_args<T>::type to calculate the result type
based on the argument type will work for integer and floating point args: not sure how this integrates with Boost.Units though.
Maybe we don't have the same need here. What I don't understand is the fact that for you, a power with integral argument should return a double. My original need when I first talked about returning different possible types was just to respect the type used by the caller. That is, if the caller asks for pow<2>(int) and works with integers in all the rest of its code, providing the result in a float or double can be disturbing and even slow it down. For instance, returning the result of pow<2>(10) in a float sounds unnatural to me if 10 was originally stored in an int. But obviously, pow<-N>(int) should return a floating point since the result is of the form 1/int. If I understand well, your approach is rather to take care of providing a type capable of holding the result even in case of big integral exponent and big integral base. Am I right or is there another rationale behind what you propose? Which one of those two approaches is the most appropriated in your opinion? Thanks Bruno

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bruno Lalande Sent: 12 February 2008 09:24 To: boost@lists.boost.org Subject: Re: [boost] [Boost] Compile-time power of a run-time base
Maybe we don't have the same need here. What I don't understand is the fact that for you, a power with integral argument should return a double. My original need when I first talked about returning different possible types was just to respect the type used by the caller. That is, if the caller asks for pow<2>(int) and works with integers in all the rest of its code, providing the result in a float or double can be disturbing and even slow it down. For instance, returning the result of pow<2>(10) in a float sounds unnatural to me if 10 was originally stored in an int. But obviously, pow<-N>(int) should return a floating point since the result is of the form 1/int.
If I understand well, your approach is rather to take care of providing a type capable of holding the result even in case of big integral exponent and big integral base. Am I right or is there another rationale behind what you propose?
I feel there is an assumption that most applications will use the resultant value in a calculation using a floating-point type, so you don't lose anything by not returning an integral type. And it reduces the (quite serious) risk of overflowing the integer type. It avoids an ugly asymmetry with negative exponents too. While it might be possible to test if the result will overflow, it all sounds a bit too complicated. But I have to admit that there will be occasions when an integer type is the Right Type. But there are other ways of achieving this when efficiency demands it. So on balance, I think following the rules used in Math Toolkit sounds the best compromise. "These rules are chosen to be compatible with the behaviour of ISO/IEC 9899:1999 Programming languages - C and with the Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 5. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf " Perhaps, to allow us to 'have our cake and eat it', some other name (int_positive_pow?) could be used for a version that returns an integral type? This would have an *unsigned* exponent parameter? But I am also not quite clear what int type should be returned. And if and how the serious risk of overflow should be dealt with. Is it all getting a bit too complicated? Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Paul A Bristow wrote:
So on balance, I think following the rules used in Math Toolkit sounds the best compromise.
"These rules are chosen to be compatible with the behaviour of ISO/IEC 9899:1999 Programming languages - C and with the Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 5.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf "
Right the idea is to be compatible with what C99 and C++0x do when an integer argument is passed to a math function. The other issue is that if: pow<-3>(2) returned an integer, then presumably it can only return 0, which isn't exactly right :-) John.

Hello,
"These rules are chosen to be compatible with the behaviour of
ISO/IEC 9899:1999 Programming languages - C and with the Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 5.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf "
Right the idea is to be compatible with what C99 and C++0x do when an integer argument is passed to a math function.
OK I have read this section of the draft and now I understand better the purpose of promote_args, so I will use it in order to to be C99 and C++0x compliant.
The other issue is that if:
pow<-3>(2)
returned an integer, then presumably it can only return 0, which isn't exactly right :-)
Just to see if it was even possible, I've implemented what I had talked about before. It takes this issue into account. Basically, here is the output of my test program with the result of pow on several types and their corresponding typeids: pow<2>(2) = (i)4 pow<2>(2.0) = (d)4 pow<2>(2.0f) = (f)4 pow<-2>(2) = (d)0.25 pow<-2>(2.0) = (d)0.25 pow<-2>(2.0f) = (d)0.25 And regarding the way in which I did it, I "guess" a use with Boost.Unitswould give the expected result. Something like: pow<3>((length)5) = (volume)125; But the most important is to implement the promote_args version. I will provide this soon. After that we can always propose, as Paul said, a special version with a different name. Regards Bruno

Hello, Here is a new version of the pow.hpp file with updated tests and docs. It nows handles errors using the Boost.Math overflow error policy, and uses promote_args to determine the return type. I've tested it on the same platforms as before, BUT it no longer compiles with gcc-2.95.4. The first reason was that policy.hpp includes <limits> that gcc 2.95 doesn't have so I replaced it by <boost/limits.hpp> and it worked, but some other Boost files include other headers that are also missing (ios for instance, included in lcast_precision.hpp). Is the support for that compiler required? Bruno On Feb 15, 2008 10:49 AM, Bruno Lalande <bruno.lalande@gmail.com> wrote:
Hello,
"These rules are chosen to be compatible with the behaviour of
ISO/IEC 9899:1999 Programming languages - C and with the Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 5.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf "
Right the idea is to be compatible with what C99 and C++0x do when an integer argument is passed to a math function.
OK I have read this section of the draft and now I understand better the purpose of promote_args, so I will use it in order to to be C99 and C++0x compliant.
The other issue is that if:
pow<-3>(2)
returned an integer, then presumably it can only return 0, which isn't exactly right :-)
Just to see if it was even possible, I've implemented what I had talked about before. It takes this issue into account. Basically, here is the output of my test program with the result of pow on several types and their corresponding typeids: pow<2>(2) = (i)4 pow<2>(2.0) = (d)4 pow<2>(2.0f) = (f)4 pow<-2>(2) = (d)0.25 pow<-2>(2.0) = (d)0.25 pow<-2>(2.0f) = (d)0.25 And regarding the way in which I did it, I "guess" a use with Boost.Unitswould give the expected result. Something like: pow<3>((length)5) = (volume)125;
But the most important is to implement the promote_args version. I will provide this soon. After that we can always propose, as Paul said, a special version with a different name.
Regards Bruno

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bruno Lalande Sent: 17 February 2008 17:04 To: boost@lists.boost.org Subject: Re: [boost] [Boost] Compile-time power of a run-time base
Here is a new version of the pow.hpp file with updated tests and docs. It nows handles errors using the Boost.Math overflow error policy, and uses promote_args to determine the return type.
Nice.
I've tested it on the same platforms as before, BUT it no longer compiles with gcc-2.95.4. The first reason was that policy.hpp includes <limits> that gcc 2.95 doesn't have so I replaced it by <boost/limits.hpp> and it worked, but some other Boost files include other headers that are also missing (ios for instance, included in lcast_precision.hpp). Is the support for that compiler required?
Not by me ;-) I would not spend time on this outdated compiler. Surely people who really want to use a compile tile pow will be using more modern compilers? Docs might provide a reference or few. I found http://www.scl.ameslab.gov/Publications/Gus/FiveMultiplications/node9.html by a very quick Google I'm sure we should give Knuth his due for having done everything before we even thought of it ;-) D.E. Knuth, The Art of Computer Programming, Vol. 2: seminumerical Algorithms, 2nd ed. Addison-Wesley, Reading, MA, 1981. I think occurrence has two cs and two r as well ;-) Would the words 'compile-time integer integral power' ensure that this doucmentation pops up when Googling? (Would the expression 'known at compile time' be clearer than 'known in advance'?) Should there be a less formal description of the user interface - perhaps simplified from the two actual templates in pow.hpp? It looks more complicated than it really is in pow.hpp. Would what I might call a 'demo' program show its use more simply for novices than the formal test ? It could show use of policies - something that may frighten some users - it did me at first ;-) It could show how especially useful is using try/catch is with policies? Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Hi, Thanks for your feedback, I will take it into account to improve the documentation. Actually I wasn't sure how long and detailed it was expected to be, so I preferred to do something short at first. Also for the description of error handling, I didn't want to end up with something too repetitive regarding what is already described in the Boost.Math error handling documentation. But indeed, a short and concise enough demo could be of help. About the "known in advance" expression, I myself hesitated a lot. The choice depends on who we prefer to talk to : the mathematician (for whom "fixed" and "known in advance" should be more natural) or the programmer (who will find "known at compile-time" more expressive). Thanks Bruno On Feb 17, 2008 7:35 PM, Paul A Bristow <pbristow@hetp.u-net.com> wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bruno Lalande Sent: 17 February 2008 17:04 To: boost@lists.boost.org Subject: Re: [boost] [Boost] Compile-time power of a run-time base
Here is a new version of the pow.hpp file with updated tests and docs. It nows handles errors using the Boost.Math overflow error policy, and uses promote_args to determine the return type.
Nice.
I've tested it on the same platforms as before, BUT it no longer compiles with gcc-2.95.4. The first reason was that policy.hpp includes <limits> that gcc 2.95 doesn't have so I replaced it by <boost/limits.hpp> and it worked, but some other Boost files include other headers that are also missing (ios for instance, included in lcast_precision.hpp). Is the support for that compiler required?
Not by me ;-) I would not spend time on this outdated compiler. Surely people who really want to use a compile tile pow will be using more modern compilers?
Docs might provide a reference or few. I found
http://www.scl.ameslab.gov/Publications/Gus/FiveMultiplications/node9.html
by a very quick Google
I'm sure we should give Knuth his due for having done everything before we even thought of it ;-)
D.E. Knuth, The Art of Computer Programming, Vol. 2: seminumerical Algorithms, 2nd ed. Addison-Wesley, Reading, MA, 1981.
I think occurrence has two cs and two r as well ;-)
Would the words 'compile-time integer integral power' ensure that this doucmentation pops up when Googling?
(Would the expression 'known at compile time' be clearer than 'known in advance'?)
Should there be a less formal description of the user interface - perhaps simplified from the two actual templates in pow.hpp? It looks more complicated than it really is in pow.hpp.
Would what I might call a 'demo' program show its use more simply for novices than the formal test ? It could show use of policies - something that may frighten some users - it did me at first ;-) It could show how especially useful is using try/catch is with policies?
Paul
--- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Bruno Lalande wrote:
Hi,
Thanks for your feedback, I will take it into account to improve the documentation. Actually I wasn't sure how long and detailed it was expected to be, so I preferred to do something short at first. Also for the description of error handling, I didn't want to end up with something too repetitive regarding what is already described in the Boost.Math error handling documentation. But indeed, a short and concise enough demo could be of help.
About the "known in advance" expression, I myself hesitated a lot. The choice depends on who we prefer to talk to : the mathematician (for whom "fixed" and "known in advance" should be more natural) or the programmer (who will find "known at compile-time" more expressive).
How about simply "known at compile time" as a compromise :-) John.

John Maddock wrote:
How about simply "known at compile time" as a compromise :-)
John.
I'm a mathematician. And I prefer "known at compile-time". It is the standard term in this context. Also, "known in advance" is imprecise. In advance of what? Both as a mathematician and as a programmer I like precision. --Johan Råde

How about simply "known at compile time" as a compromise :-)
John.
I'm a mathematician. And I prefer "known at compile-time". It is the standard term in this context.
Also, "known in advance" is imprecise. In advance of what? Both as a mathematician and as a programmer I like precision.
OK, so let's go for "known at compile-time" :-) Bruno

Hello, Here is the documentation updated regarding the requests made above. Error handling customization is now explained with an example. I describe a call with a user_error policy, and also the use of the BOOST_MATH_OVERFLOW_ERROR_POLICY macro. However, I don't show any example of use of a try/catch block with the default call, because using try/catch is a widely known C++ practice so I assume that the user knows what he has to do when I say "by default a std::overflow_error is thrown". Do you think such a trivial example should be present anyway? By the way, there is a slight error in this page: http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too... The first line of the first code section opens the namespace "policy" instead of "policies". Let me know if there's anything to modify again. What about the possibility of allowing a return type compatible with Boost.Units and/or possibly integral ? I see 3 solutions: - a return type policy in second template argument (with the current one as default) - a completely different function name - nothing at all (stick to the standard and nothing else) Regards Bruno

Bruno Lalande wrote:
Hello,
Here is the documentation updated regarding the requests made above. Error handling customization is now explained with an example. I describe a call with a user_error policy, and also the use of the BOOST_MATH_OVERFLOW_ERROR_POLICY macro. However, I don't show any example of use of a try/catch block with the default call, because using try/catch is a widely known C++ practice so I assume that the user knows what he has to do when I say "by default a std::overflow_error is thrown". Do you think such a trivial example should be present anyway?
By the way, there is a slight error in this page: http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too... The first line of the first code section opens the namespace "policy" instead of "policies".
Oops, fixed in SVN, thanks for spotting that.
Let me know if there's anything to modify again.
In: * `errno_on_error`: Sets `::errno` to `EDOM and` returns `std::numeric_limits<T>::quiet_NaN()`. * `ignore_error`: Returns `std::numeric_limits<T>::quiet_NaN()`. Actually an overflow error returns *infinity* not NaN. And in: namespace boost { namespace math { namespace policies { template <class T> T user_overflow_error(const char*, const char*, const T&) { return 123.456; } }}} You later check for -1 as a result, so should this be returning -1? And in: // Redefine the default error_overflow policy #define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error // From this point, passing a policy in argument is no longer needed, a call like this one // will return -1 in case of error: double result = pow<-5>(base); No not -1, but infinity (again) :-) I'd be inclined to place the synopsis at the top of the file: that way those already comfortable with the library can just get stuck right in without having to re-read the tutorial :-) "JoaquÃn López Muñoz" appears mangled in my version: this might be safer encoded using XML escape sequences rather than UTF8?
What about the possibility of allowing a return type compatible with Boost.Units and/or possibly integral ? I see 3 solutions: - a return type policy in second template argument (with the current one as default) - a completely different function name - nothing at all (stick to the standard and nothing else)
Well.... for Boost.Math I'd be happy with it as it is.... I'm assuming that the units folks can provide an overload looking something like: template <int p, class Unit, class Y> inline computed-result-type pow(const quantity<Unit,Y>& u) { typedef computed-result-type result_type; return result_type(boost::math::pow<p>(u.value())); } ???? John.

Ouch... looks like a lot of unfortunate copy-pastes were made :-) Sorry for that, It's fixed now. For the macro, actually it's a user_error policy that I wanted to use, so I replaced this and left the -1 which is thus OK.
I'd be inclined to place the synopsis at the top of the file: that way those already comfortable with the library can just get stuck right in without having to re-read the tutorial :-)
OK, and I moved the "header file" section as well since those two sections must remain tied, I think. "Joaquín López Muñoz" appears mangled in my version: this might be safer
encoded using XML escape sequences rather than UTF8?
I've put the whole phrase into a ''' section with escape characters inside as you can see in the attached file, but the generated HTML page is the same (still unicode) so I think it won't solve the problem for you (I can't reproduce it here). I'm not really aware of the possibilities of QuickBook for escape sequences... the goal would be to have the generated HTML source itself written in terms of escape sequences for those characters, not only in the qbk file. I can I do that?
template <int p, class Unit, class Y> inline computed-result-type pow(const quantity<Unit,Y>& u) { typedef computed-result-type result_type; return result_type(boost::math::pow<p>(u.value())); }
????
You're right. What I had thought about was actually over-engineered as I thought it was necessary to have every sub-call returning the right type (that is, the first product returning an area, then the second one returning a volume, etc...). I hadn't realized it was possible to just cast the final resulting double into the right Boost.Units type. Bruno

Bruno Lalande wrote:
Ouch... looks like a lot of unfortunate copy-pastes were made :-) Sorry for that, It's fixed now. For the macro, actually it's a user_error policy that I wanted to use, so I replaced this and left the -1 which is thus OK.
I'd be inclined to place the synopsis at the top of the file: that way those already comfortable with the library can just get stuck right in without having to re-read the tutorial :-)
OK, and I moved the "header file" section as well since those two sections must remain tied, I think.
"Joaquín López Muñoz" appears mangled in my version: this might be safer
encoded using XML escape sequences rather than UTF8?
I've put the whole phrase into a ''' section with escape characters inside as you can see in the attached file, but the generated HTML page is the same (still unicode) so I think it won't solve the problem for you (I can't reproduce it here). I'm not really aware of the possibilities of QuickBook for escape sequences... the goal would be to have the generated HTML source itself written in terms of escape sequences for those characters, not only in the qbk file. I can I do that?
I think you've probably done it already, but I'll check. In any case this looks fine now, any suggestions on where to integrate this with Boost.Math? Maybe in this section: http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too... ? Apologies for the delay in getting back to you on this... John.

Hello,
In any case this looks fine now, any suggestions on where to integrate this with Boost.Math?
Maybe in this section:
http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too...
I don't have a very good knowledge of the structure of Boost.Math in its whole, but this place seems to be fine, indeed. While quickly reading the other stuff in this section I saw a little typing error in powm1.html, "dufferent types" instead of "different types". By the way, I didn't know the existence of the page result_type.html, shouldn't I point to it in my doc, rather than boringly (and less accurately) repeat its contents? Bruno

Bruno Lalande wrote:
I don't have a very good knowledge of the structure of Boost.Math in its whole, but this place seems to be fine, indeed.
OK.
While quickly reading the other stuff in this section I saw a little typing error in powm1.html, "dufferent types" instead of "different types".
Oops! Will fix, thanks.
By the way, I didn't know the existence of the page result_type.html, shouldn't I point to it in my doc, rather than boringly (and less accurately) repeat its contents?
Yep, that would be better, but I can probably deal with that when I integrate your docs into mine - we have some templates and macros to help with all that boilerplate stuff. John.

By the way, I didn't know the existence of the page result_type.html, shouldn't I point to it in my doc, rather than boringly (and less accurately) repeat its contents?
Yep, that would be better, but I can probably deal with that when I integrate your docs into mine - we have some templates and macros to help with all that boilerplate stuff.
Nice, I let you do that. Bruno

Bruno Lalande wrote:
By the way, I didn't know the existence of the page result_type.html, shouldn't I point to it in my doc, rather than boringly (and less accurately) repeat its contents?
Yep, that would be better, but I can probably deal with that when I integrate your docs into mine - we have some templates and macros to help with all that boilerplate stuff.
Nice, I let you do that.
Hi Bruno, I've finally added this to the sandbox version of the Math.Toolkit: it'll get merged to Trunk next time we have a stable Boost.Math release ready to go. I made a few minor tweeks along the way and extended the tests a bit, so can you take a look and make sure everything looks OK to you? Cheers, John.

I've finally added this to the sandbox version of the Math.Toolkit: it'll get merged to Trunk next time we have a stable Boost.Math release ready to go. I made a few minor tweeks along the way and extended the tests a bit, so can you take a look and make sure everything looks OK to you?
Hi John, Yep, I've taken a look at the changes you made and all looks OK to me. Thanks :-) Bruno

AMDG John Maddock wrote:
I'm a bit concerned about this interface: my guess is that 90% or more of users would just want integer exponents, and these should be very easy to use, preferably simply:
pow<2>(val)
Hmmm, I wonder if we can define an overload such that:
pow<2,3>(val)
is also valid?
Regards, John.
Ok. How about: template<class N, class T> ... pow(T t); template<int N, class T> ... pow(T t) { return(pow<mpl::int_<N> >(t)); } In Christ, Steven Watanabe
participants (8)
-
"JOAQUIN LOPEZ MU?Z"
-
Bruno Lalande
-
Johan Råde
-
John Maddock
-
Martin Bonner
-
Paul A Bristow
-
Scott McMurray
-
Steven Watanabe