Visual C++ developers in need of math functions know to go <cmath>. In this blog post I’ll describe the equivalent in C++ AMP.

## <amp_math.h>

With C++ AMP, if you want to use a math function in your *restrict(amp)* functions, you need to bring in *<amp_math.h>*. In *amp_math.h* you’ll find two namespaces under the outer *concurrency* namespace and they are *fast_math* and *precise_math*. Under those namespaces you’ll find the function that you are looking for.

## concurrency::fast_math

The functions in this namespace only support single-precision do not require double precision support.

These functions sacrifice accuracy for speed. They are wrapper functions around existing HLSL intrinsics, e.g. C++ AMP’s *concurrency::fast_math::sqrt* function is equivalent to HLSL’s sqrt function.

## concurrency::precise_math

The functions in this namespace require and leverage full double precision support. In fact, and this is important to know, even if you use a function that takes and returns single-precision float types (i.e. seemingly has single precision requirements), the implementation still requires the accelerator to provide full double precision support. By using double precision features even for the implementation of some single precision functions, we can provide the higher accuracy of functions in this namespace.

Unlike the implementation of the functions in the *fast_math* namespace, the implementation of the *precise_math* functions was written from scratch for C++ AMP. So if you wanted to use the equivalent of the *sqrt* function mentioned in the previous section, you’d use *concurrency::precise_math::sqrt*.

## By the numbers

For those of you that are curious, currently *cmath* contains 22 functions, *fast_math* 35, and *precise_math* contains 68 functions.

From a single precision perspective, *precise_math* is a superset of *fast_math*, which itself is a superset of *cmath*. From a double precision perspective, *precise_math* is a superset of *cmath*.

## Code example

Consider the following full code listing (create empty C++ project, add empty cpp file, paste the 16 lines that follow)

#include <amp.h> #include <amp_math.h> using namespace concurrency; using namespace concurrency::precise_math; // 4 void main() { float a = 2.2f, b = 3.5f; float result = pow(a,b); // 8 std::vector<float> v(1); array_view<float> av(1,v); parallel_for_each(av.extent, [=](index<1> idx) restrict(amp) { av(0) = pow(a,b); // 13 }); _ASSERT(av(0) == result); // 15 }

The *pow* function on line 8 comes from <cmath> whereas the one on line 13 comes from *precise_math*, and line 15 is fine. If we were to change line 4 to use *fast_math* (using namespace concurrency::**fast**_math;) then line 13 would come from *fast_math* and, as a side effect, line 15 would assert (15.793534 != 15.793537).

*Disclaimer about line 15: float comparison should never be done with ==, but that is not the point here. Those results are on my machine with my compiler and my hardware - your mileage may vary.*

## Changes in Beta, since the Developer Preview

If you used our math functions in Visual Studio 11 Developer Preview, you will have noticed that there was no *amp_math.h* header file and instead everything was directly under the concurrency namespace in amp.h. You would have also noticed that there were none of the two namespaces described above; instead the *fast_math* functions were prefixed with “fast_”. Finally, not all of *precise_math* was implemented so you could have encountered double-precision functions that seemingly worked on non-double supporting hardware, due to a (very slow) stop-gap emulation solution we had in place which is now gone. We hope you find the new design easier and more intuitive to understand and use.