#ifndef BZ_SIMDTYPES_H #define BZ_SIMDTYPES_H #include #include BZ_NAMESPACE(blitz) template class TinyVector; /** This metaprogram returns the number of bits necessary to fit the specified number. The metaprogram result for I is obtained as _bz_meta_bitwidth::width. */ template struct _bz_meta_bitwidth { static const size_t width = _bz_meta_bitwidth<(I>>1), L+1>::width; }; template struct _bz_meta_bitwidth<0,L> { static const size_t width = L; }; /** Helper class that defines the width of the simd instructions for a given type. It also defines a type that is a TinyVector of the appropriate length to fill the simd width. This is used as the "evaluation type" to facilitate automatic vectorization. Because TinyVectors are aligned on BZ_SIMD_WIDTH, an array of vecType will be dense in memory, which is required to reinterpret an array of T to an array of vecType. \todo How do we check that the type fits evenly into the simd width? */ template class simdTypes { public: /// SIMD width of type in bytes (sizeof(T) if simd width does not /// fit a T) static const size_t byteWidth = BZ_SIMD_WIDTH>sizeof(T) ? BZ_SIMD_WIDTH : sizeof(T); /// SIMD width of types in number of elements. static const size_t vecWidth = BZ_SIMD_WIDTH>sizeof(T) ? BZ_SIMD_WIDTH/sizeof(T) : 1; /// TinyVector type of T that fills the simd width. typedef TinyVector vecType; /** Test if a pointer to T is simd aligned. */ static inline bool isVectorAligned(const T* restrict pointer) { return (uintptr_t)((void*)pointer) % BZ_SIMD_WIDTH == 0; } /** Return number of elements from pointer to next simd width boundary. This is used to figure out how many scalar operations need to be done before beginning vectorized operations. */ static inline diffType offsetToAlignment(const T* restrict pointer) { const uintptr_t m = (uintptr_t)((void*)pointer) & (byteWidth-1); return m ? (byteWidth - m)/sizeof(T) : 0; } /** Return a length which has been padded to next larger even SIMD width. */ static inline size_t paddedLength(size_t length) { return (length & (vecWidth-1)) ? (length & ~(vecWidth-1)) + vecWidth : length; }; }; /** General function just forwards to the simdTypes class. */ template inline bool isVectorAligned(const T* restrict pointer) { return simdTypes::isVectorAligned(pointer); } BZ_NAMESPACE_END #endif