00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. Eigen itself is part of the KDE project. 00003 // 00004 // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com> 00005 // 00006 // Eigen is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 3 of the License, or (at your option) any later version. 00010 // 00011 // Alternatively, you can redistribute it and/or 00012 // modify it under the terms of the GNU General Public License as 00013 // published by the Free Software Foundation; either version 2 of 00014 // the License, or (at your option) any later version. 00015 // 00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY 00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the 00019 // GNU General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Lesser General Public 00022 // License and a copy of the GNU General Public License along with 00023 // Eigen. If not, see <http://www.gnu.org/licenses/>. 00024 00025 #include "main.h" 00026 00027 struct Good1 00028 { 00029 MatrixXd m; // good: m will allocate its own array, taking care of alignment. 00030 Good1() : m(20,20) {} 00031 }; 00032 00033 struct Good2 00034 { 00035 Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be aligned 00036 }; 00037 00038 struct Good3 00039 { 00040 Vector2f m; // good: same reason 00041 }; 00042 00043 struct Bad4 00044 { 00045 Vector2d m; // bad: sizeof(m)%16==0 so alignment is required 00046 }; 00047 00048 struct Bad5 00049 { 00050 Matrix<float, 2, 6> m; // bad: same reason 00051 }; 00052 00053 struct Bad6 00054 { 00055 Matrix<double, 3, 4> m; // bad: same reason 00056 }; 00057 00058 struct Good7 00059 { 00060 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00061 Vector2d m; 00062 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 00063 }; 00064 00065 struct Good8 00066 { 00067 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00068 float f; // try the f at first -- the EIGEN_ALIGN_128 attribute of m should make that still work 00069 Matrix4f m; 00070 }; 00071 00072 struct Good9 00073 { 00074 Matrix<float,2,2,DontAlign> m; // good: no alignment requested 00075 float f; 00076 }; 00077 00078 template<bool Align> struct Depends 00079 { 00080 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align) 00081 Vector2d m; 00082 float f; 00083 }; 00084 00085 template<typename T> 00086 void check_unalignedassert_good() 00087 { 00088 T *x, *y; 00089 x = new T; 00090 delete x; 00091 y = new T[2]; 00092 delete[] y; 00093 } 00094 00095 #if EIGEN_ARCH_WANTS_ALIGNMENT 00096 template<typename T> 00097 void check_unalignedassert_bad() 00098 { 00099 float buf[sizeof(T)+16]; 00100 float *unaligned = buf; 00101 while((reinterpret_cast<std::size_t>(unaligned)&0xf)==0) ++unaligned; // make sure unaligned is really unaligned 00102 T *x = ::new(static_cast<void*>(unaligned)) T; 00103 x->~T(); 00104 } 00105 #endif 00106 00107 void unalignedassert() 00108 { 00109 check_unalignedassert_good<Good1>(); 00110 check_unalignedassert_good<Good2>(); 00111 check_unalignedassert_good<Good3>(); 00112 #if EIGEN_ARCH_WANTS_ALIGNMENT 00113 VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad4>()); 00114 VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad5>()); 00115 VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad6>()); 00116 #endif 00117 00118 check_unalignedassert_good<Good7>(); 00119 check_unalignedassert_good<Good8>(); 00120 check_unalignedassert_good<Good9>(); 00121 check_unalignedassert_good<Depends<true> >(); 00122 00123 #if EIGEN_ARCH_WANTS_ALIGNMENT 00124 VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Depends<false> >()); 00125 #endif 00126 } 00127 00128 void test_eigen2_unalignedassert() 00129 { 00130 CALL_SUBTEST(unalignedassert()); 00131 }