Perhaps there's an ingenious bitwise operation I'm forgetting, but is there a smarter way of expressing the following?
int r = foo(); // returns an int
r -= r > 0; // same as `if(r > 0) r--;`
I want to combine the lines into one expression.
Perhaps there's an ingenious bitwise operation I'm forgetting, but is there a smarter way of expressing the following?
int r = foo(); // returns an int
r -= r > 0; // same as `if(r > 0) r--;`
I want to combine the lines into one expression.
The most readable way is the smartest way:
if (r > 0)
--r;
It's readable, and it is most likely to produce the fastest code - because lots of developers don't make vain attempts to look smart, and people creating optimising compilers detect common patterns and optimise them.
Personally I would prefer if (r > 0) r--;
for readability, but if you really want to avoid conditionals:
r = r > 0 ? r-1 : r;
which is still a conditional assignment, alternatively either:
r > 0 && r--;
or:
r <= 0 || r--;
This works because, if the left side already determines the result, the right side will not be executed.
By the way, don't expect any performance differences. Most compilers will generate more or less equally performant code from all of these options.
If the test was r >= 0, then one possibility would be to isolate the sign bit, then to subtract (1-signBit).
In C, something like this (but I guess this can be transposed in many languages)
int r = foo();
return r - (int)((~ ((unsigned) r)) >> (sizeof(r)*8-1));
Of course you now depend on internal representation of int and have greatly obfuscated the code...
For r > 0, it's more involved... Maybe something like
unsigned int r = foo();
return (int) (r - ((~(r | (r-1))) >> (sizeof(r)*8-1)));
I did not even tried those snippets, and the answer is for fun, but if you take it seriously, you'll have to provide a great deal of explanations for justifying such hack, including tests, generated code analysis and benchmarks.
If each and every minor operation like this is going thru such a process, it's gonna be a pain to write code, and even more for whoever will have to maintain it (read/understand/extend...). I hope it's not premature optimization, and in this case maybe the right decision would be to write a small piece of assembler.
Well, say, for 32bit integers with 2-complement, something like this might works (untested!)
const int mask = 1 << 31;
int r = foo();
r -= ((r ^ mask) >> 31);
basically, you check if leftmost bit is zero and convert it to 1 if it is, otherwise it will still be zero, then shift it so you have 1 for positive and 0 for negative, and substract