Skip to content

Commit

Permalink
fixing pow<>
Browse files Browse the repository at this point in the history
0^0 now correclty yields 1
  • Loading branch information
brunocodutra committed Apr 11, 2016
1 parent 64f0775 commit 5044e9a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
1 change: 0 additions & 1 deletion example/src/number/arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ using x = metal::pow_t<
>;

static_assert(std::is_same<x, metal::number<long, -16807>>::value, "");
static_assert(!metal::is_just</**/metal::pow</**/metal::integer<0>, metal::integer<0>>>::value, "");
static_assert(!metal::is_just</**/metal::pow</**/metal::integer<0>, metal::integer<-3>>>::value, "");
/// [pow]
}
42 changes: 32 additions & 10 deletions include/metal/number/arithmetic/pow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,10 @@ namespace metal
namespace detail
{
template<typename T>
constexpr T pow_impl(T base, T exp, T result = 1){
return !exp ?
result :
exp < 0 ?
pow_impl(1/(base*base), -exp/2, -exp%2 ? result/base : result) :
pow_impl(base*base, exp/2, exp%2 ? result*base : result);
constexpr T pow_impl(T base, T exp, T result = 1) {
return exp == 1 ?
base*result :
pow_impl(base*base, exp/2, exp%2 ? result*base : result);
}

template<typename... nums>
Expand All @@ -87,19 +85,43 @@ namespace metal

template<typename tx, tx vx, typename ty, ty vy, typename... nums>
struct pow<number<tx, vx>, number<ty, vy>, nums...> :
pow<
number<decltype(vx*vy), pow_impl<decltype(vx*vy)>(vx, vy)>,
nums...
conditional<
boolean<vy < 0>,
pow<number<decltype(vx*vy), 0>, nums...>,
pow<
number<decltype(vx*vy), pow_impl<decltype(vx*vy)>(vx, vy)>,
nums...
>
>
{};

template<typename tx, typename ty, ty vy, typename... nums>
struct pow<number<tx, tx(0)>, number<ty, vy>, nums...> :
conditional<
boolean<(vy > 0)>,
pow<number<decltype(tx(0)*vy), 0>, nums...>
pow<number<decltype(tx()*vy), 0>, nums...>
>
{};

template<typename tx, typename ty, ty vy, typename... nums>
struct pow<number<tx, tx(1)>, number<ty, vy>, nums...> :
pow<number<decltype(tx()*vy), 1>, nums...>
{};

template<typename tx, tx vx, typename ty, typename... nums>
struct pow<number<tx, vx>, number<ty, ty(0)>, nums...> :
pow<number<decltype(vx*ty()), 1>, nums...>
{};

template<typename tx, typename ty, typename... nums>
struct pow<number<tx, tx(0)>, number<ty, ty(0)>, nums...> :
pow<number<decltype(tx()*ty()), 1>, nums...>
{};

template<typename tx, typename ty, typename... nums>
struct pow<number<tx, tx(1)>, number<ty, ty(0)>, nums...> :
pow<number<decltype(tx()*ty()), 1>, nums...>
{};
}
}

Expand Down
5 changes: 3 additions & 2 deletions test/src/metal/number/arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
ASSERT((metal::is_just_t<metal::pow<NUMS(N)>>), (BOOL(N > 0))); \
ASSERT((metal::is_just_t<metal::div<NUMS(M) COMMA(AND(M, N)) NUMS(N)>>), (BOOL(!M ^ !N))); \
ASSERT((metal::is_just_t<metal::mod<NUMS(M) COMMA(AND(M, N)) NUMS(N)>>), (BOOL(!M ^ !N))); \
ASSERT((metal::is_just_t<metal::pow<NUMS(M) COMMA(AND(M, N)) NUMS(N)>>), (BOOL(!M ^ !N))); \
ASSERT((metal::is_just_t<metal::pow<NUMS(M) COMMA(M) metal::integer<-N>>>), (BOOL(!M))); \
ASSERT((metal::is_just_t<metal::pow<NUMS(M) COMMA(AND(M, N)) NUMS(N)>>), (BOOL(M || N))); \
ASSERT((metal::is_just_t<metal::pow<NUMS(M) COMMA(M) metal::integer<-N>>>), (BOOL(!M || !N))); \
ASSERT((metal::equal_to_t<metal::neg_t<metal::neg_t<NUM(N)>>, NUM(N)>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::inc_t<NUM(N)>, NUM(INC(N))>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::dec_t<NUM(INC(N))>, NUM(N)>), (TRUE)); \
Expand All @@ -52,6 +52,7 @@
ASSERT((metal::equal_to_t<metal::mod_t<NUMS(INC(N))>, NUM(0)>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::pow_t<NUMS(INC(N))>, NUM(0)>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::add_t<metal::mul_t<metal::div_t<NUM(M), NUM(INC(N))>, NUM(INC(N))>, metal::mod_t<NUM(M), NUM(INC(N))>>, NUM(M)>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::pow_t<NUM(0) COMMA(N) NUMS(N)>, metal::integer<!!N>>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::pow_t<NUM(1) COMMA(N) NUMS(N)>, NUM(1)>), (TRUE)); \
ASSERT((metal::equal_to_t<metal::pow_t<NUM(2), NUM(N)>, metal::integer<1 << N>>), (TRUE)); \
/**/
Expand Down

0 comments on commit 5044e9a

Please sign in to comment.