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++11
pull/548/head
Jeffrey Walton 2017-11-24 17:37:55 -05:00
parent 4382b1a559
commit 3b80ead695
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
1 changed files with 58 additions and 0 deletions

58
misc.h
View File

@ -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;