I see two possible implementations for a MAX macro in C. Which of these would be best?
define MAX(X,Y) ((X) < (Y) ? : (Y) : (X))
define MAX(X,Y) 0.5*(X+Y+ABS(X-Y))
Second one is hard to read, and actually broken. Really bad idea.
Second one always uses doubles. You will get rounding errors. I certainly wouldn't expect getting a result that's not equal to either side.
When applied to integers it returns a double, quite surprising. Floats get promoted to double as well.
If you "fix" it by replacing *0.5 with /2 it'd "work" on those other types, but you'd get unexpected overflows on large integers.
I also recommend functions, and not macros so the arguments don't get evaluated twice.
There are occasionally situations where such tricky versions are appropriate. For example calculating the maximum of two integers in constant time. But they're rare, and certainly should not be used as the default implementation for MAX.
The first version is more general, efficient and easier to understand.
The second version uses a floating-point constant, which makes it specific to doubles.
It may potentially return the wrong answer since floating-point calculations may be rounded off. (due to the inability of a binary value to represent exactly every possible decimal value, 0.1 for example)
There are also more calculations involved.
The multiplication with 0.5 is not enclosed in parenthesis which may lead to unexpected results.
There's also the matter of compiler optimizations but I'm not going into that.
Related
I have a C program which involves some floating-point literal that's defined by a macro. And - it just so happens that in a performance-critical part of the code, I need the ceiling of that floating-point number, as an integer (say, an int). Now, if it were an actual literal, then I would just manually take the ceiling and be done with it. But since it's a macro, I can't do that.
Naturally, ceilf(MY_DOUBLE_LITERAL) works, but - it's expensive. (int)(MY_DOUBLE_LITERAL) + 1 will also work... except if the literal is itself an integer, in which case it will be wrong.
So, is there some way - preprocessor macros are fine - to obtain the ceiling of MY_DOUBLE_LITERAL, or alternatively to determine whether it is an integer or not?
Notes:
I cannot perform the ceil() before the performance-critical part of the code, due to constraints I won't go into. Naturally if one can move computation outside of the performance-critical part or loop, that's always best, and thanks goes to #SpyrosK for mentioning that.
C99 preferred.
You may assume the literal is a double, i.e. a decimal number like 123.4 or an exponential-notation like 1.23e4.
If your literal fits nicely within the int representation range, you will often be able to rely on compiler optimizations. clang and gcc, for example, will go as far as simply optimizing ceilf() away when it's provided a literal, so ceifl(MY_DOUBLE_LITERAL) will result in a literal being used and no time wasted at run-time.
If somehow that doesn't work with your compiler, you could use:
int poor_mans_ceil(double x)
{
return (int) x + ( ((double)(int) x < x) ? 1 : 0);
}
which should be "easier" for a compiler to optimize. You can see this happening on GodBolt.
Having said that - Some compilers in more exotic setting might fail to optimize both ceil() and the function above. Example: NVIDIA's NVCC compiler for CUDA.
A solution could be to statically store the rounded float macro literal in a const variable outside the critical part of the code and use the precomputed int const value in the critical part.
This will work as long as the float returned by the macro is always the same value.
What exactly is the reason behind this peculiar interface of nextafter (and nexttoward) functions? We specify the direction by specifying the value we want to move toward.
At the first sight it feels as if something non-obvious is hidden behind this idea. In my (naive) opinion the first choice for such functions would be something like a pair of single-parameter functions nextafter(a)/nextbefore(a). The next choice would be a two-parameter function nextafter(a, dir) in which the direction dir is specified explicitly (-1 and +1, some standard enum, etc.).
But instead we have to specify a value we want to move toward. Hence a number of questions
(A vague one). There might be some clever idea or idiomatic pattern that is so valuable that it influenced this choice of interface in these standard functions. Is there?
What if decide to just blindly use -DBL_MAX and +DBL_MAX as the second argument for nextafter to specify the negative and positive direction respectively. Are there any pitfalls in doing so?
(A refinement of 2). If I know for sure that b is [slightly] greater than a, is there any reason to prefer nextafter(a, b) over nextafter(a, DBL_MAX)? E.g. is there a chance of better performance for nextafter(a, b) version?
Is nextafter generally a heavy operation? I know that it is implementation-dependent. But, again, assuming an implementation that is based in IEEE 754 representations, is it fairly "difficult" to find the adjacent floating-point value?
With IEEE-754 binary floating point representations, if both arguments of nextafter are finite and the two arguments are not equal, then the result can be computed by either adding one to or subtracting one from the representation of the number reinterpreted as an unsigned integer [Note 1]. The (slight) complexity results from correctly dealing with the corner cases which do not meet those preconditions, but in general you'll find that it is extremely fast.
Aside from NaNs, the only thing that matters about the second argument is whether it is greater than, less than, or equal to the first argument.
The interface basically provides additional clarity for the corner case results, but it is also sometimes useful. In particular, the usage nextafter(x, 0), which truncates regardless of sign, is often convenient. You can also take advantage of the fact that nextafter(x, x); is x to clamp the result at an arbitrary value.
The difference between nextafter and nexttowards is that the latter allows you to use the larger dynamic range of long double; again, that helps with certain corner cases.
Strictly speaking, if the first argument is a zero of some sign and the other argument is a valid non-zero number of the opposite sign, then the argument needs to have its sign bit flipped before the increment. But it seemed too much legalese to add that to the list, and it is still hardly a complicated transform.
It is well known that in C, floating point literals (e.g. 1.23) have type double. As a consequence, any calculation that involves them is promoted to double.
I'm working on an embedded real-time system that has a floating point unit that supports only single precision (float) numbers. All my variables are float, and this precision is sufficient. I don't need (nor can afford) double at all. But every time something like
if (x < 2.5) ...
is written, disaster happens: the slowdown can be up to two orders of magnitude. Of course, the direct answer is to write
if (x < 2.5f) ...
but this is so easy to miss (and difficult to detect until too late), especially when a 'configuration' value is #define'd in a separate file by a less disciplined (or just new) developer.
So, is there a way to force the compiler to treat all (floating point) literals as float, as if with suffix f? Even if it's against the specs, I don't care. Or any other solutions? The compiler is gcc, by the way.
-fsingle-precision-constant flag can be used. It causes floating-point constants to be loaded in single precision even when this is not exact.
Note- This will also use single precision constants in operations on double precision variables.
Use warnings instead: -Wdouble-promotion warns about implicit float to double promotion, as in your example. -Wfloat-conversion will warn about cases where you may still be assigning doubles to floats.
This is a better solution than simply forcing double values to the nearest float value. Your floating-point code is still compliant, and you won't get any nasty surprises if a double value holds a positive value, say, less than FLT_DENORM_MIN (assuming IEEE-754) or greater than FLT_MAX.
You can cast the defined constants to (float) wherever they are used, the optimizer should do its job. This is a portable solution.
#define LIMIT 2.5
if (x < (float)LIMIT) ...
The -Wunsuffixed-float-constants flag could be used too, maybe combined with some of the other options in the accepted answer above. However, this probably won't catch unsuffixed constants in system headers. Would need to use -Wsystem-headers to catch those too. Could generate a lot of warnings...
in Redis (http://code.google.com/p/redis) there are scores associated to elements, in order to take this elements sorted. This scores are doubles, even if many users actually sort by integers (for instance unix times).
When the database is saved we need to write this doubles ok disk. This is what is used currently:
snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
Additionally infinity and not-a-number conditions are checked in order to also represent this in the final database file.
Unfortunately converting a double into the string representation is pretty slow. While we have a function in Redis that converts an integer into a string representation in a much faster way. So my idea was to check if a double could be casted into an integer without lost of data, and then using the function to turn the integer into a string if this is true.
For this to provide a good speedup of course the test for integer "equivalence" must be fast. So I used a trick that is probably undefined behavior but that worked very well in practice. Something like that:
double x = ... some value ...
if (x == (double)((long long)x))
use_the_fast_integer_function((long long)x);
else
use_the_slow_snprintf(x);
In my reasoning the double casting above converts the double into a long, and then back into an integer. If the range fits, and there is no decimal part, the number will survive the conversion and will be exactly the same as the initial number.
As I wanted to make sure this will not break things in some system, I joined #c on freenode and I got a lot of insults ;) So I'm now trying here.
Is there a standard way to do what I'm trying to do without going outside ANSI C? Otherwise, is the above code supposed to work in all the Posix systems that currently Redis targets? That is, archs where Linux / Mac OS X / *BSD / Solaris are running nowaday?
What I can add in order to make the code saner is an explicit check for the range of the double before trying the cast at all.
Thank you for any help.
Perhaps some old fashion fixed point math could help you out. If you converted your double to a fixed point value, you still get decimal precision and converting to a string is as easy as with ints with the addition of a single shift function.
Another thought would be to roll your own snprintf() function. Doing the conversion from double to int is natively supported by many FPU units so that should be lightning fast. Converting that to a string is simple as well.
Just a few random ideas for you.
The problem with doing that is that the comparisons won't work out the way you'd expect. Just because one floating point value is less than another doesn't mean that its representation as an integer will be less than the other's. Also, I see you comparing one of the (former) double values for equality. Due to rounding and representation errors in the low-order bits, you almost never want to do that.
If you are just looking for some kind of key to do something like hashing on, it would probably work out fine. If you actually care about which values really have greater or lesser value, its a bad idea.
I don't see a problem with the casts, as long as x is within the range of long long. Maybe you should check out the modf() function which separates a double into its integral and fractional part. You can then add checks against (double)LLONG_MIN and (double)LLONG_MAX for the integral part to make sure. Though there may be difficulties with the precision of double.
But before doing anything of this, have you made sure it actually is a bottleneck by measuring its performance? And is the percentage of integer values high enough that it would really make a difference?
Your test is perfectly fine (assuming you have already separately handled infinities and NANs by this point) - and it's probably one of the very few occaisions when you really do want to compare floats for equality. It doesn't invoke undefined behaviour - even if x is outside of the range of long long, you'll just get an "implementation-defined result", which is OK here.
The only fly in the ointment is that negative zero will end up as positive zero (because negative zero compares equal to positive zero).
I am having some trouble with IEEE floating point rules preventing compiler optimizations that seem obvious. For example,
char foo(float x) {
if (x == x)
return 1;
else
return 0;
}
cannot be optimized to just return 1 because NaN == NaN is false. Okay, fine, I guess.
However, I want to write such that the optimizer can actually fix stuff up for me. Are there mathematical identities that hold for all floats? For example, I would be willing to write !(x - x) if it meant the compiler could assume that it held all the time (though that also isn't the case).
I see some reference to such identities on the web, for example here, but I haven't found any organized information, including in a light scan of the IEEE 754 standard.
It'd also be fine if I could get the optimizer to assume isnormal(x) without generating additional code (in gcc or clang).
Clearly I'm not actually going to write (x == x) in my source code, but I have a function that's designed for inlining. The function may be declared as foo(float x, float y), but often x is 0, or y is 0, or x and y are both z, etc. The floats represent onscreen geometric coordinates. These are all cases where if I were coding by hand without use of the function I'd never distinguish between 0 and (x - x), I'd just hand-optimize stupid stuff away. So, I really don't care about the IEEE rules in what the compiler does after inlining my function, and I'd just as soon have the compiler ignore them. Rounding differences are also not very important since we're basically doing onscreen drawing.
I don't think -ffast-math is an option for me, because the function appears in a header file, and it is not appropriate that the .c files that use the function compile with -ffast-math.
Another reference that might be of some use for you is a really nice article on floating-point optimization in Game Programming Gems volume 2, by Yossarian King. You can read the article here. It discusses the IEEE format in quite detail, taking into account implementations and architecture, and provides many optimization tricks.
I think that you are always going to struggle to make computer floating-point-number arithmetic behave like mathematical real-number arithmetic, and suggest that you don't for any reason. I suggest that you are making a type error trying to compare the equality of 2 fp numbers. Since fp numbers are, in the overwhelming majority, approximations, you should accept this and use approximate-equality as your test.
Computer integers exist for equality testing of numerical values.
Well, that's what I think, you go ahead and fight the machine (well, all the machines actually) if you wish.
Now, to answer some parts of your question:
-- for every mathematical identity you are familiar with from real-number arithmetic, there are counter examples in the domain of floating-point numbers, whether IEEE or otherwise;
-- 'clever' programming almost always makes it more difficult for a compiler to optimise code than straightforward programming;
-- it seems that you are doing some graphics programming: in the end the coordinates of points in your conceptual space are going to be mapped to pixels on a screen; pixels always have integer coordinates; your translation from conceptual space to screen space defines your approximate-equality function
Regards
Mark
If you can assume that floating-point numbers used in this module will not be Inf/NaN, you can compile it with -ffinite-math-only (in GCC). This may "improve" the codegen for examples like the one you posted.
You could compare for bitwise equality. Although you might get bitten for some values that are equivalent but bitwise different, it will catch all those cases where you have a true equality as you mentioned. And I am not sure the compiler will recognize what you do and remove it when inlining (which I believe is what you are after), but that can easily be checked.
What happened when you tried it the obvious way and profiled it? or examined the generated asm?
If the function is inlined with values known at the call site, the optimizer has this information available. For example: foo(0, y).
You may be surprised at the work you don't have to do, but at the very least profiling or looking at what the compiler actually does with the code will give you more information and help you figure out where to proceed next.
That said, if you know certain things that the optimizer can't figure out itself, you can write multiple versions of the function, and specify the one you want to call. This is something of a hassle, but at least with inline functions they will all be specified together in one header. It's also quite a bit easier than the next step, which is using inline asm to do exactly what you want.