-
Notifications
You must be signed in to change notification settings - Fork 18
/
align.h
158 lines (133 loc) · 3.19 KB
/
align.h
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#ifndef __align_h__
#define __align_h__ 1
#ifndef HAVE_POSIX_MEMALIGN
#ifdef __GLIBC_PREREQ
#if __GLIBC_PREREQ(2,3)
#define HAVE_POSIX_MEMALIGN
#endif
#else
#ifdef _POSIX_SOURCE
#define HAVE_POSIX_MEMALIGN
#endif
#endif
#endif
#ifdef __Array_h__
namespace Array {
static const array1<Complex> NULL1;
static const array2<Complex> NULL2;
static const array3<Complex> NULL3;
}
#else
#ifdef HAVE_POSIX_MEMALIGN
#ifdef _AIX
extern "C" int posix_memalign(void **memptr, size_t alignment, size_t size);
#endif
#else
namespace Array {
// Adapted from FFTW aligned malloc/free. Assumes that malloc is at least
// sizeof(void*)-aligned. Allocated memory must be freed with free0.
inline int posix_memalign0(void **memptr, size_t alignment, size_t size)
{
if(alignment % sizeof (void *) != 0 || (alignment & (alignment - 1)) != 0)
return EINVAL;
void *p0=malloc(size+alignment);
if(!p0) return ENOMEM;
void *p=(void *)(((size_t) p0+alignment)&~(alignment-1));
*((void **) p-1)=p0;
*memptr=p;
return 0;
}
inline void free0(void *p)
{
if(p) free(*((void **) p-1));
}
}
#endif
namespace Array {
template<class T>
inline void newAlign(T *&v, size_t len, size_t align)
{
void *mem=NULL;
const char *invalid="Invalid alignment requested";
const char *nomem="Memory limits exceeded";
#ifdef HAVE_POSIX_MEMALIGN
int rc=posix_memalign(&mem,align,len*sizeof(T));
#else
int rc=posix_memalign0(&mem,align,len*sizeof(T));
#endif
if(rc == EINVAL) std::cerr << invalid << std::endl;
if(rc == ENOMEM) std::cerr << nomem << std::endl;
v=(T *) mem;
for(size_t i=0; i < len; i++) new(v+i) T;
}
template<class T>
inline void deleteAlign(T *v, size_t len)
{
for(size_t i=len; i-- > 0;) v[i].~T();
#ifdef HAVE_POSIX_MEMALIGN
free(v);
#else
free0(v);
#endif
}
}
#endif
namespace utils {
extern size_t ALIGNMENT;
inline size_t ceilquotient(size_t a, size_t b)
{
return (a+b-1)/b;
}
inline Complex *ComplexAlign(size_t size)
{
if(size == 0) return NULL;
Complex *v;
Array::newAlign(v,size,ALIGNMENT);
return v;
}
// Return a contiguous array v of n aligned buffers of length size.
// Deallocate with deleteAlign(v[0]); delete [] v;
inline Complex **ComplexAlign(size_t n, size_t size)
{
if(n == 0 || size == 0) return NULL;
Complex **v=new Complex*[n];
size_t Size=ALIGNMENT*ceilquotient(size,ALIGNMENT);
Complex *B=ComplexAlign((n-1)*Size+size);
for(size_t i=0; i < n; ++i)
v[i]=B+i*Size;
return v;
}
inline double *doubleAlign(size_t size)
{
double *v;
Array::newAlign(v,size,ALIGNMENT);
return v;
}
// Return a contiguous array v of n aligned buffers of length size.
// Deallocate with deleteAlign(v[0]); delete [] v;
inline double **doubleAlign(size_t n, size_t size)
{
if(n == 0 || size == 0) return NULL;
double **v=new double*[n];
size_t Size=ALIGNMENT*ceilquotient(size,ALIGNMENT);
double *B=doubleAlign((n-1)*Size+size);
for(size_t i=0; i < n; ++i)
v[i]=B+i*Size;
return v;
}
// Extend n*sizeof(Complex) to a multiple of ALIGNMENT
inline size_t align(size_t n)
{
return ceilquotient(n*sizeof(Complex),ALIGNMENT)*ALIGNMENT/sizeof(Complex);
}
template<class T>
inline void deleteAlign(T *p)
{
#ifdef HAVE_POSIX_MEMALIGN
free(p);
#else
Array::free0(p);
#endif
}
}
#endif