Add rotlConstant and rotrConstant
The template functions take the rotate amount as a template parameter, which will allow the constexpr to propagate into the rotate expression. It should avoid some of the compile problems we were seeing under Clang and C++11pull/548/head
parent
4382b1a559
commit
3b80ead695
58
misc.h
58
misc.h
|
|
@ -1338,6 +1338,58 @@ CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr);
|
|||
|
||||
// ************** rotate functions ***************
|
||||
|
||||
//! \brief Performs a left rotate
|
||||
//! \tparam R the number of bit positions to rotate the value
|
||||
//! \tparam T the word type
|
||||
//! \param x the value to rotate
|
||||
//! \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide.
|
||||
//! \details y must be in the range <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||
//! Use rotlMod if the rotate amount y is outside the range.
|
||||
//! \details Use rotlConstant when the rotate amount is constant. The template function was added
|
||||
//! because Clang did not propagate the constant when passed as a function parameter. Clang's
|
||||
//! need for a constexpr meant rotlFixed failed to compile on occassion.
|
||||
//! \note rotlConstant attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <unsigned int R, class T> inline T rotlConstant(T x)
|
||||
{
|
||||
// Portable rotate that reduces to single instruction...
|
||||
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
||||
// http://software.intel.com/en-us/forums/topic/580884
|
||||
// and http://llvm.org/bugs/show_bug.cgi?id=24226
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
static const unsigned int MASK = THIS_SIZE-1;
|
||||
CRYPTOPP_ASSERT(R < THIS_SIZE);
|
||||
return T((x<<R)|(x>>(-R&MASK)));
|
||||
}
|
||||
|
||||
//! \brief Performs a right rotate
|
||||
//! \tparam R the number of bit positions to rotate the value
|
||||
//! \tparam T the word type
|
||||
//! \param x the value to rotate
|
||||
//! \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide.
|
||||
//! \details y must be in the range <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||
//! Use rotrMod if the rotate amount y is outside the range.
|
||||
//! \details Use rotrConstant when the rotate amount is constant. The template function was added
|
||||
//! because Clang did not propagate the constant when passed as a function parameter. Clang's
|
||||
//! need for a constexpr meant rotrFixed failed to compile on occassion.
|
||||
//! \note rotrConstant attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <unsigned int R, class T> inline T rotrConstant(T x)
|
||||
{
|
||||
// Portable rotate that reduces to single instruction...
|
||||
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
|
||||
// http://software.intel.com/en-us/forums/topic/580884
|
||||
// and http://llvm.org/bugs/show_bug.cgi?id=24226
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
static const unsigned int MASK = THIS_SIZE-1;
|
||||
CRYPTOPP_ASSERT(R < THIS_SIZE);
|
||||
return T((x >> R)|(x<<(-R&MASK)));
|
||||
}
|
||||
|
||||
//! \brief Performs a left rotate
|
||||
//! \tparam T the word type
|
||||
//! \param x the value to rotate
|
||||
|
|
@ -1348,6 +1400,7 @@ CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr);
|
|||
//! \note rotlFixed attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotlFixed(T x, unsigned int y)
|
||||
{
|
||||
// Portable rotate that reduces to single instruction...
|
||||
|
|
@ -1370,6 +1423,7 @@ template <class T> inline T rotlFixed(T x, unsigned int y)
|
|||
//! \note rotrFixed attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotrFixed(T x, unsigned int y)
|
||||
{
|
||||
// Portable rotate that reduces to single instruction...
|
||||
|
|
@ -1392,6 +1446,7 @@ template <class T> inline T rotrFixed(T x, unsigned int y)
|
|||
//! \note rotlVariable attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotlVariable(T x, unsigned int y)
|
||||
{
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
|
|
@ -1410,6 +1465,7 @@ template <class T> inline T rotlVariable(T x, unsigned int y)
|
|||
//! \note rotrVariable attempts to enlist a <tt>rotate IMM</tt> instruction because its often faster
|
||||
//! than a <tt>rotate REG</tt>. Immediate rotates can be up to three times faster than their register
|
||||
//! counterparts.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotrVariable(T x, unsigned int y)
|
||||
{
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
|
|
@ -1425,6 +1481,7 @@ template <class T> inline T rotrVariable(T x, unsigned int y)
|
|||
//! \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide.
|
||||
//! \details y is reduced to the range <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||
//! \note rotrVariable will use either <tt>rotate IMM</tt> or <tt>rotate REG</tt>.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotlMod(T x, unsigned int y)
|
||||
{
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
|
|
@ -1439,6 +1496,7 @@ template <class T> inline T rotlMod(T x, unsigned int y)
|
|||
//! \details This is a portable C/C++ implementation. The value x to be rotated can be 8 to 64-bits wide.
|
||||
//! \details y is reduced to the range <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
|
||||
//! \note rotrVariable will use either <tt>rotate IMM</tt> or <tt>rotate REG</tt>.
|
||||
//! \sa rotlConstant, rotrConstant, rotlFixed, rotrFixed, rotlVariable, rotrVariable
|
||||
template <class T> inline T rotrMod(T x, unsigned int y)
|
||||
{
|
||||
static const unsigned int THIS_SIZE = sizeof(T)*8;
|
||||
|
|
|
|||
Loading…
Reference in New Issue