/* *************************************************************

Copyright 2010 Terry Lyons, Stephen Buckley, Djalil Chafai,
Greg Gyurk� and Arend Janssen.

Distributed under the terms of the GNU General Public License,
Version 3. (See accompanying file License.txt)

************************************************************* */

#pragma once
#ifndef ConstLog2_h__
#define ConstLog2_h__

namespace alg {

/// A template for constructing integer constants

/// For \f$exp > 0\f$, produces the largest unsigned long long integer \f$ans\f$
/// such that \f$2^(ans+1) > exp\f$ and \f$ans\f$ is smallest integer with this
/// property.

template<unsigned long long exp>
struct ConstLog2 {
    enum
    {
        ans = ConstLog2<exp / 2>::ans + 1
    };
};

template<>
struct ConstLog2<1> {
    enum
    {
        ans = 0
    };
};

template<>
struct ConstLog2<0> {
    enum
    {
        ans = 0
    };
};
/// Test of ConstLog2 template
template<unsigned long long RANGE>
struct TestConstLog2 {
    enum
    {
        ans = ((RANGE >> ConstLog2<RANGE>::ans) == 1) && TestConstLog2<RANGE - 1>::ans
    };
};

template<>
struct TestConstLog2<1> {
    enum
    {
        ans = ((1 >> ConstLog2<1>::ans) == 1) && (ConstLog2<0>::ans == 0)
    };
};

}// namespace alg

#endif// ConstLog2_h__
