source: XIOS/dev/dev_olga/src/extern/blitz/include/blitz/simdtypes.h @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 2.5 KB
Line 
1#ifndef BZ_SIMDTYPES_H
2#define BZ_SIMDTYPES_H
3
4#include <blitz/blitz.h>
5#include <stdint.h>
6
7BZ_NAMESPACE(blitz)
8
9template<class T,int N> class TinyVector;
10
11/** This metaprogram returns the number of bits necessary to fit the
12    specified number. The metaprogram result for I is obtained as
13    _bz_meta_bitwidth<I,0>::width. */
14template<size_t I, size_t L> struct _bz_meta_bitwidth {
15  static const size_t width = _bz_meta_bitwidth<(I>>1), L+1>::width;
16};
17
18template<size_t L> struct _bz_meta_bitwidth<0,L> {
19  static const size_t width = L;
20};
21
22
23/** Helper class that defines the width of the simd instructions for a
24    given type. It also defines a type that is a TinyVector of the
25    appropriate length to fill the simd width. This is used as the
26    "evaluation type" to facilitate automatic vectorization. Because
27    TinyVectors are aligned on BZ_SIMD_WIDTH, an array of vecType will
28    be dense in memory, which is required to reinterpret an array of T
29    to an array of vecType. \todo How do we check that the type fits
30    evenly into the simd width? */
31template<typename T> class simdTypes {
32public:
33  /// SIMD width of type in bytes (sizeof(T) if simd width does not
34  /// fit a T)
35  static const size_t byteWidth = 
36    BZ_SIMD_WIDTH>sizeof(T) ? BZ_SIMD_WIDTH : sizeof(T);
37
38  /// SIMD width of types in number of elements.
39  static const size_t vecWidth =
40    BZ_SIMD_WIDTH>sizeof(T) ? BZ_SIMD_WIDTH/sizeof(T) : 1;
41
42  /// TinyVector type of T that fills the simd width.
43  typedef TinyVector<T, vecWidth> vecType;
44
45  /** Test if a pointer to T is simd aligned. */
46  static inline bool isVectorAligned(const T* restrict pointer)
47  { return (uintptr_t)((void*)pointer) % BZ_SIMD_WIDTH == 0; } 
48
49  /** Return number of elements from pointer to next simd width
50      boundary. This is used to figure out how many scalar operations
51      need to be done before beginning vectorized operations. */
52  static inline diffType offsetToAlignment(const T* restrict pointer) { 
53    const uintptr_t m = (uintptr_t)((void*)pointer) & (byteWidth-1);
54    return m ? (byteWidth - m)/sizeof(T) : 0;
55} 
56
57  /** Return a length which has been padded to next larger even SIMD
58      width. */
59  static inline size_t paddedLength(size_t length) {
60    return (length & (vecWidth-1)) ? 
61      (length & ~(vecWidth-1)) + vecWidth : length;
62  };
63};
64
65/** General function just forwards to the simdTypes class. */
66template <typename T>
67inline bool isVectorAligned(const T* restrict pointer) {
68  return simdTypes<T>::isVectorAligned(pointer); }
69
70
71BZ_NAMESPACE_END
72
73#endif
Note: See TracBrowser for help on using the repository browser.