38

In the latest C++ standard, I noticed the following macros :

bool isgreater(float x, float y);
bool isgreaterequal(float x, float y);
bool isless(float x, float y);
bool islessequal(float x, float y);
bool islessgreater(float x, float y);
bool isunordered(float x, float y);

These macros are from C (7.12.14 and 7.12.14).

So, why would someone use these macros, instead of operators? Is there anything special that these macros are doing (like checking for inf), or are they the same as their corresponding operator?

C++ example :

#include <iostream>
#include <cmath>

int main()
{
  float x=0.2;
  float y=0.5;
  std::cout << x << " < " << y << " : " << std::boolalpha << std::islessequal( x, y ) << std::endl;
  std::cout << x << " < " << y << " : " << std::boolalpha << ( x <= y ) << std::endl;
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
BЈовић
  • 62,405
  • 41
  • 173
  • 273

2 Answers2

38

Unlike the relational operators, these macros do really only return a boolean value and do never raise any floating point exception.

In short: You only have to deal with true/false and nothing else.


references:

The Open Group descriptions (not the C or C++ standard, but highly relevant in the Unix/Linux world and almost always similar to the standards):

C++ standard:

C Library [c.math]:

The classification/comparison functions behave the same as the C macros with the corresponding names defined in 7.12.3, Classification macros, and 7.12.14, Comparison macros in the C Standard. Each function is overloaded for the three floating-point types, as follows [...]

C standard:

7.12.14 Comparison macros

[...] For any ordered pair of numeric values exactly one of the relationships — less, greater, and equal — is true. Relational operators may raise the ‘‘invalid’’ floating-point exception when argument values are NaNs. For a NaN and a numeric value, or for two NaNs, just the unordered relationship is true. The following subclauses provide macros that are quiet (non floating-point exception raising) versions of the relational operators, and other comparison macros that facilitate writing efficient code that accounts for NaNs without suffering the ‘‘invalid’’ floating-point exception. In the synopses in this subclause, real-floating indicates that the argument shall be an expression of real floating type.

Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • 3
    I.e. we _still_ don't have a valid predicate for `std::set` other than the rather useless `isunordered`. (See http://stackoverflow.com/questions/4816156/are-ieee-floats-valid-key-types-for-stdmap-and-stdset why) – MSalters Aug 06 '12 at 12:46
  • @MSalters: I love macros, too, no rly. – Sebastian Mach Aug 06 '12 at 15:03
  • 1
    It's not a macro problem (they're not even macro's in C++). The functions fail to define a strict weak ordering for `NaN`. They just remove the exception, but that doesn't make the result useful enough. – MSalters Aug 06 '12 at 15:07
  • Yeah, missed the part about that being functions in C++ :P But I realised the ordering problem, too. – Sebastian Mach Aug 06 '12 at 15:14
14

isgreater et al. were incorporated into C++11 from C99. They are defined to not raise the invalid floating-point exception when x and/or y are signalling NaN values.

The rationale given is:

This macro is a quiet (non-floating-point exception raising) version of a relational operator. It facilitates writing efficient code that accounts for NaNs without suffering the invalid floating-point exception.

The numeric value of the macro on NaN is the same as always; NaN values compare false to all other values including NaN values under all relational operators and the new macros.

ecatmur
  • 152,476
  • 27
  • 293
  • 366