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