Suppose that I want invert a number, i.e. 5 becomes -5 or -10 becomes 10. Mathematically, I can either multiply it by -1 or subtract it from 0. But what is quickest/most efficient on an 8-bit AVR? Or is the compiler smart enough to optimize either style to the fewest instructions?
// Style #1
int one (const int number)
{
return number * -1;
}
// Style #2
int two (const int number)
{
return 0 - number;
}
Is there any difference if I work on a float instead of an int?
Inverting usually means dividing one by the number, 1/x.
For negating, you can use unary negation:
return -number;
If you are worried about performance, don't create a function for this, that might introduce some overheads (although the compiler's optimiser might find ways to remove those).
Yes, you're right. Mathematical jargon has never been my cup of tea (which is why I provided an example, just to be sure). For some reason, I tend to think of negating in boolean context only, go figure.
Creating a function just for that in real code would be silly indeed, but that line was part of a larger function and I just singled it out to make things shorter. I'm aware of unary -, but is it better emulated by style #1 or style #2 if I just happen to use one or the other?
Afterthought: Curiously enough, when we talk about a display, inverting it means making black white and making white black, doesn't it? Yet, what we are really doing is negating each pixel's value.
I might use that, but I usually include the 0, so it stands out in code… it will be optimised away anyway, but makes the intent clearer. To me anyway !
for simplicity and readability I'd go for
a = -a;
as a signed integer.
For speed, I wonder if the bitwise xor instruction is faster (but much less comprehensible)
eg
int nx = 0xFFFF;
int a = 12;
..
a = a ^ nx; //invert all bits to form 1's complement
a++; //add 1 to form 2's complement
Exactly the same speed, I would guess. Addition, subtraction, bitwise and/or/xor and single-bit shifts are probably all one cycle operations, even for the relatively simple ALU in an AVR chip. Multiplication, division, and, I guess, multiple-bit shifts will be done in software or at least as multiple cycle operations in AVR chips.
So this seems to imply that number * -1 is slower than 0 - number, since multiplication is involved in the first case. Unless the compiler treats multiplication by -1 as a subtraction in disguise and optimizes it away.
You are correct, in theory. AVR chips used in most Arduino don't have hardware supported multiplication I think, and almost certainly not division, and definitely not floating point operations of any sort. Even more sophisticated chips, that can do such things in hardware, can't do then in a single cycle, so multiplying by -1 will always be slower than subtracting from 0 on almost any chip, I suspect. But, in practice, as you suspect, it may be that the compiler can spot and optimise stuff like that and do it in a more efficient way so that it makes no difference.