Use bit arithmetic.
For +ve (and 0), msb is 0. For -ve, msb is 1.
max(a, b)
- returns a, when a > b, a-b is +ve, so a * 1 + b * 0
- returns b, when b > a, a-b is -ve, so a * 0 + b * 1
// 0 for +ve, 1 for -ve, 0 for 0. msb(x): return (x >> 31) & 1 lsb(x): return x & 1 // returns 1 if +ve, 0 if -ve, 1 if 0. // bit is 0 or 1 only ispositive(bit): return msb(bit) ^1 //or ~msb(bit) &1
//bug max(a, b): return a * ispositive(a-b) + b * ispositive(b-a)But (a-b) could cause overflow when a, b are of different signs.
(int.max, -1), int.max-(-1) = -ve number
(int.min, 1), int.min-1 = +ve number
When a, b are of different signs, the +ve number is max.
So two functions - different signs and same signs.
// when a, b have same signs return a * ispositive(a-b) + b * ispositive(b-a) // when a, b have different signs return a * ispositive(a) + b * ispositive(b)So for max, multiply functions with their masks and sum.
a b a^b --same-- 0 0 0 1 1 0 --diff-- 0 1 1 1 0 1 //bug max(a, b): return issamesign(a, b) * ( a * ispositive(a-b) + b * ispositive(b-a) ) + isdiffsign(a, b) * ( a * ispositive(a) + b * ispositive(b) ) isdiffsign(a, b): return msb(a) ^ msb(b) issamesign(a, b): return toggle(isdiffsign(a, b)) toggle(bit): return lsb(bit) ^ 1[Hat tip to ctci]
But when a == b (except 0), max(a, b) returns a+b i.e 2a or 2b. So this refactor to fix ispositive(x):
// return 1 for +ve, 0 for -ve and 0. ispositive(x): return (msb(x) ^ 1) * isnotzero(x) isnotzero(x): return msb(x | -x) iszero(x): return toggle(isnotzero(x)) int max(a, b): return issamesign(a, b) * ( a * ispositive(a-b) + b * ispositive(b-a) ) + isdiffsign(a, b) * ( a * ispositive(a) + b * ispositive(b) ) + iszero(a-b) * (a|b)Instead of a mutually exclusive implementation of ispositive(x) for +ve and 0, since isnegative(x) is mutually exclusive (1 only if -ve), it suffices for a mutually exclusive implementation of isgreater(a, b) where a is greater if same signs and b-a is negative OR diff signs and b is negative.
int max(a, b): isgreater(a, b) * a + isgreater(b, a) * b + iszero(a - b) * (a|b) // 1 if a > b, 0 if a <= b bit isgreater(a, b): return issamesign(a, b) * isnegative(b-a) | isdiffsign(a, b) * isnegative(b) bit issamesign(a, b): return toggle(isdiffsign(a, b)) bit isdiffsign(a, b): return msb(a ^ b) // 1 if neg, 0 if >= 0 bit isnegative(x): return msb(x) bit toggle(x): bit msb(x): bit lsb(x):
No comments:
Post a Comment