Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

Problem with rotation math

0 votes
asked Jan 26, 2018 by Lee Shallis (360 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 (360 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 (360 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.
...