The math.h header provides a large variety of mathematical functions as well as one macro. This post will focus on just the macro while each function will have its own dedicated post.

HUGE_VAL

The only macro in math.h is HUGE_VAL which is defined as "a positive double expression, not neceessarily representable as a float." This sounds like a good place to use the IEEE 754 reserved value for infinity which is described like so:

$$sign = \begin{cases} 0 & \text{positive infinity}\\ 1 & \text{negative infinity} \end{cases} $$
$$exponent = 2^{w} - 1$$
$$significand = 0$$

We will use the value for positive infinity so that we can represent negative infinity by simply prepending the unary minus operator to this macro, (-HUGE_VAL). A double value on x86_64 is 8 bytes in length and it will be easiest just to represent this value with 16 hexadecimal digits:

#define HUGE_VAL    (0x7FF0000000000000L)

Since a hexadecimal constant in C can't have an exponent part then we use the L suffix to ensure that HUGE_VAL is interpreted as a double expression when it is used.

Test

The test for this macro is very simple and just ensures that the file has access to the macro through including the math.h header:

#include <math.h>

int
math_test(void)
{
    int ret         = 0;
    double hugeVal  = 0.0;

    /* Test the HUGE_VAL macro */
    hugeVal = HUGE_VAL;

    return ret;
}

If the test fails then a compile error will be generated:

error: ‘HUGE_VAL’ undeclared (first use in this function)

Otherwise, everything will compile and succeed.

Error Conditions

math.h functions make use of two macros to indicate error conditions, EDOM and ERANGE. We already talked about these and defined them in errno.h but we'll review them here.

A domain error occurs when an input argument is outside the domain over which the function is defined. When this occurrs, errno is set to EDOM and an implementation-defined value is returned to indicate that an error condition was triggered.

A range errors occurs when the result of a function can't be represented as a double value. If the result overflows the double type, the return value is set to HUGE_VAL with the same sign as the correct return value (if it was negative then we can return (-HUGE_VAL)) and errno is set to ERANGE. If the result underflows the double type then the return value is set to 0. For underflows, errno is not required to be set to ERANGE, but an implementation may choose to do so. This is because the value is so small that the architecture is not able to differentiate it from 0.

You can associate EDOM with input errors, while ERANGE deals with output errors. These macros aren't used in the math.h header itself but will be used by most, if not all, of the functions provided by math.h.

comments powered by Disqus