// // Copyright (c) 2002 by Stephen C. Dewhurst // Permission to use, copy, modify, distribute and sell this software for any purpose is // hereby granted without fee, provided that the above copyright notice appears in all copies // and that both that copyright notice and this permission notice appear in supporting documentation. // The author or makes no representations about the suitability of this software for any purpose. // It is provided "as is" without express or implied warranty. // // "typeof" operator implementation // // Described in CUJ 20(8, 10, and 12), August, October, and December 2002: "A Bit-Wise Typeof" // #ifndef MULTISHIFT_H #define MULTISHIFT_H #include #define MASK( n ) (((1<<((n)-1))-1)|(1<<((n)-1))) typedef unsigned short Code; const Code NumCodes = 4; const Code CodeLen = std::numeric_limits::digits; const Code CodeMax = MASK(CodeLen); const Code CodeMask = CodeMax; #define BOUND( n ) ((n)&MASK(CodeLen)) template struct ShiftLeft1 { enum { basemask = MASK(n), leftendmask = BOUND(basemask << CodeLen-n), lostbits = BOUND((c & leftendmask) >> CodeLen-n), r1 = BOUND(c << n) }; }; template struct ShiftRight1 { enum { mask = MASK(n), lostbits = BOUND(c & mask), r1 = BOUND(c >> n) }; }; template struct ShiftLeft2 { enum { r1 = ShiftLeft1::r1, r2 = ShiftLeft1::r1 | ShiftLeft1::lostbits, lostbits = ShiftLeft1::lostbits }; }; template struct ShiftRight2 { enum { r2 = ShiftRight1::r1, r1 = ShiftRight1::r1 | ShiftRight1::lostbits<<(CodeLen-n), lostbits = ShiftRight1::lostbits }; }; template struct ShiftLeft3 { enum { r1 = ShiftLeft2::r1, r2 = ShiftLeft2::r2, r3 = ShiftLeft1::r1 | ShiftLeft2::lostbits, lostbits = ShiftLeft1::lostbits }; }; template struct ShiftRight3 { enum { r3 = ShiftRight2::r2, r2 = ShiftRight2::r1, r1 = ShiftRight1::r1 | ShiftRight2::lostbits<<(CodeLen-n), lostbits = ShiftRight1::lostbits }; }; template struct ShiftLeft4 { typedef ShiftLeft3 SL; enum { r1 = SL::r1, r2 = SL::r2, r3 = SL::r3, r4 = ShiftLeft1::r1 | ShiftLeft3::lostbits, lostbits = ShiftLeft1::lostbits }; }; template struct ShiftRight4 { typedef ShiftRight3 SR; enum { r4 = SR::r3, r3 = SR::r2, r2 = SR::r1, r1 = ShiftRight1::r1 | ShiftRight3::lostbits<<(CodeLen-n), lostbits = ShiftRight1::lostbits }; }; template struct ShiftLeftLong1Impl { enum { r1 = 0 }; }; template struct ShiftLeftLong1Impl { enum { r1 = ShiftLeft1::r1 }; }; template struct ShiftLeftLong1 { enum { r1 = ShiftLeftLong1Impl<(n>CodeLen),c,n>::r1 }; }; template struct ShiftRightLong1Impl { enum { r1 = 0 }; }; template struct ShiftRightLong1Impl { enum { r1 = ShiftRight1::r1 }; }; template struct ShiftRightLong1 { enum { r1 = ShiftRightLong1Impl<(n>CodeLen),c,n>::r1 }; }; template struct ShiftLeftLong2Impl { enum { r2 = ShiftLeftLong1::r1 }; }; template struct ShiftLeftLong2Impl { enum { r2 = ShiftLeft2::r2 }; }; template struct ShiftLeftLong2 { enum { r1 = ShiftLeftLong1::r1, r2 = ShiftLeftLong2Impl<(n>CodeLen),c2,c1,n>::r2 }; }; template struct ShiftRightLong2Impl { enum { r2 = ShiftRightLong1::r1 }; }; template struct ShiftRightLong2Impl { enum { r2 = ShiftRight2::r1 }; }; template struct ShiftRightLong2 { enum { r2 = ShiftRightLong1::r1, r1 = ShiftRightLong2Impl<(n>CodeLen),c2,c1,n>::r2 }; }; template struct ShiftLeftLong3Impl { enum { r3 = ShiftLeftLong2::r2 }; }; template struct ShiftLeftLong3Impl { enum { r3 = ShiftLeft3::r3 }; }; template struct ShiftLeftLong3 { enum { r1 = ShiftLeftLong2::r1, r2 = ShiftLeftLong2::r2, r3 = ShiftLeftLong3Impl<(n>CodeLen),c3,c2,c1,n>::r3 }; }; template struct ShiftRightLong3Impl { enum { r1 = ShiftRightLong2::r1 }; }; template struct ShiftRightLong3Impl { enum { r1 = ShiftRight3::r1 }; }; template struct ShiftRightLong3 { enum { r3 = ShiftRightLong2::r2, r2 = ShiftRightLong2::r1, r1 = ShiftRightLong3Impl<(n>CodeLen),c3,c2,c1,n>::r1 }; }; template struct ShiftLeftLong4Impl { enum { r4 = ShiftLeftLong3::r3 }; }; template struct ShiftLeftLong4Impl { enum { r4 = ShiftLeft4::r4 }; }; template struct ShiftLeftLong4 { typedef ShiftLeftLong3 SL; enum { r1 = SL::r1, r2 = SL::r2, r3 = SL::r3, r4 = ShiftLeftLong4Impl<(n>CodeLen),c4,c3,c2,c1,n>::r4 }; }; template struct ShiftRightLong4Impl { enum { r1 = ShiftRightLong3::r1 }; }; template struct ShiftRightLong4Impl { enum { r1 = ShiftRight4::r1 }; }; template struct ShiftRightLong4 { typedef ShiftRightLong3 SR; enum { r4 = SR::r3, r3 = SR::r2, r2 = SR::r1, r1 = ShiftRightLong4Impl<(n>CodeLen),c4,c3,c2,c1,n>::r1 }; }; template struct ShiftLeft { typedef ShiftLeftLong4 SL; enum { code1 = SL::r1, code2 = SL::r2, code3 = SL::r3, code4 = SL::r4, // Provide a means to detect overflow, but don't issue error. // This allows clearing of left bits by left/right shift sequence. overflow = (n>=CodeLen && c4!=0) || (n>=2*CodeLen && c3!=0) || (n>=3*CodeLen && c2!= 0) || (n>=4*CodeLen && c1!=0) }; }; template struct ShiftRight { typedef ShiftRightLong4 SR; enum { code1 = SR::r1, code2 = SR::r2, code3 = SR::r3, code4 = SR::r4 }; }; #endif