/* * isTmax - returns 1 if x is the maximum, two's complement number, * and 0 otherwise * Legal ops: ! ~ & ^ | + * Max ops: 10 * Rating: 1 */ intisTmax(int x) { /* * 0111...1 + 1 = 1000...0 * ~ 1000...0 = 0111...1 * * But there is another circumstance ! * 1111...1 + 1 = 0000...0 * ~ 0000...0 = 1111...1 * And we need to prove that there are only these two numbers that satisfy * ~(x + 1) == x */ return !(~(x+1)^x) & !!(~x); }
/* * allOddBits - return 1 if all odd-numbered bits in word set to 1 * where bits are numbered from 0 (least significant) to 31 (most significant) * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1 * Legal ops: ! ~ & ^ | + << >> * Max ops: 12 * Rating: 2 */ intallOddBits(int x) { /* * Return 1 if all odd-numbered bits in word are 1s. * We can use 0xAA(170) to construct 0xAAAAAAAA. * * Notice that we only demand the odd-numbered bits are 1s, for * example, allOddBits(0xFFFFFFFF) should return 1. * They satisfy that x & mask == mask. On the other hand, if * x satisfy x & mask == mask, x's all odd-numbered bits are 1s. */ int mask = 0xAA; // 10101010 mask = (mask << 8) + mask; // 0xAAAA mask = (mask << 16) + mask; // 0xAAAAAAAA return !((x & mask) ^ mask); }
/* * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9') * Example: isAsciiDigit(0x35) = 1. * isAsciiDigit(0x3a) = 0. * isAsciiDigit(0x05) = 0. * Legal ops: ! ~ & ^ | + << >> * Max ops: 15 * Rating: 3 */ intisAsciiDigit(int x) { /* * x should be 00...0011 0xxx * or * 00...0011 100x */ /* int situation_1 = 0x06; int situation_2 = 0x1c; return !(x>>3 ^ situation_1) | !(x>>1 ^ situation_2); */
/** * Of course you can add the condition that x>>31 == 0 to avoid * overflow. However, the codes below are enough. * This requires a mathematical proof. */ int low = x + (~0x30 + 1); // x - 0x30 >= 0 int up = 0x39 + (~x + 1); // 0x39 - x >= 0 return !(low >> 31) & !(up >> 31); }
conditional
1 2 3 4 5 6 7 8 9 10 11
/* * conditional - same as x ? y : z * Example: conditional(2,4,5) = 4 * Legal ops: ! ~ & ^ | + << >> * Max ops: 16 * Rating: 3 */ intconditional(int x, int y, int z) { int mask = !x + ~1 + 1; // !x-1 is 00...0 if x==0 and 11...1 otherwise. return (mask & y) | (~mask & z); }
isLessOrEqual
比较麻烦的是异号时,做减法可能会溢出,好在这种情况下谁是正的谁大
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* * isLessOrEqual - if x <= y then return 1, else return 0 * Example: isLessOrEqual(4,5) = 1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 24 * Rating: 3 */ intisLessOrEqual(int x, int y) { /** * If x and y have same signs, then we can use y-x to judge. * However, if x>0 and y<0, or x<0, y>0, overflow may happen. * In this situation, we only need to see whether the sign bit of x is 1. */ int neg_and_pos = (x ^ y) >> 31; // 11...1 if xy < 0. int x_msb = (x>>31) & 1; // 00...00 or 00...01 int same_sign_result = y + (~x + 1); // y-x return (neg_and_pos & x_msb) | (!neg_and_pos & !(same_sign_result>>31)); }
logicalNeg
如果x不是0,那么它和它的补(逆元)的符号位是不一样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* * logicalNeg - implement the ! operator, using all of * the legal operators except ! * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1 * Legal ops: ~ & ^ | + << >> * Max ops: 12 * Rating: 4 */ intlogicalNeg(int x) { /** * Notice that if x is not 0, then the MSB of x is 1 * or the MSB of -x is 1 */ int neg_x = ~x + 1; int res = neg_x | x; return (res >> 31) + 1; }
/* * floatScale2 - Return bit-level equivalent of expression 2*f for * floating point argument f. * Both the argument and result are passed as unsigned int's, but * they are to be interpreted as the bit-level representation of * single-precision floating point values. * When argument is NaN, return argument * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ unsignedfloatScale2(unsigned uf) { int msb = uf >> 31; unsigned sp_mask = 0x7f800000; unsigned denormalized_mask = 0x807fffff; if ((uf & sp_mask) == sp_mask) { return uf; // f is NaN, infinity. } elseif ((uf | denormalized_mask) == denormalized_mask) { // f is a denormalized value including +0 and -0. /** * It's interesting that just left shifting 1 and adding the sign bit is enough. * Because if the 22th bit is 1, left shift is equivalent to times 2 although f * is normalized now. The exponent is the same and normalized just add a implict 1. * If the 22th bit is 0, we only need to time the fraction field by left shift. */ uf = (msb << 31) + (uf << 1); } else { // f is a normalized value. uf = uf + 0x00800000; if ((uf & sp_mask) == sp_mask) { // f overflows. uf = (msb << 31) + sp_mask; } } return uf; }
/* * floatPower2 - Return bit-level equivalent of the expression 2.0^x * (2.0 raised to the power x) for any 32-bit integer x. * * The unsigned value that is returned should have the identical bit * representation as the single-precision floating-point number 2.0^x. * If the result is too small to be represented as a denorm, return * 0. If too large, return +INF. * * Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while * Max ops: 30 * Rating: 4 */ unsignedfloatPower2(int x) { unsigned result; if (x < -149) { result = 0; } elseif (x < -126) { // Denormalized value. result = 0x00000001u << (x + 149); } elseif (x > 127) { result = 0x7f800000u; } else { x = x + 127; result = x << 23; } return result; }