ATLAS makes fairly heavy use of macros in order to achieve something approaching precision (and in some cases type) independent code. Any routine can include the general macro file atlas_misc.h in order to get access to these macros. Low level routines are compiled multiple times with differing makefile-controlled cpp macros (call these index macros) in order to produce differing implementations. The index macros used in ATLAS presently include:
Each of these index macros define a number of helper macros that go with
them. atlas_misc.h should be examined for full details.
For instance, if SREAL or DREAL are defined, the
type-determinant macro TREAL is defined. Similarly,
if SCPLX or DCPLX are defined, the
type-determinant macro TCPLX is defined.
For a simpler example, the precision macro defines ATL_rone
, which
corresponds to 1.0f in single precision, and 1.0 in double.
A great many of these helper macros are designed to be used to help
in resolving names independant of type. In order to use these naming
macros, we use the macro-joining function Mjoin(Mac1, Mac2),
which results in the joining of the Mac1 and Mac2.
You can examine the GEMV kernel implementations for examples of how this works. In particular, ATLAS uses the same implementation for single and double precision by using these macros, and recompiling the same source with differing index macros. Just to give a quick example, the index macro controlling defines a helper macro BNM which corresponds to the correct beta name for the gemv and ger kernels. Using this trick, we can reduce:
#ifdef BETA0 #ifdef Conj_ void ATL_dgemvNc_a1_x1_b0_y1 #else void ATL_dgemvN_a1_x1_b0_y1 #endif #elif defined (BETA1) #ifdef Conj_ void ATL_dgemvNc_a1_x1_b1_y1 #else void ATL_dgemvN_a1_x1_b1_y1 #endif #elif defined (BETAXI0) #ifdef Conj_ void ATL_dgemvNc_a1_x1_bXi0_y1 #else void ATL_dgemvN_a1_x1_bXi0_y1 #endif #else #ifdef Conj_ void ATL_dgemvNc_a1_x1_bX_y1 #else void ATL_dgemvN_a1_x1_bX_y1 #endif #endifto:
#include "atlas_misc.h" #ifdef Conj_ void Mjoin(Mjoin(ATL_dgemvNc_a1_x1,BNM),_y1) #else void Mjoin(Mjoin(ATL_dgemvN_a1_x1,BNM),_y1) #endif