Topic: allow pow() to have an integer base?


Author: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Fri, 3 Sep 2004 00:49:51 GMT
Raw View
kwikius wrote:
>  template <unsigned int N> int pow(int v);
>
>  pow<2>(x);
>

Is 2 the base of the exponent? At first sight I would read it 2^x, but
you seem to intend x^2. Anyway, whatever choice you make is arbitrary,
as both choices have good reasons on their side. A

   template <int Base> int pow(unsigned Exponent);

could be as useful as

   template <unsigned Exponent> int pow(int Base);

And why not

   template <int Base, unsigned Exponent> int pow();

then?

The problem is that both operands may be unknown at compile time. A
template based implementation is certainly useful, but cannot replace a
"regular" function with two operands.

Regards,

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Sat, 4 Sep 2004 07:40:44 GMT
Raw View
Alberto Barbati <AlbertoBarbati@libero.it> wrote in message news:<KCKZc.73542$1V3.1780368@twister2.libero.it>...
> kwikius wrote:
> >  template <unsigned int N> int pow(int v);
> >
> >  pow<2>(x);
> >
>
> Is 2 the base of the exponent? At first sight I would read it 2^x, but
> you seem to intend x^2. Anyway, whatever choice you make is arbitrary,
> as both choices have good reasons on their side. A
>
>    template <int Base> int pow(unsigned Exponent);
>
> could be as useful as
>
>    template <unsigned Exponent> int pow(int Base);

Well in my case there is only one choice to make because I use a
similar function in my physical_quantities library.

http://www.servocomm.freeserve.co.uk/Cpp/physical_quantity/index.html
(New version available soon BTW ;-) )

Here types need to conform to dimensional analysis hence (pqs is the
library namespace).

pqs::length::m length = square.side_length();  // a length in meters
pqs::area::m2  area_of_square = pow<2>(length);  // an area in square
meters

note that eg
pqs::volume::m3 volume_of_cube = pow<2>(length);

will not compile because the result_type of pow2 length is an area.
I cant make any use of a runtime pow function because the resulting
type must be available at compile time, and its dependent on the
exponent to be available at compile_time too.

> And why not
>
>    template <int Base, unsigned Exponent> int pow();

This I actually do too in my pqs library except that it is a compile
time metafunction ala boost::mpl
in mpl it might look like:

 boost::mpl::pow<int_<Base>,int_<Exponent> >::apply::type::value;
(May be wrong...my mpl is not that good nevertheless its simple to
achieve via a recursive metafunction.)

> then?
>
> The problem is that both operands may be unknown at compile time. A
> template based implementation is certainly useful, but cannot replace a
> "regular" function with two operands.

It doesnt need to... std::pow(double,int) etc are already there. If
you dont know what the exponent is you must return a real type ;-)

The major issue with pow<N>(x)  is that it has problems with ADL,
however I think this can be solved by using an extra parameter:
(A trick from boost::numeric_cast() )

template<int N, template<int> class Pow>
    Result_type pow(type t, Pow<N> = Pow<N>() )
    {
        std::cout <<  "my " << N << "\n";
    }

pow(m,any_type_with_int_param<2>());

Though the user needs to think about it, to use this approach.

regards
Andy Little

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Sat, 4 Sep 2004 19:04:10 GMT
Raw View
kwikius wrote:
> Alberto Barbati <AlbertoBarbati@libero.it> wrote in message news:<KCKZc.73542$1V3.1780368@twister2.libero.it>...
>>
>>The problem is that both operands may be unknown at compile time. A
>>template based implementation is certainly useful, but cannot replace a
>>"regular" function with two operands.
>
> It doesnt need to... std::pow(double,int) etc are already there. If
> you dont know what the exponent is you must return a real type ;-)
>

pow(double, double) (as there's no pow(double, int)) performs an
approximate computation using floating point math. The whole point in
this thread is about a function that would perform the exact computation
using integer math alone.

Regards,

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Ben Strasser <ben04_01@freenet.de>
Date: Sat, 4 Sep 2004 23:21:35 GMT
Raw View
kwikius wrote:

>
> It doesnt need to... std::pow(double,int) etc are already there. If
> you dont know what the exponent is you must return a real type ;-)
>
Aha, so pow(int,unsigned int) and pow(unsigned int,unsigned int) can
return a non integral value?

