

/** Greatest common divisor of two integers.
* gcd(a,b) == gcd(b,a), gcd(a,0) == a.
*/
static int gcd(int a, int b)
{
    /* it is more convenient to have a>b
    * [otherwise the first remainder calculation just swaps them]
    */

    while (b != 0) {
        int c = a % b;
        a = b;
        b = c;
    }

    return a;
}


/** Rotate a memory buffer of specified size by n bytes to the left.
* Right-rotation is achieved by rotating it size-n.
* Element size can be a divisor of gcd(size,n).
*/
void* memrot(void* p, int size, int n)
{
    int rounds;
    char *q, *e;

    if (size == 0) {  /* nothing to do; %size below would fail */
        return p;
    }

    n %= size;  /* adjust n to be 0<=n<size */
    if (n < 0) {  /* consider a possible negative n */
        n += size;
    }

    if (n == 0) {  /* nothing to do; rounds below would be large */
        return p;
    }

    q = (char*)p;  /* starting point for a round */
    e = q + size;  /* end of buffer, to wrap-adjust */
    rounds = gcd(size, n);  /* number of rounds needed to move memory */

    for (; rounds > 0; q++, rounds--) {
        char* r = q;
        char c = *r;  /* the one temporary location needed for moving the whole buffer */
        for (;;) {

            char* s = r + n;  /* next location to be moved */
            if (s >= e) {  /* consider wrap */
                s -= size;
            }

            if (s == q) {
                break;  /* done */
            }

            *r = *s;  /* move */
            r = s;  /* next */
        }
        *r = c;
    }

    return p;
}


