xref: /aosp_15_r20/external/eigen/test/dynalloc.cpp (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
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