1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10 #include "main.h"
11
12 #if EIGEN_MAX_ALIGN_BYTES>0
13 #define ALIGNMENT EIGEN_MAX_ALIGN_BYTES
14 #else
15 #define ALIGNMENT 1
16 #endif
17
18 typedef Matrix<float,8,1> Vector8f;
19
check_handmade_aligned_malloc()20 void check_handmade_aligned_malloc()
21 {
22 for(int i = 1; i < 1000; i++)
23 {
24 char *p = (char*)internal::handmade_aligned_malloc(i);
25 VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
26 // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
27 for(int j = 0; j < i; j++) p[j]=0;
28 internal::handmade_aligned_free(p);
29 }
30 }
31
check_aligned_malloc()32 void check_aligned_malloc()
33 {
34 for(int i = ALIGNMENT; i < 1000; i++)
35 {
36 char *p = (char*)internal::aligned_malloc(i);
37 VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
38 // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
39 for(int j = 0; j < i; j++) p[j]=0;
40 internal::aligned_free(p);
41 }
42 }
43
check_aligned_new()44 void check_aligned_new()
45 {
46 for(int i = ALIGNMENT; i < 1000; i++)
47 {
48 float *p = internal::aligned_new<float>(i);
49 VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
50 // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
51 for(int j = 0; j < i; j++) p[j]=0;
52 internal::aligned_delete(p,i);
53 }
54 }
55
check_aligned_stack_alloc()56 void check_aligned_stack_alloc()
57 {
58 for(int i = ALIGNMENT; i < 400; i++)
59 {
60 ei_declare_aligned_stack_constructed_variable(float,p,i,0);
61 VERIFY(internal::UIntPtr(p)%ALIGNMENT==0);
62 // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
63 for(int j = 0; j < i; j++) p[j]=0;
64 }
65 }
66
67
68 // test compilation with both a struct and a class...
69 struct MyStruct
70 {
71 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
72 char dummychar;
73 Vector8f avec;
74 };
75
76 class MyClassA
77 {
78 public:
79 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
80 char dummychar;
81 Vector8f avec;
82 };
83
check_dynaligned()84 template<typename T> void check_dynaligned()
85 {
86 // TODO have to be updated once we support multiple alignment values
87 if(T::SizeAtCompileTime % ALIGNMENT == 0)
88 {
89 T* obj = new T;
90 VERIFY(T::NeedsToAlign==1);
91 VERIFY(internal::UIntPtr(obj)%ALIGNMENT==0);
92 delete obj;
93 }
94 }
95
check_custom_new_delete()96 template<typename T> void check_custom_new_delete()
97 {
98 {
99 T* t = new T;
100 delete t;
101 }
102
103 {
104 std::size_t N = internal::random<std::size_t>(1,10);
105 T* t = new T[N];
106 delete[] t;
107 }
108
109 #if EIGEN_MAX_ALIGN_BYTES>0
110 {
111 T* t = static_cast<T *>((T::operator new)(sizeof(T)));
112 (T::operator delete)(t, sizeof(T));
113 }
114
115 {
116 T* t = static_cast<T *>((T::operator new)(sizeof(T)));
117 (T::operator delete)(t);
118 }
119 #endif
120 }
121
test_dynalloc()122 void test_dynalloc()
123 {
124 // low level dynamic memory allocation
125 CALL_SUBTEST(check_handmade_aligned_malloc());
126 CALL_SUBTEST(check_aligned_malloc());
127 CALL_SUBTEST(check_aligned_new());
128 CALL_SUBTEST(check_aligned_stack_alloc());
129
130 for (int i=0; i<g_repeat*100; ++i)
131 {
132 CALL_SUBTEST( check_custom_new_delete<Vector4f>() );
133 CALL_SUBTEST( check_custom_new_delete<Vector2f>() );
134 CALL_SUBTEST( check_custom_new_delete<Matrix4f>() );
135 CALL_SUBTEST( check_custom_new_delete<MatrixXi>() );
136 }
137
138 // check static allocation, who knows ?
139 #if EIGEN_MAX_STATIC_ALIGN_BYTES
140 for (int i=0; i<g_repeat*100; ++i)
141 {
142 CALL_SUBTEST(check_dynaligned<Vector4f>() );
143 CALL_SUBTEST(check_dynaligned<Vector2d>() );
144 CALL_SUBTEST(check_dynaligned<Matrix4f>() );
145 CALL_SUBTEST(check_dynaligned<Vector4d>() );
146 CALL_SUBTEST(check_dynaligned<Vector4i>() );
147 CALL_SUBTEST(check_dynaligned<Vector8f>() );
148 }
149
150 {
151 MyStruct foo0; VERIFY(internal::UIntPtr(foo0.avec.data())%ALIGNMENT==0);
152 MyClassA fooA; VERIFY(internal::UIntPtr(fooA.avec.data())%ALIGNMENT==0);
153 }
154
155 // dynamic allocation, single object
156 for (int i=0; i<g_repeat*100; ++i)
157 {
158 MyStruct *foo0 = new MyStruct(); VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
159 MyClassA *fooA = new MyClassA(); VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
160 delete foo0;
161 delete fooA;
162 }
163
164 // dynamic allocation, array
165 const int N = 10;
166 for (int i=0; i<g_repeat*100; ++i)
167 {
168 MyStruct *foo0 = new MyStruct[N]; VERIFY(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
169 MyClassA *fooA = new MyClassA[N]; VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
170 delete[] foo0;
171 delete[] fooA;
172 }
173 #endif
174
175 }
176