You can surely cause an overflow but a no non integral value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Sun, 5 Sep 2004 15:56:47 GMT
Raw View
Alberto Barbati <AlbertoBarbati@libero.it> wrote in message news:<bPf_c.81951$OH4.2303570@twister1.libero.it>...
> kwikius wrote:
> > Alberto Barbati <AlbertoBarbati@libero.it> wrote in message news:<KCKZc.73542$1V3.1780368@twister2.libero.it>...
> >>
> >>The problem is that both operands may be unknown at compile time. A
> >>template based implementation is certainly useful, but cannot replace a
> >>"regular" function with two operands.
> >
> > It doesnt need to... std::pow(double,int) etc are already there. If
> > you dont know what the exponent is you must return a real type ;-)
> >
>
> pow(double, double) (as there's no pow(double, int))

BTW double pow(double, int) is part of the C++ standard.

 performs an
> approximate computation using floating point math. The whole point in
> this thread is about a function that would perform the exact computation
> using integer math alone.

Point taken. The only issue is whether you try to raise some sort of
error on overflow. Perhaps long would be better as the result as I
think its guaranteed 32 bits.

long pow(int Base, unsigned int Exponent)?

regards
Andy Little

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Mon, 6 Sep 2004 15:22:51 GMT
Raw View
Ben Strasser <ben04_01@freenet.de> wrote in message news:<2puppaFp6qk8U1@uni-berlin.de>...
> kwikius wrote:
>
> >
> > It doesnt need to... std::pow(double,int) etc are already there. If
> > you dont know what the exponent is you must return a real type ;-)
> >
> Aha, so pow(int,unsigned int) and pow(unsigned int,unsigned int) can
> return a non integral value?

Touche! You have me there my friend.
>
> You can surely cause an overflow but a no non integral value.


Hows about this. VC7.1 cl optimises the code below to constants :-):

#include <iostream>
template <unsigned int Exp>
inline long pow( int base)
{
    return base * pow<Exp-1>(base);
}
template<>
inline long pow<0>(int base) { return 1;}
template<>
inline long pow<1>(int base) { return base;}
template<>
inline long pow<2>(int base) { return base * base;}

int main()
{
   std::cout <<  pow<6>(10) <<'\n';
   std::cout <<  pow<0>(10) <<'\n';
   std::cout <<  pow<7>(2) << '\n';
   std::cout <<  pow<2>(0x100) << '\n';
}

regards
Andy Little

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Ben Strasser <ben04_01@freenet.de>
Date: Tue, 7 Sep 2004 03:06:22 GMT
Raw View
kwikius wrote:
>
> Hows about this. VC7.1 cl optimises the code below to constants :-):
>
> #include <iostream>
> template <unsigned int Exp>
> inline long pow( int base)
> {
>     return base * pow<Exp-1>(base);
> }
> template<>
> inline long pow<0>(int base) { return 1;}
> template<>
> inline long pow<1>(int base) { return base;}
> template<>
> inline long pow<2>(int base) { return base * base;}
>
> int main()
> {
>    std::cout <<  pow<6>(10) <<'\n';
>    std::cout <<  pow<0>(10) <<'\n';
>    std::cout <<  pow<7>(2) << '\n';
>    std::cout <<  pow<2>(0x100) << '\n';
> }
>
> regards
> Andy Little
>
So? That will only work if the exponent is a compiletime expression, and
you can assume that every standard conform compiler will make a constant
there (because it can be used in constant expressions so it needs to
able to compute that value at compiletime).

But that doesn't change that pow(unsigned int,unsigned int) can evaluate
at runtime.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: beliavsky@aol.com
Date: Tue, 31 Aug 2004 15:33:50 GMT
Raw View
According to http://www.dinkumware.com/htm_cpl/math.html#pow the
exponentiation functions in C and C++ are

pow, powf, powl
double pow(double x, double y);
float pow(float x, float y); [C++ only]
long double pow(long double x, long double y); [C++ only]
double pow(double x, int y); [C++ only]
float pow(float x, int y); [C++ only]
long double pow(long double x, int y); [C++ only]
float powf(float x, float y); [required with C99]
long double powl(long double x,
    long double y); [required with C99]

What about raising an integer to a power, especially to an integer
power? I often do this in Fortran using the ** operator.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jackklein@spamcop.net (Jack Klein)
Date: Wed, 1 Sep 2004 03:56:26 GMT
Raw View
On Tue, 31 Aug 2004 15:33:50 GMT, beliavsky@aol.com wrote in
comp.std.c++:

