I'm writing a little library where you can set a range; start and end points are doubles. The library has some build-in or calculated default values for that range, but once they are set by the range setting function, there is no way to go back to the default value.
Hence what I like to do is to use the NaN value as the indicator to use the default value, but I haven't found any standard definition of NaN, and reading the gcc manual it says that there are platforms that don't support NaN.
My questions are:
Are there any recent platforms that don't use IEEE 754 floating point numbers? I don't care about some obscured embedded devices, because the lib focuses on platforms with GUI, to be accurate cairo.
And the second question would you use the NaN value as an argument for such a purpose? I have no problem with defining it some where in the header.
NaN is not equal to any number, not even to itself. Hence, using it as an indicator will lead to convoluted code or even bugs. I would not use it in this way.
I would not use a NaN for this purpose - beyond the issue of just which NaN to use (and there are many), it would be better to add a function call API to reset to the defaults.
NaNs are kind of weird to deal with in code, and I certainly wouldn't like a library to use them purposes which they are not made for.
Edit: Another problem that I just thought of is that if a calculation results in NaN, and it is passed as the argument, you will get unintended behavior. For example:
MyFunc(SomeCalculation()); //if SomeCalculation() is assumed to not be NaN,
//this will cause unintended behavior
Related
The manual pages for fenv.h (feraiseexcept and its ilk) are unusually uninformative; the examples I find online (cppreference.com and others) are very minimal.
How are they supposed to be used? In particular, does feraiseexcept(...) always return? What should one return from a function that gets an illegal argument, like sqrt(-1)? I assume NAN.
Should one get and restore the original state in a function? For example, one might compute a starting point for some iterative algorithm, if that computation turns out inaccurate is of no consequence as presumably, the iteration can converge to full precision.
How should one use this in a program calling e.g. library functions?
(I'd prefer not to have to dive into random math library sources to answer the above.)
The manual pages for fenv.h (feraisexceptionand [its] ilk) are unusually uninformative, the examples I find on line (cppreference.com and others) are very minimal.
<fenv.h> is specified by the C standard. The Unix manual pages are useful only insofar as they extend the C specification. Regard cppreference.com with skepticism; it is known to have errors.
How are they supposed to be used?
Discussing all of <fenv.h> is too broad a question for Stack Overflow.
In particular, does feraisexception(...) always return?
Per C 2018 7.6.2.3 2 and foonote 221, feraiseexcept attempts to cause floating-point exceptions as if they had been generated by arithmetic instructions. Thus, if it raises an exception for which a trap is enabled, it will cause a trap.
In contrast, fesetexceptflag merely sets floating-point exception flags without generating actual exceptions. Per 7.6.2.4 2, “… This function does not raise floating-point exceptions, but only sets the state of the flags.”
What should one return from a function that gets an illegal argument, like sqrt(-1)? I assume NAN.
This is outside the domain of <fenv.h>. sqrt is specified in 7.12, covering <math.h>. Per 7.12.7.5 2, a sqrt domain error occurs if the argument is less than zero. Per 7.12.1, 2, “… On a domain error, the function returns an implementation-defined value…” and it may also set errno and/or raise the “invalid” floating-point exception. Commonly, implementations will return a quiet NaN.
Should one get and restore the original state in a function?
This is up to the person who is specifying or implementing a function. Routines that provide “elementary” mathematical functions, as for the standard math library, may be required to affect the floating-point state only as called for by the ideal function being provided, concealing any internal operations. For example, if log10(100) is implemented by using an engineered polynomial to approximate the logarithm, the evaluation of the polynomial might use arithmetic operations that have very high precision and accuracy, so high that the final result, when rounded to the final format, is exactly two. But the intermediate calculations might involve some operations that were inexact. Thus, the inexact exception would be raised. If the routine merely evaluated the polynomial and returned the exact result, 2, it would have raised the inexact flag. Ideally, the routine would suppress floating-point traps, save the exception flags, do its calculations, restore originally enabled traps, set the proper exception flags if any, and return the result. (Alternately, the routine might be implemented to use only integer arithmetic, avoiding the floating-point issues.)
Outside of specialized library routines, floating-point subroutines rarely go to this extent. It is up to each application how it wants its routines to behave.
For example, one might compute a starting point for some iterative algorithm, if that computation turns out inaccurate is of no consecuence as pressumably the iteration can converge to full precision.
This paragraph is unclear and may be ungrammatical. I am unable to answer it as written.
How should one use this in a program calling e.g. library functions?
This question is unclear, possibly due to the lack of clarity of the preceding paragraph. The antecedent of “this” is unclear.
Aside from the NAN macro, C99 has two ways to generate a NaN value for a floating point number, the nanf(const char *tagp) function and strtof("NAN(char-sequence)").
Both of these methods of generating a NaN take an optional string argument (*tagp in nanf() and the char-sequence in the strtof method). What exactly does this string argument do? I haven't been able to find any concrete examples of how you'd use it. From cppreference.com we have:
The call nan("string") is equivalent to the call strtod("NAN(string)", (char**)NULL);
The call nan("") is equivalent to the call strtod("NAN()", (char**)NULL);
The call nan(NULL) is equivalent to the call strtod("NAN", (char**)NULL);
And nan(3) says:
These functions return a representation (determined by tagp) of a quiet NaN. [snip]
The argument tagp is used in an unspecified manner. On IEEE 754 systems, there are many representations of NaN, and
tagp selects one.
This doesn't really tell me what I can use for the tagp string or why I'd ever want to use it. Is there a list anywhere of the valid options for this tag string, and what would the reason be to use one over the default nanf(NULL)?
Tl;Dr : tagp argument gives you the ability to have different NAN values.
This is from man page for nan(3) which gives a little more information on tagp.
Mainly:
The nan() functions return a quiet NaN, whose trailing fraction field
contains the result of converting
tagp to an unsigned integer.
This gives you the ability to have different NAN values.
Specifically from the C99 Rationale doc:
Other applications of NaNs may prove useful. Available parts of NaNs
have been used to encode auxiliary information, for example about the
NaN’s origin. Signaling NaNs might be candidates for filling
uninitialized storage; and their available parts could distinguish
uninitialized floating objects. IEC 60559 signaling NaNs and trap
handlers potentially provide hooks for maintaining diagnostic
information or for implementing special arithmetics.
There is an implementation of it here. Mind you, this may or may not be standard conforming, as noted in comments. However, it should give you an idea of what tagp is used for.
As in the man page, you can see the replacement mentioned above:
nan("1") = nan (7ff8000000000001)
nan("2") = nan (7ff8000000000002)
Full man page here:
NAN(3) BSD Library Functions Manual
NAN(3)
NAME
nan -- generate a quiet NaN
SYNOPSIS
#include
double
nan(const char *tagp);
long double
nanl(const char *tagp);
float
nanf(const char *tagp);
DESCRIPTION
The nan() functions return a quiet NaN, whose trailing fraction field contains the result of converting
tagp to an unsigned integer. If tagp is too large to be contained in the trailing fraction field of the
NaN, then the least significant bits of the integer represented by tagp are used.
SPECIAL VALUES
If tagp contains any non-numeric characters, the function returns a NaN whos trailing fraction field is
zero.
If tagp is empty, the function returns a NaN whos trailing fraction field is zero.
STANDARDS
The nan() functions conform to ISO/IEC 9899:2011.
BSD July 01, 2008
This doesn't really tell me what I can use for the tagp string or why I'd ever want to use it.
Some floating point standards, e.g., IEEE-754, have multiple different NaN values. This nan function specification allows an implementation to select a specific NaN representation depending on the string on a way that might be specified by the implementation.
I'm fairly new to Lua. While testing I discovered #INF/#IND. However, I can't find a good reference that explains it.
What are #INF, #IND, and similar (such as negatives) and how do you generate and use them?
#INF is infinite, #IND is NaN. Give it a test:
print(1/0)
print(0/0)
Output on my Windows machine:
1.#INF
-1.#IND
As there's no standard representation for these in ANSI C, you may get different result. For instance:
inf
-nan
Expanding #YuHao already good answer.
Lua does little when converting a number to a string, since it heavily relies on the underlying C library implementation. In fact Lua print implementation calls Lua tostring which in turn (after a series of other calls) uses the lua_number2str macro, which is defined in terms of C sprintf. Thus in the end you see whatever representation for infinities and NaNs the C implementation uses (this may vary according to which compiler was used to compile Lua and which C runtime your application is linked to).
#YuHao has already answered what the OP has effectively asked: what does +/-1.#INF (+-inf) and -1.#IND (nan) mean.
What I want to do here is just to add some value to the question/answer by expanding on to deal with -- to check -- them (which I just needed and learned to):
inf (+/-1.#INF) are the highest number(+/-) that Lua can represent, and the Language provides such value(s) for you through math.huge. So you can test if a number is +/-INF:
local function isINF(value)
return value == math.huge or value == -math.huge
end
nan (-1.#IND) is something that can not be handled numerically, and the result of any operation involving it is also Not-a-number(*). Long-story-short... if a number is a NaN, comparing it against itself will (always) be False. The function below implements the simplest way for checking if a NaN:
local function isNAN(value)
return value ~= value
end
(*): This (NaN) is formally defined some where in the IEEE754 standard (floating-point numbers).
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.
Is it a good idea to use IEEE754 floating point NaN (not-a-number) for values which are undefined for non-mathematical reasons?
In our case they are not yet set because the values have not been received from some other device. The context is an embedded system using IEC1131 REAL32 values. Edit: The programming language is C, so we would most likely use NAN and isnanf(x), which are from C99. Though we may need some extra contortions to get these into our OS compatibility layer.
The default in programming languages seems to be to initialize floating point variables with positive zero, whose internal representation is all zeros. That is not usable for us, because 0 is in the range of valid values.
It seems like a clean solution to use NaN, but maybe it is more hassle than it is worth and we should pick some other value?
Just noticed this question.
This is one of the uses of NaNs that the IEEE 754 committee has in mind (I was a committee member). The propagation rules for NaNs in arithmetic make this very attractive, because if you have a result from a long sequence of calculations that involve some initialized data, you will not mistake the result for a valid result. It can also make tracing back through your calculations to find where you are using the initialized data much more straightforward.
That said, there are a few pitfalls that are outside of the 754 committee's control: as others have noted, not all hardware supports NaN values at speed, which can result in performance hazards. Fortunately, one does not often do a lot of operations on initialized data in a performance-critical setting.
NaNs are a reasonable choice for a 'no value' sentential (the D programming language uses them for uninitialized values, for instance), but because any comparisons involving them will be false, you can get a few surprises:
if (result == DEFAULT_VALUE), won't work as expected if DEFAULT_VALUE is NaN, as Jon mentioned.
They can also cause problems with range checking if you're not careful. Consider the function:
bool isOutsideRange(double x, double minValue, double maxValue)
{
return x < minValue || x > maxValue;
}
If x is NaN, this function would incorrectly report that x is between minValue and maxValue.
If you just want a magic value for users to test against, I'd recommend positive or negative infinity instead of NaN, as it doesn't come with the same traps. Use NaN when you want it for its property that any operations on a NaN result in a NaN: it's handy when you don't want to rely on callers checking the value, for example.
[Edit: I initially managed to type "any comparisons involving them will be true" above, which is not what I meant, and is wrong, they're all false, apart from NaN != NaN, which is true]
I have used NaNs in similar situations just because of that: the usual default initialization value 0 is also a valid value. NaNs work fine so far.
It's a good question, by the way, why the default initialization value is usually (for instance, in Java primitive types) 0 and not NaN. Couldn't it as well be 42 or whatever? I wonder what's the rationale of zeros.
I think it is a bad idea in general. One thing to keep in mind is that most CPU treat Nan much slower then "usual" float. And it is hard to guarantee you will never have Nan in usual settings. My experience in numerical computing is that it often brings more trouble than it worths.
The right solution is to avoid encoding "absence of value" in the float, but to signal it in another way. That's not always practical, though, depending on your codebase.
Be careful with NaN's... they can spread like wildfire if you are not careful.
They are a perfectly valid value for floats, but any assignments involving them will also equal NaN, so they propagate through your code. This is quite good as a debugging tool if you catch it, however it can also be a real nuisance if you are bringing something to release and there is a fringe case somewhere.
D uses this as rationale for giving floats NaN as default. (Which I'm not sure I agree with.)
My feelings are that it's a bit hacky, but at least every other numbers you make operations with this NaN value gives NaN as result - when you see a NaN in a bug report, at least you know what kind of mistake you are hunting.
If your basic need is to have a floating point value which doesn't represent any number which could possibly have been received from the device, and if the device guarantees it will never return NaN, then it seems reasonable to me.
Just remember that depending on your environment, you probably need a special way of detecting NaNs (don't just use if (x == float.NaN) or whatever your equivalent is.)
This sounds like a good use for nans to me. Wish I had thought of it...
Sure, they are supposed to propagate like a virus, that is the point.
I think I would use nan instead of one of the infinities. It might be nice to use a signaling nan and have it cause an event on the first use, but by then its too late it should go quiet on the first use.
Using NaN as a default value is reasonable.
Note that some expressions, such as (0.0 / 0.0), return NaN.