Floating Point - fpclassify

Hello everyone!

I am working on a project that needs to recognize if an input double is not actually a number that can normally be represented by the IEEE 754 Standard format ( inf, NaN, zero …). So for these occasions in c++ ( and c ), I use the fpclassify function. You can find it here: fpclassify - C++ Reference .

So I try this on the Arduino IDE, and during the Validation, the compiler does not recognise it. I have to say that I include the <math.h> library. Here is an example of what I tried in order to debug ( actually the example of cplusplus reference changed main to setup and printf to Serial.print). Here is the code:

/* fpclassify example */
#include <math.h>       /* fpclassify, signbit, FP_* */

void setup()
{
  Serial.begin (9600);
  
  double d = 1.0 / 0.0;
  switch (fpclassify(d)) {
    case FP_INFINITE:  Serial.println ("infinite");  break;
    case FP_NAN:       Serial.println ("NaN");       break;
    case FP_ZERO:      Serial.println ("zero");      break;
    case FP_SUBNORMAL: Serial.println ("subnormal"); break;
    case FP_NORMAL:    Serial.println ("normal");    break;
  }
  if (signbit(d)) Serial.println (" negative\n");
  else Serial.println (" positive or unsigned\n");
}

void loop()
{}

And the message I get:

sketch_may04a.ino: In function ‘void setup()’:
sketch_may04a.ino:9:23: error: ‘fpclassify’ was not declared in this scope
sketch_may04a.ino:10:10: error: ‘FP_INFINITE’ was not declared in this scope
sketch_may04a.ino:11:10: error: ‘FP_NAN’ was not declared in this scope
sketch_may04a.ino:12:10: error: ‘FP_ZERO’ was not declared in this scope
sketch_may04a.ino:13:10: error: ‘FP_SUBNORMAL’ was not declared in this scope
sketch_may04a.ino:14:10: error: ‘FP_NORMAL’ was not declared in this scope

I would appreciate it if somebody let me know why does this happen, and if there are some solutions.
Thank you for your help :slight_smile:

Evidently, that function is not defined in the Arduino version of math.h. Arduino C++ is nonstandard in several ways, for example "double" is treated the same as "float" on AVR-based Arduinos.

An interesting side question would be: "what does the compiler do with this line"?

 double d = 1.0 / 0.0;

Thank you for your reply :slight_smile:

Actually it seems to be like that ( it is not included in Arduino math.h ). I found another function is the cplusplus library to test, the isinf();

So answering to your question, what would the compiler do for the line:

double d = 1.0 / 0.0;

Actually it is ok, and it gives a value of inf as I can see. I wrote this code:

/* fpclassify example */
#include <math.h>       /* fpclassify, signbit, FP_* */

void setup()
{
  Serial.begin (9600);
  
  double d = 1.0 / 0.0;
  if ( isinf (d) ) Serial.print("Hello!\n");
 
  if (signbit(d)) Serial.println (" negative\n");
  else Serial.println (" positive or unsigned\n");
}

void loop()
{}

it was compiled and succesfully uploaded.
On the serial monitor I got this:

Hello!
positive or unsigned

I maintain an Arduino Helpers library that contains GCC’s cmath implementation, with support for the fpclassify function:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Arduino_Helpers[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]AH[/color][/b][color=#434f54]/[/color][color=#000000]STL[/color][color=#434f54]/[/color][color=#000000]cmath[/color][color=#434f54]>[/color]

[color=#00979c]void[/color] [color=#000000]print_classification[/color][color=#000000]([/color][color=#00979c]double[/color] [color=#000000]d[/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color] [color=#000000]([/color][color=#000000]d[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#5e6d03]switch[/color] [color=#000000]([/color][color=#000000]std[/color][color=#434f54]:[/color][color=#434f54]:[/color][color=#000000]fpclassify[/color][color=#000000]([/color][color=#000000]d[/color][color=#000000])[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#5e6d03]case[/color] [color=#000000]FP_INFINITE[/color][color=#434f54]:[/color]  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color] [color=#000000]([/color][color=#005c5f]"  infinite"[/color][color=#000000])[/color][color=#000000];[/color]  [color=#5e6d03]break[/color][color=#000000];[/color]
    [color=#5e6d03]case[/color] [color=#000000]FP_NAN[/color][color=#434f54]:[/color]       [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color] [color=#000000]([/color][color=#005c5f]"  NaN"[/color][color=#000000])[/color][color=#000000];[/color]       [color=#5e6d03]break[/color][color=#000000];[/color]
    [color=#5e6d03]case[/color] [color=#000000]FP_ZERO[/color][color=#434f54]:[/color]      [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color] [color=#000000]([/color][color=#005c5f]"  zero"[/color][color=#000000])[/color][color=#000000];[/color]      [color=#5e6d03]break[/color][color=#000000];[/color]
    [color=#5e6d03]case[/color] [color=#000000]FP_SUBNORMAL[/color][color=#434f54]:[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color] [color=#000000]([/color][color=#005c5f]"  subnormal"[/color][color=#000000])[/color][color=#000000];[/color] [color=#5e6d03]break[/color][color=#000000];[/color]
    [color=#5e6d03]case[/color] [color=#000000]FP_NORMAL[/color][color=#434f54]:[/color]    [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color] [color=#000000]([/color][color=#005c5f]"  normal"[/color][color=#000000])[/color][color=#000000];[/color]    [color=#5e6d03]break[/color][color=#000000];[/color]
  [color=#000000]}[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color] [color=#000000]([/color][color=#000000]std[/color][color=#434f54]:[/color][color=#434f54]:[/color][color=#d35400]signbit[/color][color=#000000]([/color][color=#000000]d[/color][color=#000000])[/color] [color=#434f54]?[/color] [color=#005c5f]" (negative)"[/color]
                                  [color=#434f54]:[/color] [color=#005c5f]" (positive or unsigned)"[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color] [color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#000000]1.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#434f54]-[/color][color=#000000]1.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#000000]0.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#434f54]-[/color][color=#000000]0.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#000000]1.[/color] [color=#434f54]/[/color] [color=#000000]0.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#434f54]-[/color][color=#000000]1.[/color] [color=#434f54]/[/color] [color=#000000]0.[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]print_classification[/color][color=#000000]([/color][color=#000000]0.[/color] [color=#434f54]/[/color] [color=#000000]0.[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color][color=#000000]}[/color]

Output:

1.00
  normal (positive or unsigned)
-1.00
  normal (negative)
0.00
  zero (positive or unsigned)
0.00
  zero (negative)
inf
  infinite (positive or unsigned)
inf
  infinite (negative)
nan
  NaN (negative)

Pieter