add C++1y bit operations (partial)

This commit is contained in:
bolero-MURAKAMI 2014-03-31 14:58:24 +09:00
parent 1bb9336d34
commit 56c9d52436
17 changed files with 435 additions and 67 deletions

50
sprout/bit/clrsb.hpp Normal file
View file

@ -0,0 +1,50 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_CLRSB_HPP
#define SPROUT_BIT_CLRSB_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/clz.hpp>
namespace sprout {
namespace detail {
# if SPROUT_USE_BUILTIN_BIT_OPERATION
inline SPROUT_CONSTEXPR int
clrsb(unsigned x) {
return __builtin_clrsb(x);
}
inline SPROUT_CONSTEXPR int
clrsb(unsigned long x) {
return __builtin_clrsbl(x);
}
inline SPROUT_CONSTEXPR int
clrsb(unsigned long long x) {
return __builtin_clrsbll(x);
}
# endif
template<typename Integral>
inline SPROUT_CONSTEXPR int
clrsb(Integral x) {
return sprout::clz(~x);
}
} // namespace detail
//
// clrsb
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
int
>::type
clrsb(Integral x) {
return sprout::detail::clrsb(x);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CLRSB_HPP

View file

@ -16,52 +16,59 @@ namespace sprout {
namespace detail {
# if SPROUT_USE_BUILTIN_BIT_OPERATION
inline SPROUT_CONSTEXPR int
clz(unsigned n) {
return __builtin_clz(n);
clz_non0(unsigned x) {
return __builtin_clz(x);
}
inline SPROUT_CONSTEXPR int
clz(unsigned long n) {
return __builtin_clzl(n);
clz_non0(unsigned long x) {
return __builtin_clzl(x);
}
inline SPROUT_CONSTEXPR int
clz(unsigned long long n) {
return __builtin_clzll(n);
clz_non0(unsigned long long x) {
return __builtin_clzll(x);
}
# endif
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR int
clz_impl(T n, T m = T(1) << (CHAR_BIT * sizeof(T) - 1)) {
return m == 0 || n & m ? 0
: 1 + sprout::detail::clz_impl(n, static_cast<T>(m >> 1))
clz_non0_impl(Integral x, Integral m = Integral(1) << (CHAR_BIT * sizeof(Integral) - 1)) {
return m == 0 || x & m ? 0
: 1 + sprout::detail::clz_non0_impl(x, static_cast<Integral>(m >> 1))
;
}
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_unsigned<T>::value,
std::is_unsigned<Integral>::value,
int
>::type
clz(T n) {
return sprout::detail::clz_impl(static_cast<T>(n));
clz_non0(Integral x) {
return sprout::detail::clz_non0_impl(static_cast<Integral>(x));
}
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_signed<T>::value,
std::is_signed<Integral>::value,
int
>::type
clz(T n) {
return sprout::detail::clz(static_cast<typename std::make_unsigned<T>::type>(n));
clz_non0(Integral x) {
return sprout::detail::clz_non0(static_cast<typename std::make_unsigned<Integral>::type>(x));
}
template<typename Integral>
inline SPROUT_CONSTEXPR int
clz(Integral x) {
return x == 0 ? static_cast<int>(sizeof(x) * CHAR_BIT)
: sprout::detail::clz_non0(x)
;
}
} // namespace detail
//
// clz
//
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<T>::value,
std::is_integral<Integral>::value,
int
>::type
clz(T n) {
return sprout::detail::clz(n);
clz(Integral x) {
return sprout::detail::clz(x);
}
} // namespace sprout

29
sprout/bit/cntl0.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_CNTL0_HPP
#define SPROUT_BIT_CNTL0_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/clz.hpp>
namespace sprout {
//
// cntl0
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
int
>::type
cntl0(Integral x) SPROUT_NOEXCEPT {
return sprout::clz(x);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CNTL0_HPP

29
sprout/bit/cntl1.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_CNTL1_HPP
#define SPROUT_BIT_CNTL1_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/clrsb.hpp>
namespace sprout {
//
// cntl1
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
int
>::type
cntl1(Integral x) SPROUT_NOEXCEPT {
return sprout::clrsb(x);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CNTL0_HPP

29
sprout/bit/cntt0.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_CNTT0_HPP
#define SPROUT_BIT_CNTT0_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/ctz.hpp>
namespace sprout {
//
// cntt0
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
int
>::type
cntt0(Integral x) SPROUT_NOEXCEPT {
return sprout::ctz(x);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CNTT0_HPP

29
sprout/bit/cntt1.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_CNTT1_HPP
#define SPROUT_BIT_CNTT1_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/ctz.hpp>
namespace sprout {
//
// cntt1
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
int
>::type
cntt1(Integral x) SPROUT_NOEXCEPT {
return sprout::ctz(~x);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CNTT1_HPP

View file

@ -8,6 +8,7 @@
#ifndef SPROUT_BIT_CTZ_HPP
#define SPROUT_BIT_CTZ_HPP
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
@ -15,47 +16,54 @@ namespace sprout {
namespace detail {
# if SPROUT_USE_BUILTIN_BIT_OPERATION
inline SPROUT_CONSTEXPR int
ctz(unsigned n) {
return __builtin_ctz(n);
ctz_non0(unsigned x) {
return __builtin_ctz(x);
}
inline SPROUT_CONSTEXPR int
ctz(unsigned long n) {
return __builtin_ctzl(n);
ctz_non0(unsigned long x) {
return __builtin_ctzl(x);
}
inline SPROUT_CONSTEXPR int
ctz(unsigned long long n) {
return __builtin_ctzll(n);
ctz_non0(unsigned long long x) {
return __builtin_ctzll(x);
}
# endif
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_unsigned<T>::value,
std::is_unsigned<Integral>::value,
int
>::type
ctz(T n) {
return n & 1 ? 0
: 1 + sprout::detail::ctz(static_cast<T>(n >> 1))
ctz_non0(Integral x) {
return x & 1 ? 0
: 1 + sprout::detail::ctz_non0(static_cast<Integral>(x >> 1))
;
}
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_signed<T>::value,
std::is_signed<Integral>::value,
int
>::type
ctz(T n) {
return sprout::detail::ctz(static_cast<typename std::make_unsigned<T>::type>(n));
ctz_non0(Integral x) {
return sprout::detail::ctz_non0(static_cast<typename std::make_unsigned<Integral>::type>(x));
}
template<typename Integral>
inline SPROUT_CONSTEXPR int
ctz(Integral x) {
return x == 0 ? static_cast<int>(sizeof(x) * CHAR_BIT)
: sprout::detail::ctz_non0(x)
;
}
} // namespace detail
//
// ctz
//
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<T>::value,
std::is_integral<Integral>::value,
int
>::type
ctz(T n) {
return sprout::detail::ctz(n);
ctz(Integral x) {
return sprout::detail::ctz(x);
}
} // namespace sprout

View file

@ -9,9 +9,20 @@
#define SPROUT_BIT_OPERATION_HPP
#include <sprout/config.hpp>
#include <sprout/bit/shll.hpp>
#include <sprout/bit/shlr.hpp>
#include <sprout/bit/shal.hpp>
#include <sprout/bit/shar.hpp>
#include <sprout/bit/rotl.hpp>
#include <sprout/bit/rotr.hpp>
#include <sprout/bit/cntl0.hpp>
#include <sprout/bit/cntt0.hpp>
#include <sprout/bit/cntl1.hpp>
#include <sprout/bit/cntt1.hpp>
#include <sprout/bit/popcount.hpp>
#include <sprout/bit/clz.hpp>
#include <sprout/bit/ctz.hpp>
#include <sprout/bit/clrsb.hpp>
#include <sprout/bit/rotate.hpp>
#include <sprout/bit/reverse.hpp>
#include <sprout/bit/length.hpp>

View file

@ -8,34 +8,34 @@
#ifndef SPROUT_BIT_ROTATE_HPP
#define SPROUT_BIT_ROTATE_HPP
#include <cstddef>
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/rotl.hpp>
#include <sprout/bit/rotr.hpp>
namespace sprout {
//
// left_rotate
//
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<T>::value,
T
std::is_integral<Integral>::value,
Integral
>::type
left_rotate(T x, std::size_t n) {
return (x << n) ^ (x >> (sizeof(T) * CHAR_BIT - n));
left_rotate(Integral x, int s) {
return sprout::rotl(x, s);
}
//
// right_rotate
//
template<typename T>
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<T>::value,
T
std::is_integral<Integral>::value,
Integral
>::type
right_rotate(T x, std::size_t n) {
return (x >> n) ^ (x << (sizeof(T) * CHAR_BIT - n));
right_rotate(Integral x, int s) {
return sprout::rotr(x, s);
}
} // namespace sprout

30
sprout/bit/rotl.hpp Normal file
View file

@ -0,0 +1,30 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_ROTL_HPP
#define SPROUT_BIT_ROTL_HPP
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/shlr.hpp>
namespace sprout {
//
// rotl
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
rotl(Integral x, int s) SPROUT_NOEXCEPT {
return (x << s) | sprout::shlr(x, sizeof(x) * CHAR_BIT - s);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_ROTL_HPP

30
sprout/bit/rotr.hpp Normal file
View file

@ -0,0 +1,30 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_ROTR_HPP
#define SPROUT_BIT_ROTR_HPP
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/shlr.hpp>
namespace sprout {
//
// rotr
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
rotr(Integral x, int s) SPROUT_NOEXCEPT {
return sprout::shlr(x, s) | (x << (sizeof(x) * CHAR_BIT - s));
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_ROTR_HPP

29
sprout/bit/shal.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_SHAL_HPP
#define SPROUT_BIT_SHAL_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/bit/shll.hpp>
namespace sprout {
//
// shal
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
shal(Integral x, int s) SPROUT_NOEXCEPT {
return sprout::shll(x, s);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_SHAL_HPP

29
sprout/bit/shar.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_SHAR_HPP
#define SPROUT_BIT_SHAR_HPP
#include <type_traits>
#include <sprout/config.hpp>
namespace sprout {
//
// shar
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
shar(Integral x, int s) SPROUT_NOEXCEPT {
typedef typename std::make_signed<Integral>::type type;
return static_cast<Integral>(static_cast<type>(x) >> s);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_SHAR_HPP

29
sprout/bit/shll.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_SHLL_HPP
#define SPROUT_BIT_SHLL_HPP
#include <type_traits>
#include <sprout/config.hpp>
namespace sprout {
//
// shll
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
shll(Integral x, int s) SPROUT_NOEXCEPT {
typedef typename std::make_unsigned<Integral>::type type;
return static_cast<Integral>(static_cast<type>(x) << s);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_SHLL_HPP

29
sprout/bit/shlr.hpp Normal file
View file

@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2011-2014 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_BIT_SHLR_HPP
#define SPROUT_BIT_SHLR_HPP
#include <type_traits>
#include <sprout/config.hpp>
namespace sprout {
//
// shlr
//
template<typename Integral>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_integral<Integral>::value,
Integral
>::type
shlr(Integral x, int s) SPROUT_NOEXCEPT {
typedef typename std::make_unsigned<Integral>::type type;
return static_cast<Integral>(static_cast<type>(x) >> s);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_SHLR_HPP

View file

@ -18,7 +18,7 @@
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/bytes_iterator.hpp>
#include <sprout/operation/fixed/set.hpp>
#include <sprout/bit/rotate.hpp>
#include <sprout/bit/rotl.hpp>
namespace sprout {
static_assert(CHAR_BIT == 8, "CHAR_BIT == 8");
@ -45,28 +45,28 @@ namespace sprout {
public:
SPROUT_CONSTEXPR std::uint32_t
operator()(std::uint32_t a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t t, std::uint32_t s) const {
return b + sprout::left_rotate(a + sprout::md5_detail::func_f(b, c, d) + x + t, s);
return b + sprout::rotl(a + sprout::md5_detail::func_f(b, c, d) + x + t, s);
}
};
struct round2_op {
public:
inline SPROUT_CONSTEXPR std::uint32_t
operator()(std::uint32_t a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t t, std::uint32_t s) const {
return b + sprout::left_rotate(a + sprout::md5_detail::func_g(b, c, d) + x + t, s);
return b + sprout::rotl(a + sprout::md5_detail::func_g(b, c, d) + x + t, s);
}
};
struct round3_op {
public:
inline SPROUT_CONSTEXPR std::uint32_t
operator()(std::uint32_t a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t t, std::uint32_t s) const {
return b + sprout::left_rotate(a + sprout::md5_detail::func_h(b, c, d) + x + t, s);
return b + sprout::rotl(a + sprout::md5_detail::func_h(b, c, d) + x + t, s);
}
};
struct round4_op {
public:
inline SPROUT_CONSTEXPR std::uint32_t
operator()(std::uint32_t a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, std::uint32_t t, std::uint32_t s) const {
return b + sprout::left_rotate(a + sprout::md5_detail::func_i(b, c, d) + x + t, s);
return b + sprout::rotl(a + sprout::md5_detail::func_i(b, c, d) + x + t, s);
}
};

View file

@ -23,7 +23,7 @@
#include <sprout/algorithm/fixed/fill.hpp>
#include <sprout/range/algorithm/fixed/copy.hpp>
#include <sprout/operation/fixed/set.hpp>
#include <sprout/bit/rotate.hpp>
#include <sprout/bit/rotl.hpp>
#ifdef SPROUT_WORKAROUND_NOT_TERMINATE_RECURSIVE_CONSTEXPR_FUNCTION_TEMPLATE
# include <sprout/workaround/recursive_function_template.hpp>
#endif
@ -61,7 +61,7 @@ namespace sprout {
| (block_[i * 4 + 1] << 16)
| (block_[i * 4 + 2] << 8)
| (block_[i * 4 + 3])
: sprout::left_rotate(
: sprout::rotl(
calc_w(i - 3) ^ calc_w(i - 8) ^ calc_w(i - 14) ^ calc_w(i - 16),
1
)
@ -98,9 +98,9 @@ namespace sprout {
) const
{
return process_block_1<D + 1>(
sprout::left_rotate(a, 5) + f + e + k + calc_w(i),
sprout::rotl(a, 5) + f + e + k + calc_w(i),
a,
sprout::left_rotate(b, 30),
sprout::rotl(b, 30),
c,
d,
i + 1
@ -227,9 +227,9 @@ namespace sprout {
) const
{
return process_block_1(
sprout::left_rotate(a, 5) + f + e + k + calc_w(i),
sprout::rotl(a, 5) + f + e + k + calc_w(i),
a,
sprout::left_rotate(b, 30),
sprout::rotl(b, 30),
c,
d,
i + 1
@ -388,7 +388,7 @@ namespace sprout {
w[i] |= (block_[i * 4 + 3]);
}
for (std::size_t i = 16; i < 80; ++i) {
w[i] = sprout::left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
w[i] = sprout::rotl((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
}
std::uint32_t a = h_[0];
std::uint32_t b = h_[1];
@ -411,10 +411,10 @@ namespace sprout {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
unsigned temp = sprout::left_rotate(a, 5) + f + e + k + w[i];
unsigned temp = sprout::rotl(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = sprout::left_rotate(b, 30);
c = sprout::rotl(b, 30);
b = a;
a = temp;
}