Is this C code:
/* LERP(a,b,c) = linear interpolation macro, is 'a' when c == 0.0 and 'b' when c == 1.0 */
#define LERP(a,b,c) (((b) - (a)) * (c) + (a))
http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_T.html
Equals this C# code?
private static double LERP(double a, double b, double c) { return (((b) - (a)) * (c) + (a)); }
?
Technically, no they are not equal. The C macro can take any type:
int
,float
,byte
, etc.Your C# version can only handle double, without explicit casts. You'd need to add overloads as needed for other types.
No. The C variant comes with all the deficiencies of
#define
-macros. Reminder:Potential Waste of Performance
Imagine a pure function call in an invokation of the
#define
-macro:That line expands to:
Now you have potentially doubled the runtime for two invokations of your faculty function that was perviously just one.
This surely gets worse if you nest your lerping, as is for instance common in some graphics programming situations:
Expanding to:
Expanding to (formatting tweaked for readability):
Whereas the clean version does computationally not more than:
or
So in a two dimensional setup
fac()
fac()
It gets exponentially worse with every dimension you'd add. Even five-dimensional Perlin Noise is sometimes seen (3d volume + time + continous seed), for which some expressions are evaluated freaking 31 times, instead of just once!:
You can also see the preprocessed code by invoking
cpp
(note the single appearance ofprobe()
before).Again, full source is here.
Potential Undefined Behaviour
You can put evil stuff into it:
which expands to
which is undefined behaviour in C¹ (and in C++, btw).
a
might be increased twice, or it might be increased once, or an exception might be thrown that saysDebug-Runtime-Exception: Invoked Undefined Behaviour
, or the compiler is smart enough to reject that code, or whatever.The undefined behaviour comes from the fact that the C99-standard (and C++2003, too) does not allow a value to be modified multiple times before reaching the next Sequence Point.
ID pollution and infection
(This is more relevant if you'd convert the C# into the macro variant.)
The
#define
-macro-name pollutes and infects the whole unit of translation from the point of definition to either the end-of-unit or its undefinition.More ...
¹: C99 (ISO/IEC 9899:TC2), J.2, "Undefined Behaviour":
Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored (6.5).
It's basically equivalent, yes. You can also get rid of some parentheses:
To get what you had in C you may use:
But I agree with amit. This might be the same you had in C (but solely for double not for other types) still it might not be what you really want.. (with delegate you could set 'i++' as a, not only result of i++)
no. consider the following:
LERP(x++,1,2);
The c code might also have a side effect of increasing x twice [it is undefined as mentioned by @phresnel], while the c# code is perfectly defined, and will increase x only once.
the result also might be different, since the first
a
and the second one [in the macro] might have a different value, since it might have increased in the first one.Yes, but you can write it more simple: