octave-maintainers
[Top][All Lists]

## Re: bitshift of int8, int16, etc?

 From: Daniel J Sebald Subject: Re: bitshift of int8, int16, etc? Date: Sun, 24 Jun 2007 21:24:15 -0500 User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020

```David Bateman wrote:
```
```Matlab doesn't define the bitshifts of int8, etc (at least not in
2007a), though Octave does. However, it appears that there is an error
in Octave's shift operations of signed integer types. For example consider

bitshift(int8(127),1)

Logically, this should give "-2", but rather gives "0".. Thinking about
the fix for this I asked myself, whether we should use logical or
arithmetic shifts. That is should we keep the sign bit of the integer
types. Looking at

bitshift (-10, -1)

and the fact that it gives "-5" in both Octave and matlab. Therefore it
appears that we should be doing arithmetic shifts for the signed integer
types for consistency. In fact looking at

bitshift (int8(-1),-1)

and the fact it gives "-1" in Octave means we do respect the arithmetic
shifts. Now the reason for the issue with

bitshift (int8(127), 1)

is that std::numeric_limits<int8_t>::max() is "127" and in
oct-inttypes.h the left shift operator is defined as

template <class T2>
octave_int<T>& operator <<= (const T2& x)
{
ival = ((ival << x) > std::numeric_limits<T>::max ()) ? 0 : (ival << x);
return *this;
}

Shouldn't this just be defined as

template <class T2>
octave_int<T>& operator <<= (const T2& x)
{
ival = ival << x;
return *this;
}
```
```
Does the proposed version limit the class value to the maximum inherently?  E.g., say
it is int8 type and bit shift is +1 and current value is 127; Is ival = 127 <<
1 equal to 254 but then treated as 126 in all uses of the int8 value?

The thing I wonder is that if as you describe this, it is arithmetic shift and
negative numbers are shifted similarly to postive numbers, should there also be
a test on the value being no less than the minimum allowed value of the class?

template <class T2>
octave_int<T>& operator <<= (const T2& x)
{
ival = ival << x;
if (ival > std::numeric_limits<T>::max ())
ival &= std::numeric_limits<T>::max ();
else if (ival < std::numeric_limits<T>::min ())
ival |= std::numeric_limits<T>::min ();
return *this;
}

For example, say int8, the value is maximum and shift is +1:

<24zeros>01111111 shifted +1 becomes <24zeros>11111110 but that is greater than max in
ival's 32 or 64 bit world so the value is and'd with <24zeros>01111111 which results in
<24zeros>01111110.

Or another example, say int 8, the value is minimum + 1 and shift is +1:

<24ones>10000001 shifted +1 becomes <24ones>00000010 but that is less than min in ival's 32
or 64 bit world so the value is or'd with <24ones>10000000 which results in
<24ones>10000010.

(If the shift is negative, then there is nothing to worry about, right?)  It
all depends how behavior is defined.  I'm not 100% sure what it should be
defined as.

Dan

```