File: simdtypes.h

package info (click to toggle)
blitz%2B%2B 1%3A0.10-3.2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 13,276 kB
  • ctags: 12,037
  • sloc: cpp: 70,465; sh: 11,116; fortran: 1,510; python: 1,246; f90: 852; makefile: 701
file content (73 lines) | stat: -rw-r--r-- 2,558 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#ifndef BZ_SIMDTYPES_H
#define BZ_SIMDTYPES_H

#include <blitz/blitz.h>
#include <stdint.h>

BZ_NAMESPACE(blitz)

template<class T,int N> 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<I,0>::width. */
template<size_t I, size_t L> struct _bz_meta_bitwidth {
  static const size_t width = _bz_meta_bitwidth<(I>>1), L+1>::width;
};

template<size_t L> 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<typename T> 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<T, vecWidth> 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 <typename T>
inline bool isVectorAligned(const T* restrict pointer) {
  return simdTypes<T>::isVectorAligned(pointer); }


BZ_NAMESPACE_END

#endif