summaryrefslogtreecommitdiff log msg author committer range
path: root/generic/lib/integer/rotate.inc
blob: e83dd51a8328fc8f5b7ef4baef947330b6d75ab7 (plain)
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ``` ``````/** * Not necessarily optimal... but it produces correct results (at least for int) * If we're lucky, LLVM will recognize the pattern and produce rotate * instructions: * http://llvm.1065342.n5.nabble.com/rotate-td47679.html * * Eventually, someone should feel free to implement an llvm-specific version */ _CLC_OVERLOAD _CLC_DEF GENTYPE rotate(GENTYPE x, GENTYPE n){ //Try to avoid extra work if someone's spinning the value through multiple //full rotations n = n % (GENTYPE)GENSIZE; //Determine if we're doing a right or left shift on each component //The actual shift algorithm is based on a rotate right //e.g. a rotate of int by 5 bits becomes rotate right by 26 bits // and a rotate of int by -4 bits becomes rotate right by 4 GENTYPE amt = (n > (GENTYPE)0 ? (GENTYPE)GENSIZE - n : (GENTYPE)0 - n ); //Calculate the bits that will wrap GENTYPE mask = ( (GENTYPE)1 << amt ) - (GENTYPE)1; GENTYPE wrapped_bits = x & mask; //Shift the input value right and then AND a mask that eliminates //sign-extension interference //if the rotate amount is 0, just use ~0 for a mask GENTYPE se_mask = !amt ? ~((GENTYPE)0) : ( ( (GENTYPE)1 << ((GENTYPE)GENSIZE - amt) ) - (GENTYPE)1 ); GENTYPE unwrapped_bits = x >> amt; unwrapped_bits &= se_mask; //Finally shift the input right after moving the wrapped bits into position return unwrapped_bits | (wrapped_bits << ( (GENTYPE)GENSIZE - amt ) ); }``````