Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faster inequalities in C

Let's say we have these inequalities:

if (a*a+b*b>0) {
    ...
}

if (a*b+c*d>0) {
    ...
}

Obviously, both of them require 2 multiplications to evaluate.
The thing is, do we really need to calculate 2 full-precision products just to check whether these expressions are positive or not?
Is there any mathematical trickery that allows me to write those if commands without the need to evaluate 2 products?
Will it be faster?
Or perhaps the compiler takes care of making it as fast as possible?
Am I overthinking?

EDIT: Well, that escalated quickly. I just want to point out that I am speaking in general terms. I don't need such a micro-optimization in any project of mine anyway. Also, yes, I could have omitted the first one for being too trivial. Possibly the second one is more interesting.

like image 836
user2464424 Avatar asked Nov 24 '25 15:11

user2464424


2 Answers

Your "am I overthinking" question suggests me that you haven't found this to be an actual bottleneck by really profiling your code. So I'd say yes, you're just trying to do premature optimization.

However, if this really is a major performance-critical part of your application, then the only improvement I can think of right now is the following. Since squares of real numbers can never be negative, then "a squared is greater than zero" is equivalent with "a is not zero". So if comparisons are fast (well, that's relative -- faster than multiplication) on your architecture, then

if (a*a+b*b>0) {
    ...
}

can be written as

if (a || b) {
    ...
}

(provided that no corner cases arise. If the variables are signed integers or floating-point numbers representing real numbers, then this should be fine. If, however, there are some unsigned integer overflow or complex numbers involved, then you will have to perform additional checks, and at that point, it's hard to reason about the relative performance without true profiling.)

I don't have such a "clever" "optimization" for the second case in my mind, but perhaps someone else can come up with something similar -- if and only if it is absolutely necessary. Not otherwise -- code readability is preferred over performance when performance is not critical.

I'm assuming none of these expressions will overflow either because the types don't have a concept of overflow or because the values are in range. When overflow and potential wrap-around enters the picture (e.g. if a and b are unsigned int) different rules apply.

The first statement is obviously equivalent to

if (a != 0 || b != 0)

or

if (a || b)

which trades an extra branch for two multiplications and an addition.

The second statement is a bit more interesting: I'd think it could be reasonable to determine the signs of the operand and only do the actual math when a*b and c*d have opposite signs. In all other cases the condition can be determined without knowing the actual values. Whether the resulting logic is faster than the computations will depend on the types, I'd guess.

like image 33
Dietmar Kühl Avatar answered Nov 26 '25 05:11

Dietmar Kühl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!