1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1 (at) gmail.com> 5 // Copyright (C) 2015 Gael Guennebaud <gael.guennebaud (at) inria.fr> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #if defined(EIGEN_TEST_PART_1) 12 // default 13 #elif defined(EIGEN_TEST_PART_2) 14 #define EIGEN_MAX_STATIC_ALIGN_BYTES 16 15 #define EIGEN_MAX_ALIGN_BYTES 16 16 #elif defined(EIGEN_TEST_PART_3) 17 #define EIGEN_MAX_STATIC_ALIGN_BYTES 32 18 #define EIGEN_MAX_ALIGN_BYTES 32 19 #elif defined(EIGEN_TEST_PART_4) 20 #define EIGEN_MAX_STATIC_ALIGN_BYTES 64 21 #define EIGEN_MAX_ALIGN_BYTES 64 22 #endif 23 24 #include "main.h" 25 26 typedef Matrix<float, 6,1> Vector6f; 27 typedef Matrix<float, 8,1> Vector8f; 28 typedef Matrix<float, 12,1> Vector12f; 29 30 typedef Matrix<double, 5,1> Vector5d; 31 typedef Matrix<double, 6,1> Vector6d; 32 typedef Matrix<double, 7,1> Vector7d; 33 typedef Matrix<double, 8,1> Vector8d; 34 typedef Matrix<double, 9,1> Vector9d; 35 typedef Matrix<double,10,1> Vector10d; 36 typedef Matrix<double,12,1> Vector12d; 37 38 struct TestNew1 39 { 40 MatrixXd m; // good: m will allocate its own array, taking care of alignment. 41 TestNew1() : m(20,20) {} 42 }; 43 44 struct TestNew2 45 { 46 Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned, 47 // 8-byte alignment is good enough here, which we'll get automatically 48 }; 49 50 struct TestNew3 51 { 52 Vector2f m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned 53 }; 54 55 struct TestNew4 56 { 57 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 58 Vector2d m; 59 float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects 60 }; 61 62 struct TestNew5 63 { 64 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 65 float f; // try the f at first -- the EIGEN_ALIGN_MAX attribute of m should make that still work 66 Matrix4f m; 67 }; 68 69 struct TestNew6 70 { 71 Matrix<float,2,2,DontAlign> m; // good: no alignment requested 72 float f; 73 }; 74 75 template<bool Align> struct Depends 76 { 77 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align) 78 Vector2d m; 79 float f; 80 }; 81 82 template<typename T> 83 void check_unalignedassert_good() 84 { 85 T *x, *y; 86 x = new T; 87 delete x; 88 y = new T[2]; 89 delete[] y; 90 } 91 92 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 93 template<typename T> 94 void construct_at_boundary(int boundary) 95 { 96 char buf[sizeof(T)+256]; 97 size_t _buf = reinterpret_cast<internal::UIntPtr>(buf); 98 _buf += (EIGEN_MAX_ALIGN_BYTES - (_buf % EIGEN_MAX_ALIGN_BYTES)); // make 16/32/...-byte aligned 99 _buf += boundary; // make exact boundary-aligned 100 T *x = ::new(reinterpret_cast<void*>(_buf)) T; 101 x[0].setZero(); // just in order to silence warnings 102 x->~T(); 103 } 104 #endif 105 106 void unalignedassert() 107 { 108 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 109 construct_at_boundary<Vector2f>(4); 110 construct_at_boundary<Vector3f>(4); 111 construct_at_boundary<Vector4f>(16); 112 construct_at_boundary<Vector6f>(4); 113 construct_at_boundary<Vector8f>(EIGEN_MAX_ALIGN_BYTES); 114 construct_at_boundary<Vector12f>(16); 115 construct_at_boundary<Matrix2f>(16); 116 construct_at_boundary<Matrix3f>(4); 117 construct_at_boundary<Matrix4f>(EIGEN_MAX_ALIGN_BYTES); 118 119 construct_at_boundary<Vector2d>(16); 120 construct_at_boundary<Vector3d>(4); 121 construct_at_boundary<Vector4d>(EIGEN_MAX_ALIGN_BYTES); 122 construct_at_boundary<Vector5d>(4); 123 construct_at_boundary<Vector6d>(16); 124 construct_at_boundary<Vector7d>(4); 125 construct_at_boundary<Vector8d>(EIGEN_MAX_ALIGN_BYTES); 126 construct_at_boundary<Vector9d>(4); 127 construct_at_boundary<Vector10d>(16); 128 construct_at_boundary<Vector12d>(EIGEN_MAX_ALIGN_BYTES); 129 construct_at_boundary<Matrix2d>(EIGEN_MAX_ALIGN_BYTES); 130 construct_at_boundary<Matrix3d>(4); 131 construct_at_boundary<Matrix4d>(EIGEN_MAX_ALIGN_BYTES); 132 133 construct_at_boundary<Vector2cf>(16); 134 construct_at_boundary<Vector3cf>(4); 135 construct_at_boundary<Vector2cd>(EIGEN_MAX_ALIGN_BYTES); 136 construct_at_boundary<Vector3cd>(16); 137 #endif 138 139 check_unalignedassert_good<TestNew1>(); 140 check_unalignedassert_good<TestNew2>(); 141 check_unalignedassert_good<TestNew3>(); 142 143 check_unalignedassert_good<TestNew4>(); 144 check_unalignedassert_good<TestNew5>(); 145 check_unalignedassert_good<TestNew6>(); 146 check_unalignedassert_good<Depends<true> >(); 147 148 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 149 if(EIGEN_MAX_ALIGN_BYTES>=16) 150 { 151 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4f>(8)); 152 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(8)); 153 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12f>(8)); 154 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2d>(8)); 155 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(8)); 156 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector6d>(8)); 157 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8d>(8)); 158 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector10d>(8)); 159 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12d>(8)); 160 // Complexes are disabled because the compiler might aggressively vectorize 161 // the initialization of complex coeffs to 0 before we can check for alignedness 162 //VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cf>(8)); 163 VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4i>(8)); 164 } 165 for(int b=8; b<EIGEN_MAX_ALIGN_BYTES; b+=8) 166 { 167 if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(b)); 168 if(b<64) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4f>(b)); 169 if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(b)); 170 if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix2d>(b)); 171 if(b<128) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4d>(b)); 172 //if(b<32) VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cd>(b)); 173 } 174 #endif 175 } 176 177 void test_unalignedassert() 178 { 179 CALL_SUBTEST(unalignedassert()); 180 } 181