Problem with rotation math

0 votes
asked Jan 26, 2018 by Lee Shallis (340 points)
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

2 Answers

0 votes
answered Jan 29, 2018 by Lee Shallis (340 points)
 
Best answer
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]
0 votes
answered Jan 27, 2018 by Lee Shallis (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>
Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...