# Problem with rotation math

First the relevant code:

[code]

#define ZIC signed char
#define ZUC unsigned char
#define ZIS signed short
#define ZUS unsigned short
#define ZI signed int
#define ZU unsigned int
#define ZIL signed long
#define ZUL unsigned long

// ...

typedef ZIC zic_t;
typedef ZUC zuc_t;
typedef ZIS zis_t;
typedef ZUS zus_t;
typedef ZI zi_t;
typedef ZU zu_t;
typedef ZIL zil_t;
typedef ZUL zul_t;

// ...

typedef struct    zUV {
zus_t size;
zul_t bits;
zul_t zero;
char const *endian;
zuc_t *buff;
} zuv_t;

// ...

typedef struct _ZBIT {
zul_t num;
zuc_t rem;
zuc_t bit;
zus_t pos;
} _zbit_t;

_zbit_t _CalcZbit( zul_t num ) {
_zbit_t n = {0};
n.num = num;
n.rem = num % CHAR_BIT;
n.bit = 1 << n.rem;
n.pos = (num / CHAR_BIT) + (n.rem == 0);
return n;
}

zuv_t* __zuvRol( zuv_t *num, zul_t bits ) {
if ( !bits ) return num;
if ( !_zuvRlNum( num ) ) return NULL;
_zbit_t nth = _CalcZbit(num->zero + num->bits), i = nth,
pos = _CalcZbit(num->zero + bits),
beg = _CalcZbit(num->zero);
zuc_t *tmp = malloc( num->size );
if ( !tmp ) return NULL;
memcpy( tmp, num->buff, num->size );
memset( num->buff, 0, num->size );
while ( i.pos > beg.pos || i.bit >= beg.bit ) {
if ( !i.bit ) {
--i.pos;
i.bit = SCHAR_MIN;
}
if ( pos.pos == beg.pos && pos.bit < beg.bit ) {
pos = nth;
} else if ( !pos.bit ) {
--pos.pos;
pos.bit = SCHAR_MIN;
}
else if ( tmp[pos.pos] & pos.bit )
num->buff[i.pos] |= i.bit;
i.bit >>= 1;
pos.bit >>= 1;
}
free( tmp );
return num;
}

typedef struct _ZBIT {
zul_t num;
zuc_t rem;
zuc_t bit;
zus_t pos;
} _zbit_t;

_zbit_t _CalcZbit( zul_t num ) {
_zbit_t n = {0};
n.num = num;
n.rem = num % CHAR_BIT;
n.bit = 1 << n.rem;
n.pos = (num / CHAR_BIT) + (n.rem == 0);
return n;
}

zuv_t* __zuvRol( zuv_t *num, zul_t bits ) {
if ( !bits ) return num;
if ( !_zuvRlNum( num ) ) return NULL;
_zbit_t nth = _CalcZbit(num->zero + num->bits), i = nth,
pos = _CalcZbit(num->zero + bits),
beg = _CalcZbit(num->zero);
zuc_t *tmp = malloc( num->size );
if ( !tmp ) return NULL;
memcpy( tmp, num->buff, num->size );
memset( num->buff, 0, num->size );
while ( i.pos > beg.pos || i.bit >= beg.bit ) {
if ( !i.bit ) {
--i.pos;
i.bit = SCHAR_MIN;
}
if ( pos.pos == beg.pos && pos.bit < beg.bit ) {
pos = nth;
} else if ( !pos.bit ) {
--pos.pos;
pos.bit = SCHAR_MIN;
}
else if ( tmp[pos.pos] & pos.bit )
num->buff[i.pos] |= i.bit;
i.bit >>= 1;
pos.bit >>= 1;
}
free( tmp );
return num;
}

[/code]

Then my results (val* are hard integers while num* are soft integers from above math):

[code]

1310 val1 = 00000111010110111100110100010101u, 123456789u

1311 val2 = 00000000000000000000000000000111u, 7u

1312 (val1 <>= val2) = 10101101111001101000101010000011u

1313 (num1 <>= num2) = 00000000000000000000000000000000u

1320 val1 = 00000111010110111100110100010101u, 123456789u

1321 val3 = 00000000000000000000000000001101u, 13u

1322 (val1 <>= val3) = 01111001101000101010000011101011u

1323 (num1 <>= num3) = 00000000000111010110110100000000u

1330 val2 = 00000000000000000000000000000111u, 7u

1331 val3 = 00000000000000000000000000001101u, 13u

1332 (val2 <>= val3) = 00000000000000001110000000000000u

1333 (num2 <>= num3) = 00000000000000000000000000000000u

[/code]

Any ideas on how to fix this would be appreciated

answered Jan 29, 2018 by (340 points)

Got it!

[code]

zuv_t* __zuvRol( zuv_t *num, zul_t bits ) {
if ( !bits ) return num;
if ( !_zuvRlNum( num ) ) return NULL;
_zbit_t end = _CalcZbit((num->zero + num->bits)-1),
beg = _CalcZbit(num->zero), d = beg,
s = _CalcZbit((end.num+1) - bits);
zuc_t *tmp = calloc( 1, num->size );
if ( !tmp ) return NULL;
while ( d.pos < end.pos || ( d.bit && d.bit <= end.bit ) ) {
if ( !d.bit ) {
++d.pos;
d.bit = 1;
}
if ( ( s.pos == end.pos ) && ( s.bit > end.bit || !s.bit ) )
s = beg;
else if ( !s.bit ) {
++s.pos;
s.bit = 1;
}
if ( num->buff[s.pos] & s.bit )
tmp[d.pos] |= d.bit;
d.bit <<= 1;
s.bit <<= 1;
}
memcpy( num->buff, tmp, num->size );
free( tmp );
return num;
}

[/code]
answered Jan 27, 2018 by (340 points)
Got my results closer to those expected, the first result is still coming out incorrect but the other 2 are now coming out correct, I'm obviously missing somthing so I will post the updated function here:

<code>

zuv_t* __zuvRol( zuv_t *num, zul_t bits ) {
if ( !bits ) return num;
if ( !_zuvRlNum( num ) ) return NULL;
_zbit_t nth = _CalcZbit((num->zero + num->bits)-1), i = nth,
pos = _CalcZbit(nth.num - bits),
beg = _CalcZbit(num->zero);
zuc_t *tmp = calloc( 1, num->size );
if ( !tmp ) return NULL;
while ( i.pos > beg.pos || i.bit >= beg.bit ) {
if ( !i.bit ) {
--i.pos;
i.bit = SCHAR_MIN;
}
if ( ( pos.pos == beg.pos ) && ( pos.bit < beg.bit ) )
pos = nth;
else if ( !pos.bit ) {
--pos.pos;
pos.bit = SCHAR_MIN;
}
if ( num->buff[pos.pos] & pos.bit )
tmp[i.pos] |= i.bit;
i.bit >>= 1;
pos.bit >>= 1;
}
memcpy( num->buff, tmp, num->size );
free( tmp );
return num;
}

</code>