# Using the Intel® Math Library

Many routines in the Intel® Math Library are more optimized for Intel® microprocessors than for non-Intel microprocessors.

The mathimf.h header file includes prototypes for Intel® Math Library functions.

To use the Intel Math Library, include the header file, mathimf.h, in your program. If the Intel® oneAPI DPC++/C++ Compiler is used for linking, then the Intel Math Library is used by default.

## Example: Using Real Functions

The following examples demonstrate how to use the Intel Math Library with the Intel oneAPI DPC++/C++ Compiler. After you compile this example and run the program, the program will display the sine value of `x`.

Linux*

    // real_math.c
    #include <stdio.h>
    #include <mathimf.h>

    int main() {
     float fp32bits;
     double fp64bits;
     long double fp80bits;
     long double pi_by_four = 3.141592653589793238/4.0;

    // pi/4 radians is about 45 degrees
     fp32bits = (float) pi_by_four; // float approximation to pi/4
     fp64bits = (double) pi_by_four; // double approximation to pi/4
     fp80bits = pi_by_four; // long double (extended) approximation to pi/4

    // The sin(pi/4) is known to be 1/sqrt(2) or approximately .7071067
     printf("When x = %8.8f, sinf(x) = %8.8f \n", fp32bits, sinf(fp32bits));
     printf("When x = %16.16f, sin(x) = %16.16f \n", fp64bits, sin(fp64bits));
     printf("When x = %20.20Lf, sinl(x) = %20.20Lf \n", fp80bits, sinl(fp80bits));

     return 0;
    }

Use the following command to compile the example code on Linux platforms:

    [invocation] real_math.c

The invocation is `icx` for C, `icpx` for C++, or `dpcpp` for DPC++.

Windows*

    // real_math.c
    #include <stdio.h>
    #include <mathimf.h>

    int main() {
      float fp32bits;
      double fp64bits;

    // /Qlong-double compiler option required because, without it,
    // long double types are mapped to doubles.
      long double fp80bits;
      long double pi_by_four = 3.141592653589793238/4.0;

    // pi/4 radians is about 45 degrees
      fp32bits = (float) pi_by_four;

    // float approximation to pi/4
      fp64bits = (double) pi_by_four;

    // double approximation to pi/4
      fp80bits = pi_by_four;

    // long double (extended) approximation to pi/4
    // The sin(pi/4) is known to be 1/sqrt(2) or approximately .7071067
      printf("When x = %8.8f, sinf(x) = %8.8f \n",
      fp32bits, sinf(fp32bits));

      printf("When x = %16.16f, sin(x) = %16.16f \n",
      fp64bits, sin(fp64bits));

      printf("When x = %20.20f, sinl(x) = %20.20f \n",
      (double) fp80bits, (double) sinl(fp80bits));

    // printf() does not support the printing of long doubles
    // on Microsoft* Windows*, so fp80bits is cast to double in this example.
      return 0;
    }

This content is specific to C++; it does not apply to DPC++.

Since the real_math.c program includes the long double data type, use the /Qlong-double and /Qpc80 compiler options in the command line:

`[invocation] /Qlong-double /Qpc80 real_math.c`

The invocation is `icx` for C/C++ or `dpcpp-cl` for DPC++.

## Example Using Complex Functions

After you compile this example and run the program, you should get the following results:

`When z = 1.0000000 + 0.7853982 i, cexpf(z) = 1.9221154 + 1.9221156 i`

`When z = 1.000000000000 + 0.785398163397 i, cexp(z) = 1.922115514080 + 1.922115514080 i`

Linux and Windows

    // complex_math.c
    #include <stdio.h>
    #include <complex.h>

    int main() {
      float _Complex c32in,c32out;
      double _Complex c64in,c64out;
      double pi_by_four= 3.141592653589793238/4.0;
      c64in = 1.0 + I* pi_by_four;

    // Create the double precision complex number 1 + (pi/4) * i
    // where I is the imaginary unit.
      c32in = (float _Complex) c64in;

    // Create the float complex value from the double complex value.
      c64out = cexp(c64in);
      c32out = cexpf(c32in);

    // Call the complex exponential,
    // cexp(z) = cexp(x+iy) = e^ (x + i y) = e^x * (cos(y) + i sin(y))
     printf("When z = %7.7f + %7.7f i, cexpf(z) = %7.7f + %7.7f i \n"
     ,crealf(c32in),cimagf(c32in),crealf(c32out),cimagf(c32out));
     printf("When z = %12.12f + %12.12f i, cexp(z) = %12.12f + %12.12f i \n"
     ,creal(c64in),cimag(c64in),creal(c64out),cimagf(c64out));

      return 0;
    }