> According to http://www.dinkumware.com/htm_cpl/math.html#pow the
> exponentiation functions in C and C++ are
>
> pow, powf, powl
> double pow(double x, double y);
> float pow(float x, float y); [C++ only]
> long double pow(long double x, long double y); [C++ only]
> double pow(double x, int y); [C++ only]
> float pow(float x, int y); [C++ only]
> long double pow(long double x, int y); [C++ only]
> float powf(float x, float y); [required with C99]
> long double powl(long double x,
>     long double y); [required with C99]
>
> What about raising an integer to a power, especially to an integer
> power? I often do this in Fortran using the ** operator.

There are automatic conversions from the integer types to the floating
points.  The compiler will perform them automatically.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Wed, 1 Sep 2004 16:20:56 GMT
Raw View
jackklein@spamcop.net (Jack Klein) wrote in message news:<sqcaj0h125c3rt0k00o9buonnbhl7jml6a@4ax.com>...
> On Tue, 31 Aug 2004 15:33:50 GMT, beliavsky@aol.com wrote in
> comp.std.c++:
..
> > What about raising an integer to a power, especially to an integer
> > power? I often do this in Fortran using the ** operator.
>
> There are automatic conversions from the integer types to the floating
> points.  The compiler will perform them automatically.

The point is, it shouldn't convert to floating point. If the first
argument is an integer and the second one is non-negative, and the
result will fit in an integer, it can often be calculated faster, and
with less possibility of roundoff error, using integer operations than
with floating point ones.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: wade@stoner.com (Bill Wade)
Date: Wed, 1 Sep 2004 16:32:39 GMT
Raw View
jackklein@spamcop.net (Jack Klein) wrote in message news:<sqcaj0h125c3rt0k00o9buonnbhl7jml6a@4ax.com>...
> On Tue, 31 Aug 2004 15:33:50 GMT, beliavsky@aol.com wrote in
> comp.std.c++:
>
> > According to http://www.dinkumware.com/htm_cpl/math.html#pow the
> > exponentiation functions in C and C++ are
> >
> > pow, powf, powl
> > double pow(double x, double y);
> > [and lots of other floating-point types]
> >
> > What about raising an integer to a power, especially to an integer
> > power? I often do this in Fortran using the ** operator.
>
> There are automatic conversions from the integer types to the floating
> points.  The compiler will perform them automatically.

On some systems long's mantissa is bigger than double's.  The
automatic conversion gives the wrong answer.

Unexpected promotion in the middle of an expression can also change
the answer: assert(pow(3,1)/2==1);

Of course, now there is a backwards compatibility issue.  Adding
  int pow(int,int);
changes results.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Thu, 2 Sep 2004 15:45:09 GMT
Raw View
>
> Unexpected promotion in the middle of an expression can also change
> the answer: assert(pow(3,1)/2==1);
>
> Of course, now there is a backwards compatibility issue.  Adding
>   int pow(int,int);
> changes results.

 template <unsigned int N> int pow(int v);

 pow<2>(x);

//rational powers

 template<int N, int D> double pow(int V);

 pow<1,2>(x);

regards
Andy Little

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: beliavsky@aol.com
Date: Thu, 2 Sep 2004 20:09:04 GMT
Raw View
jackklein@spamcop.net (Jack Klein) wrote in message news:<sqcaj0h125c3rt0k00o9buonnbhl7jml6a@4ax.com>...
> On Tue, 31 Aug 2004 15:33:50 GMT, beliavsky@aol.com wrote in
> comp.std.c++:
>
> > According to http://www.dinkumware.com/htm_cpl/math.html#pow the
> > exponentiation functions in C and C++ are
> >
> > pow, powf, powl
> > double pow(double x, double y);
> > float pow(float x, float y); [C++ only]
> > long double pow(long double x, long double y); [C++ only]
> > double pow(double x, int y); [C++ only]
> > float pow(float x, int y); [C++ only]
> > long double pow(long double x, int y); [C++ only]
> > float powf(float x, float y); [required with C99]
> > long double powl(long double x,
> >     long double y); [required with C99]
> >
> > What about raising an integer to a power, especially to an integer
> > power? I often do this in Fortran using the ** operator.
>
> There are automatic conversions from the integer types to the floating
> points.  The compiler will perform them automatically.

Yes, but I think i^j where i and j are both integers should be
evaluated EXACTLY with integer arithmetic and return an integer. 2^10
= 1024, not 1023.99999999 , but rounding error is acceptable for
2.0^10. Maybe a new function called 'powint' should be created.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]