diff --git a/include/boost/integer/static_log2.hpp b/include/boost/integer/static_log2.hpp new file mode 100644 index 0000000..4b677f3 --- /dev/null +++ b/include/boost/integer/static_log2.hpp @@ -0,0 +1,109 @@ +// Boost static_log2.hpp header file ------------------------------- // + +// Copyright (C) 2003 Vesa Karvonen. +// Copyright (C) 2001 Daryle Walker. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. +// +// -------------------------------------------------------- +// See http://www.boost.org/libs/integer for documentation. +// --------------------------------------------------------------------------- // + +#ifndef BOOST_INTEGER_STATIC_LOG2_HPP +#define BOOST_INTEGER_STATIC_LOG2_HPP + + +#include "boost/config.hpp" // for BOOST_STATIC_CONSTANT + +namespace boost { + + typedef unsigned long static_log2_argument_type; + typedef int static_log2_result_type; + + namespace detail { + + namespace log2_impl { + + // choose_initial_n<> + // + // Choose an initial value of n for the core template. + // If we call MAX the maximum value for static_log2_argument_type + // (for instance, ULONG_MAX) that initial value n is the power of + // two that satisfies the following relation: + // + // n 2n p + // 2 < MAX <= 2 - 1 [ n = 2 , p >= 4 ] + // + // Example: if on your platform unsigned longs have 48 value bits + // then n = 32 is chosen (p=5). + // + // It's easy to prove that, with such a choice, the core algorithm + // works correctly for any width of static_log2_argument_type (not + // only powers of two) and that recursion always terminates with + // x = 1 and n = 0. + + // argument_type must be unsigned and have a width > 16 (this + // is guaranteed e.g. for unsigned long). Under that restriction, + // it can be changed in the future if larger types will be + // standardized, without affecting the rest of the code. + + typedef static_log2_argument_type argument_type; + typedef static_log2_result_type result_type; + + + template + struct choose_initial_n { + + enum { c = (argument_type(1) << n << n) != 0 }; + BOOST_STATIC_CONSTANT(result_type, value = !c*n + choose_initial_n<2*c*n>::value); + + }; + + template <> + struct choose_initial_n<0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + + const result_type minimum_arg_type_width = 32; + const result_type initial_n = choose_initial_n::value; + + template + struct static_log2_impl { + + enum { c = (x >> n) > 0 }; // x >= 2**n ? + BOOST_STATIC_CONSTANT(result_type, value = c*n + (static_log2_impl< (x>>c*n), n/2 >::value) ); + }; + + template <> + struct static_log2_impl<1, 0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + } + } // detail + + + + // -------------------------------------- + // static_log2 + // ---------------------------------------- + + template + struct static_log2 { + + BOOST_STATIC_CONSTANT + (static_log2_result_type, value = detail::log2_impl::static_log2_impl::value); + }; + + template <> + struct static_log2<0> { }; + +} + + + +#endif // include guard