Since this example program includes the _Complex data type, be sure to include the [Q]std=c99 compiler option in the command line.

To compile this example code in Linux use the following command:

    [invocation] -std=c99 complex_math.c

The invocation is `icx` for C, `icpx` for C++, or `dpcpp` for DPC++.

To compile this example code in Windows, use the following command:

    [invocation] /Qstd=c99 complex_math.c

The invocation is `icx` for C/C++ or `dpcpp-cl` for DPC++.

### Note

_Complex data types are supported in C but not in C++ programs.

## Exception Conditions

If you call a math function using argument(s) that may produce undefined results, an error number is assigned to the system variable errno. Math function errors are usually domain errors or range errors.

Domain errors result from arguments that are outside the domain of the function. For example, acos is defined only for arguments between -1 and +1 inclusive. Attempting to evaluate `acos(-2)` or `acos(3)` results in a domain error, where the return value is QNaN.

Range errors occur when a mathematically valid argument results in a function value that exceeds the range of representable values for the floating-point data type. Attempting to evaluate `exp(1000)` results in a range error, where the return value is INF.

When domain or range error occurs, the following values are assigned to errno:

- domain error (EDOM): `errno = 33`

- range error (ERANGE): `errno = 34`

The following example shows how to read the errno value for an EDOM and ERANGE error.

    // errno.c
    #include <errno.h>
    #include <mathimf.h>
    #include <stdio.h>

    int main(void) {
      double neg_one=-1.0;
      double zero=0.0;

    // The natural log of a negative number is considered a domain error - EDOM
      printf("log(%e) = %e and errno(EDOM) = %d \n",neg_one,log(neg_one),errno);

    // The natural log of zero is considered a range error - ERANGE
      printf("log(%e) = %e and errno(ERANGE) = %d \n",zero,log(zero),errno);
    }

The output of errno.c will look like this:

`log(-1.000000e+00) = nan and errno(EDOM) = 33`

`log(0.000000e+00) = -inf and errno(ERANGE) = 34`

For the math functions in this section, a corresponding value for errno is listed when applicable.

Other Considerations

Some math functions are inlined automatically by the compiler. The functions actually inlined may vary and may depend on any vectorization or processor-specific compilation options used. You can disable automatic inline expansion of all functions by compiling your program with the -fno-builtin option (Linux) or the /Oi- option (Windows).

It is strongly recommended to use the default rounding mode (round-to-nearest-even) when calling math library transcendental functions and compiling with default optimization or higher. Faster implementations— in terms of latency and/or throughput— of these functions are validated under the default round-to-nearest-even mode. Using other rounding modes may make results generated by these faster implementations less accurate, or set unexpected floating-point status flags. This behavior may be avoided by using the -fp-model strict option (Linux) or /fp: strict option (Windows). This option warns the compiler not to assume default settings for the floating-point environment.

### Note

64-bit decimal transcendental functions rely on binary double extended precision arithmetic.

To obtain accurate results, user applications that call 64-bit decimal transcendentals should ensure that the x87 unit is operating in 80-bit precision (64-bit binary significands). In an environment where the default x87 precision is not 80 bits, such as Windows, it can be set to 80 bits by compiling the application source files with the /Qpc80 option.

A change of the default precision control or rounding mode may affect the results returned by some of the mathematical functions.

The following are important compiler options when using certain data types in IA-32 (for C++ only) and Intel® 64 architectures running Windows operating systems:

- /Qlong-double: Use this option when compiling programs that require support for the long double data type (80-bit floating-point). Without this option, compilation will be successful, but long double data types will be mapped to double data types.

- /Qstd=c99: Use this option when compiling programs that require support for _Complex data types.

Parent topic: Intel® Math Library

## See Also

fbuiltin, Oi compiler option
Overview: Tuning Performance
Qlong-double compiler option
std, Qstd compiler option