SpaceDog SpaceDog - 12 days ago 6
Objective-C Question

Is there any advantage in terms of speed by using MIN MAX instead of checking the range by regular code?

I see this code segment on a sample application created by Apple:

- (AVCaptureWhiteBalanceGains)normalizedGains:(AVCaptureWhiteBalanceGains)gains
{
AVCaptureWhiteBalanceGains g = gains;

g.redGain = MAX( 1.0, g.redGain );
g.greenGain = MAX( 1.0, g.greenGain );
g.blueGain = MAX( 1.0, g.blueGain );

g.redGain = MIN( self.videoDevice.maxWhiteBalanceGain, g.redGain );
g.greenGain = MIN( self.videoDevice.maxWhiteBalanceGain, g.greenGain );
g.blueGain = MIN( self.videoDevice.maxWhiteBalanceGain, g.blueGain );

return g;
}


Apple is checking red, green and blue gain values to prevent values from lying outside a valid range.

OK, I know what MIN MAX do, but is that really necessary to write this like they did? This kind of code makes your brain burn for a micro-second because it is hard to understand that at a glance if you never saw that before.

Instead wouldn't easier to write a function to check that? Like:

- (CGFloat) checkValue:(CGFloat)v againstMinimum:(CGFloat)min andMaximum:(CGFloat)max {
if (v < min) return min;
if (v > max) return max;
return v;
}


Or write a static block inside the function, if they did not want the code to grow outside the function.

My question is: is there any gain in speed by using one method or the other?

CRD CRD
Answer

My question is: is there any gain in speed by using one method or the other?

Well MIN and MAX are macros which expand to inline code, while your checkValue:againstMinimum:andMaximum: is a method which will require a method dispatch – so the former is undoubtedly faster, but the benefit is probably insignificant over the whole application.

If you want clarity, and you should, but not pay too much for it you could start with a function:

CGFloat checkValue(CGFloat min, CGFloat v, CGFloat max)
{
   if (v < min) return min;
   if (v > max) return max; 
   return v;
}

and to get the benefit of inlining add NS_INLINE:

NS_INLINE CGFloat checkValue(CGFloat min, CGFloat v, CGFloat max) ...

Both of those have the advantage they are functions – typically better compiler error messages, no strange effects from double-evaluation of arguments, etc. – but if you like macro solutions you can just go with:

#define CLAMP(lower, v, upper) MIN(MAX(lower, v), upper)

Pick which you find clearest, don't concern yourself too much over the speed – unless later analysis shows it to be an issue.

HTH