#ifndef NJK_NBITOPS_INCL #define NJK_NBITOPS_INCL 1 /* Copyright 2004 Nicholas J. Kain * Released under BSD license. * * Stupid bitshift tricks. Most are portable, some are not. The unportable * routines are listed. * * Some of these tricks come from sources such as: * http://bob.allegronetwork.com/prog/tricks.html */ #ifdef IS_X86_TARGET_MMX #define IS_X86_TARGET #endif /* Absolute Value. */ /* Unportable. This will break if rightshift is not signed. */ /* Assuming a x86 target, it is preferable to use the asm versions. */ #ifdef IS_X86_TARGET_MMX /* Works on all 686. */ static inline int abs(int x) { int tmp; asm ( "movl %0, %1; negl %0; cmpl $0, %1; cmovge %0, %1;" :"=a"(x) :"r"(tmp), "0"(x) : ); return x; } #elif IS_X86_TARGET /* Works on all x86. */ static inline int abs(int x) { asm ( "cdq; xorl %%edx, %0; subl %%edx, %0;" :"=a"(x) :"0"(x) :"%edx"); return x; } #else static inline int abs(int x) { int mask = x >> 31; x = (x ^ mask) - mask; return x; } #endif /* Round to next power of two. */ /* Totally portable. Can be made to work with 64-bit values: merely add * an additional shift-or with value 32 at the end. Note that mapping * includes: 0 -> 1 | -x -> 0 */ static inline int nextpow2(int x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); ++x; return x; } /* Get the most significant bit. */ /* Copy and paste of above, merely adds a rightshift. */ static inline int getmsb(int x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); ++x; x >>= 1; return x; } /* Rounds to next power of two if not a power of two. Note: 0 -> 0 | -x -> 0 */ static inline int rndpow2(int x) { --x; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); ++x; return x; } /* Checks to see if number is a positive power of two. */ static inline int u_ispow2(int x) { if (x & (x - 1)) return 0; else return 1; } /* Checks to see if number is a positive power of two. */ static inline int ispow2(int x) { x = abs(x); return u_ispow2(x); } /* Unportable. We need signed right shifts. */ static inline int fastmax(int a, int b) { a -= b; a &= (~a) >> 31; a += b; return a; } /* Unportable. We need signed right shifts. */ static inline int fastmin(int a, int b) { a -= b; a &= a >> 31; a += b; return a; } /* Clamps x to be within [a, b]. Keep in mind that overflow may occur and * break results if a and b are too far apart. */ #ifdef IS_X86_TARGET static inline int clamprange(int x, int a, int b) { asm ( "subl %0, %1; subl %0, %2; cdq; not %%edx; andl %%edx, %1; subl %2, %1; addl %0, %2; cdq; andl %%edx, %1; addl %2, %1;" :"=a"(x) :"r"(a), "r"(b), "0"(x) :"%edx"); return x; } #else static inline int clamprange(int x, int a, int b) { x -= a; x &= (~x) >> 31; x += a; x -= b; x &= x >> 31; x += b; return x; } #endif #ifdef IS_X86_TARGET static inline int divpow2(int x, int divisor) { int tmp; asm ( "movl %0, %2; slrl $31, %0; addl %2, %0; sarl %1, %0" :"=a"(x) :"r"(divisor), "r"(tmp), "0"(x) : ); return x; } #else static inline int divpow2(int x, int divisor) { int sign = ((unsigned int)x) >> 31; x += sign; x >>= divisor; return x; } #endif static inline int avg2int(int x, int y) { return (a & b) + ((a ^ b) >> 1); } #endif