#if !defined HAVE_BITROTATE_H__
#define      HAVE_BITROTATE_H__
// This file is part of the FXT library.
// Copyright (C) 2010 Joerg Arndt
// License: GNU General Public License version 3 or later,
// see the file COPYING.txt in the main directory.


#include "fxttypes.h"
#include "bits/bitsperlong.h"
#include "bits/bitasm.h"


static inline ulong bit_rotate_left(ulong x, ulong r)
// Return word rotated r bits to the left
// (i.e. toward the most significant bit)
//.
// GCC optimizes the function to asm 'roll %cl,%ebx'
{
#if defined  BITS_USE_ASM
    return asm_rol(x, r);
#else
//    r &= (BITS_PER_LONG-1);  // modulo wordlength
    return  (x<<r) | (x>>(BITS_PER_LONG-r));
#endif
}
// -------------------------


static inline ulong bit_rotate_right(ulong x, ulong r)
// Return word rotated r bits to the right
// (i.e. toward the least significant bit)
//.
// GCC optimizes the function to asm 'rorl %cl,%ebx'
{
#if defined  BITS_USE_ASM
    return asm_ror(x, r);
#else
//    r &= (BITS_PER_LONG-1);  // modulo wordlength
    return  (x>>r) | (x<<(BITS_PER_LONG-r));
#endif
}
// -------------------------


static inline ulong bit_rotate_sgn(ulong x, long r)
// Positive r --> shift away from element zero
{
    if ( r > 0 )  return  bit_rotate_left(x, (ulong)r);
    else          return  bit_rotate_right(x, (ulong)-r);
}
// -------------------------


static inline ulong bit_rotate_left(ulong x, ulong r, ulong ldn)
// Return ldn-bit word rotated r bits to the left
// (i.e. toward the most significant bit)
// Must have  0 <= r <= ldn
{
    ulong m = ~0UL >> ( BITS_PER_LONG - ldn );
    x &= m;
    x = (x<<r) | (x>>(ldn-r));
    x &= m;
    return  x;
}
// -------------------------


static inline ulong bit_rotate_right(ulong x, ulong r, ulong ldn)
// Return ldn-bit word rotated r bits to the right
// (i.e. toward the least significant bit)
// Must have  0 <= r <= ldn
{
    ulong m = ~0UL >> ( BITS_PER_LONG - ldn );
    x &= m;
    x = (x>>r) | (x<<(ldn-r));
    x &= m;
    return  x;
}
// -------------------------

static inline ulong bit_rotate_sgn(ulong x, long r, ulong ldn)
// Positive r --> shift away from element zero
{
    if ( r > 0 )  return  bit_rotate_left(x, (ulong)r, ldn);
    else          return  bit_rotate_right(x, (ulong)-r, ldn);
}
// -------------------------


#endif  // !defined HAVE_BITROTATE_H__

