00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #ifndef _EXMAT_SIMDCONTAINER_H
00031 #define _EXMAT_SIMDCONTAINER_H
00032
00033
00034 #ifdef _MSC_VER
00035 # pragma warning( push )
00036 # pragma warning( disable : 4201 4786 )
00037 #endif // _MSC_VER
00038
00039 #include <iterator>
00040 #include "../ErrorCheck.h"
00041 #include "../Iterators.h"
00042 #include "../Allocator.h"
00043 #include "SIMDAlignment.h"
00044
00045 #include "../Assignment.h"
00046
00047
00048 namespace exmat {
00049
00050
00052 namespace SIMD {
00053
00054
00056 template<typename T>
00057 struct SIMD_UNIT_Chooser {
00058 typedef NullTag RET;
00059 };
00060
00061 #if EXMAT_SIMD_FLOAT
00062 template<>
00063 struct SIMD_UNIT_Chooser<float> {
00064 enum {
00065 ALIGN = EXMAT_SIMD_FLOAT_ALIGN
00066 };
00067 typedef EXMAT_SIMD_FLOAT_UNIT RET;
00068 };
00069 #endif // EXMAT_SIMD_FLOAT
00070
00071 #if EXMAT_SIMD_DOUBLE
00072 template<>
00073 struct SIMD_UNIT_Chooser<double> {
00074 enum {
00075 ALIGN = EXMAT_SIMD_DOUBLE_ALIGN
00076 };
00077 typedef EXMAT_SIMD_DOUBLE_UNIT RET;
00078 };
00079 #endif // EXMAT_SIMD_DOUBLE
00080
00081
00083 template<int ROWS_, int COLS_, typename T=float>
00084 struct EXMAT_TYPE_ALIGN_PREFIX(EXMAT_SIMD_DEFAULT_ALIGN)
00085 SCon_RM : public SIMDTag, public RowMajorTag
00086 {
00087 typedef typename SIMD_UNIT_Chooser<T>::RET UNIT;
00088 enum {
00089 ALIGNED = true,
00090 ROWS = ROWS_,
00091 COLS = COLS_,
00093 Align = SIMD_UNIT_Chooser<T>::ALIGN,
00095 nElePerUnit = sizeof(UNIT)/sizeof(T),
00097 nUnitPerRow = (COLS+nElePerUnit-1)/nElePerUnit,
00099 nUnit = nUnitPerRow*ROWS,
00100
00101 rPadding = (COLS%nElePerUnit == 0) ? 0 : nElePerUnit-COLS%nElePerUnit,
00102 cPadding = 0,
00104 rStride = COLS+rPadding,
00105 cStride = ROWS,
00107 nTotalEle = ROWS*(COLS+rPadding),
00108
00109 IsLinear = true,
00110 IsLinearRecursive = true,
00111 TNOP = 0,
00112 ENOP = 0,
00113 EXPLevel = 0
00114 };
00115
00116 union {
00117 UNIT unitData[nUnit];
00118 T data[ROWS][COLS+rPadding];
00119 struct { T x, y, z, w; };
00120 };
00121
00122 EXMAT_INLINE2 SCon_RM() {
00123 ALIGNMENT_CHECK(sizeof(UNIT));
00124 }
00125
00126
00127
00128 EXMAT_INLINE2 T& setAt(size_t i)
00129 { return *(&data[0][0]+i+i*rPadding/COLS); }
00130 EXMAT_INLINE2 const T& getAt(size_t i) const
00131 { return *(&data[0][0]+i+i*rPadding/COLS); }
00132 EXMAT_INLINE2 T& setAt(size_t i, size_t j)
00133 { return data[i][j]; }
00134 EXMAT_INLINE2 const T& getAt(size_t i, size_t j) const
00135 { return data[i][j]; }
00136 EXMAT_INLINE2 UNIT& setUnitAt(size_t i)
00137 { return unitData[i]; }
00138 EXMAT_INLINE2 const UNIT& getUnitAt(size_t i) const
00139 { return unitData[i]; }
00140 } EXMAT_TYPE_ALIGN_SUFFIX(EXMAT_SIMD_DEFAULT_ALIGN);
00141
00142
00144 template<int ROWS_, int COLS_, typename T=float>
00145 struct EXMAT_TYPE_ALIGN_PREFIX(EXMAT_SIMD_DEFAULT_ALIGN)
00146 SCon_CM : public SIMDTag, public ColMajorTag
00147 {
00148 typedef typename SIMD_UNIT_Chooser<T>::RET UNIT;
00149 enum {
00150 ALIGNED = true,
00151 ROWS = ROWS_,
00152 COLS = COLS_,
00154 Align = SIMD_UNIT_Chooser<T>::ALIGN,
00156 nElePerUnit = sizeof(UNIT)/sizeof(T),
00158 nUnitPerCol = (ROWS+nElePerUnit-1)/nElePerUnit,
00160 nUnit = nUnitPerCol*COLS,
00161 rPadding = 0,
00163 cPadding = (ROWS%nElePerUnit == 0) ? 0 : nElePerUnit-ROWS%nElePerUnit,
00164 rStride = COLS,
00166 cStride = ROWS+cPadding,
00168 nTotalEle = COLS*(ROWS+cPadding),
00169
00170 IsLinear = true,
00171 IsLinearRecursive = true,
00172 TNOP = 0,
00173 ENOP = 0,
00174 EXPLevel = 0
00175 };
00176
00177 union {
00178 UNIT unitData[nUnit];
00179 T data[COLS][ROWS+cPadding];
00180 struct { T x, y, z, w; };
00181 };
00182
00183 EXMAT_INLINE2 SCon_CM() {
00184 ALIGNMENT_CHECK(sizeof(UNIT));
00185 }
00186
00187
00188
00189 EXMAT_INLINE2 T& setAt(size_t i)
00190 { return *(&data[0][0]+i+i*cPadding/ROWS); }
00191 EXMAT_INLINE2 const T& getAt(size_t i) const
00192 { return *(&data[0][0]+i+i*cPadding/ROWS); }
00193 EXMAT_INLINE2 T& setAt(size_t i, size_t j)
00194 { return data[j][i]; }
00195 EXMAT_INLINE2 const T& getAt(size_t i, size_t j) const
00196 { return data[j][i]; }
00197 EXMAT_INLINE2 UNIT& setUnitAt(size_t i)
00198 { return unitData[i]; }
00199 EXMAT_INLINE2 const UNIT& getUnitAt(size_t i) const
00200 { return unitData[i]; }
00201 } EXMAT_TYPE_ALIGN_SUFFIX(EXMAT_SIMD_DEFAULT_ALIGN);
00202
00203
00205 template<int ROWS_, int COLS_, typename T=float>
00206 struct SConCA_RM : public SIMDTag, public RowMajorTag
00207 {
00208 typedef typename SIMD_UNIT_Chooser<T>::RET UNIT;
00209 enum {
00210 ALIGNED = true,
00211 ROWS = ROWS_,
00212 COLS = COLS_,
00214 Align = SIMD_UNIT_Chooser<T>::ALIGN,
00216 nElePerUnit = sizeof(UNIT)/sizeof(T),
00218 nUnitPerRow = (COLS+nElePerUnit-1)/nElePerUnit,
00220 nUnit = nUnitPerRow*ROWS,
00221
00222 rPadding = (COLS%nElePerUnit == 0) ? 0 : nElePerUnit-COLS%nElePerUnit,
00223 cPadding = 0,
00225 rStride = COLS+rPadding,
00226 cStride = ROWS,
00228 nTotalEle = ROWS*(COLS+rPadding),
00229
00230 IsLinear = true,
00231 IsLinearRecursive = true,
00232 TNOP = 0,
00233 ENOP = 0,
00234 EXPLevel = 0
00235 };
00236
00237
00238 #if EXMAT_VC2005
00239 UNIT* refPtr;
00240 # define INIT_REF \
00241 refPtr( (UNIT*)aligned_stack_allocate(sizeof(UNIT)*nUnit) ), \
00242 unitData( (UNIT (&)[nUnit]) *refPtr), \
00243 data((T (&)[ROWS][COLS+rPadding])(unitData[0]))
00244 #else
00245 # define INIT_REF \
00246 unitData( (UNIT (&)[nUnit]) *(UNIT*)aligned_stack_allocate(sizeof(UNIT)*nUnit)), \
00247 data((T (&)[ROWS][COLS+rPadding])(unitData[0]))
00248 #endif // EXMAT_VC2005
00249
00250
00251 #ifdef _MSC_VER
00252 union {
00253 #endif
00254
00255 UNIT (&unitData)[nUnit];
00256 T (&data)[ROWS][COLS+rPadding];
00257 #ifdef _MSC_VER
00258 };
00259 #endif
00260
00261 EXMAT_INLINE2 SConCA_RM() : INIT_REF {
00262 ALIGNMENT_CHECK(sizeof(UNIT));
00263 }
00264
00265 #undef INIT_REF
00266
00267 EXMAT_INLINE2 virtual ~SConCA_RM() {
00268 aligned_stack_free();
00269 }
00270
00271
00272
00273 EXMAT_INLINE2 T& setAt(size_t i)
00274 { return *(&data[0][0]+i+i*rPadding/COLS); }
00275 EXMAT_INLINE2 const T& getAt(size_t i) const
00276 { return *(&data[0][0]+i+i*rPadding/COLS); }
00277 EXMAT_INLINE2 T& setAt(size_t i, size_t j)
00278 { return data[i][j]; }
00279 EXMAT_INLINE2 const T& getAt(size_t i, size_t j) const
00280 { return data[i][j]; }
00281 EXMAT_INLINE2 UNIT& setUnitAt(size_t i)
00282 { return unitData[i]; }
00283 EXMAT_INLINE2 const UNIT& getUnitAt(size_t i) const
00284 { return unitData[i]; }
00285 };
00286
00288 template<int ROWS_, int COLS_, typename T=float>
00289 struct SConCA_CM : public SIMDTag, public ColMajorTag
00290 {
00291 typedef typename SIMD_UNIT_Chooser<T>::RET UNIT;
00292 enum {
00293 ALIGNED = true,
00294 ROWS = ROWS_,
00295 COLS = COLS_,
00297 Align = SIMD_UNIT_Chooser<T>::ALIGN,
00299 nElePerUnit = sizeof(UNIT)/sizeof(T),
00301 nUnitPerCol = (ROWS+nElePerUnit-1)/nElePerUnit,
00303 nUnit = nUnitPerCol*COLS,
00304 rPadding = 0,
00306 cPadding = (ROWS%nElePerUnit == 0) ? 0 : nElePerUnit-ROWS%nElePerUnit,
00307 rStride = COLS,
00309 cStride = ROWS+cPadding,
00311 nTotalEle = COLS*(ROWS+cPadding),
00312
00313 IsLinear = true,
00314 IsLinearRecursive = true,
00315 TNOP = 0,
00316 ENOP = 0,
00317 EXPLevel = 0
00318 };
00319
00320
00321 #if EXMAT_VC2005
00322 UNIT* refPtr;
00323 # define INIT_REF \
00324 refPtr( (UNIT*)aligned_stack_allocate(sizeof(UNIT)*nUnit) ), \
00325 unitData( (UNIT (&)[nUnit]) *refPtr), \
00326 data((T (&)[COLS][ROWS+cPadding])(unitData[0]))
00327 #else
00328 # define INIT_REF \
00329 unitData( (UNIT (&)[nUnit]) *(UNIT*)aligned_stack_allocate(sizeof(UNIT)*nUnit)), \
00330 data((T (&)[COLS][ROWS+cPadding])(unitData[0]))
00331 #endif // EXMAT_VC2005
00332
00333
00334 #ifdef _MSC_VER
00335 union {
00336 #endif
00337 UNIT (&unitData)[nUnit];
00338 T (&data)[COLS][ROWS+cPadding];
00339 #ifdef _MSC_VER
00340 };
00341 #endif
00342
00343 EXMAT_INLINE2 SConCA_CM() : INIT_REF {
00344 ALIGNMENT_CHECK(sizeof(UNIT));
00345 }
00346
00347 #undef INIT_REF
00348
00349 EXMAT_INLINE2 virtual ~SConCA_CM() {
00350 aligned_stack_free();
00351 }
00352
00353
00354
00355 EXMAT_INLINE2 T& setAt(size_t i)
00356 { return *(&data[0][0]+i+i*cPadding/ROWS); }
00357 EXMAT_INLINE2 const T& getAt(size_t i) const
00358 { return *(&data[0][0]+i+i*cPadding/ROWS); }
00359 EXMAT_INLINE2 T& setAt(size_t i, size_t j)
00360 { return data[j][i]; }
00361 EXMAT_INLINE2 const T& getAt(size_t i, size_t j) const
00362 { return data[j][i]; }
00363 EXMAT_INLINE2 UNIT& setUnitAt(size_t i)
00364 { return unitData[i]; }
00365 EXMAT_INLINE2 const UNIT& getUnitAt(size_t i) const
00366 { return unitData[i]; }
00367 };
00368
00369
00371 template<int R, int C, typename T>
00372 struct SConCHooser {
00373 typedef typename IF<
00374 C == 1,
00375
00376 #if EXMAT_VC6
00377 SConCA_CM<R,C,T>,
00378 SConCA_RM<R,C,T>
00379 #else
00380 SCon_CM<R,C,T>,
00381 SCon_RM<R,C,T>
00382 #endif // EXMAT_VC6
00383 >::RET RET;
00384 };
00385
00386
00389 template<int ROWS_, int COLS_, typename T=float>
00390 struct EXMAT_TYPE_ALIGN_PREFIX(EXMAT_SIMD_DEFAULT_ALIGN)
00391 SCon : public SConCHooser<ROWS_,COLS_,T>::RET
00392 {
00393 typedef typename SConCHooser<ROWS_,COLS_,T>::RET super_type;
00394 typedef typename super_type::UNIT SIMD_unit_type;
00395 typedef T value_type;
00396 typedef value_type& reference;
00397 typedef const value_type& const_reference;
00398 typedef value_type* row_type;
00399 typedef const value_type* const_row_type;
00400 typedef NullTag col_type;
00401 typedef size_t index_type;
00402 typedef typename Loki::TypeTraits<value_type>::ParameterType param_type;
00403 typedef typename Loki::TypeTraits<const value_type>::ParameterType const_param_type;
00404 typedef NullTag exp_tag;
00405
00406 typedef SCon<ROWS_,COLS_,T> self_type;
00407 typedef self_type rep_type;
00408 typedef mat_iterator<self_type> iterator;
00409 typedef const_mat_iterator<self_type> const_iterator;
00410
00411 #if EXMAT_USING_MEMVAR
00412 using super_type::data;
00413 #endif // EXMAT_USING_MEMVAR
00414
00415 enum {
00416 ROWS = ROWS_,
00417 COLS = COLS_,
00418 nTotalEle = super_type::nTotalEle,
00419 nUnit = super_type::nUnit,
00420 rPadding = super_type::rPadding,
00421 cPadding = super_type::cPadding,
00422 rStride = super_type::rStride,
00423 cStride = super_type::cStride
00424 };
00425
00426 EXMAT_INLINE2 SCon() {
00427
00428
00429 if(rPadding > 0 || cPadding > 0)
00430 memset(&(this->data[0][0]), 0, sizeof(value_type)*nTotalEle);
00431 }
00432
00434 EXMAT_INLINE2 SCon(const self_type& x) {
00435 exmat::PNS::Assign_FullUnRollSIMD(*this, x);
00436 }
00437
00438 EXMAT_INLINE2 explicit SCon(const value_type s) {
00439 SIMD_unit_type scalar = Intrinsics::load1_p(&s);
00440 for(int i=0; i<nUnit; ++i)
00441 this->unitData[i] = scalar;
00442 }
00443
00444 EXMAT_INLINE2 self_type& operator=(const self_type& x) {
00445 exmat::PNS::Assign_FullUnRollSIMD(*this, x);
00446 return *this;
00447 }
00448
00449 EXMAT_INLINE2 self_type& operator=(const value_type s) {
00450 SIMD_unit_type scalar = Intrinsics::load1_p(&s);
00451 for(int i=0; i<nUnit; ++i)
00452 this->unitData[i] = scalar;
00453 return *this;
00454 }
00455
00456
00457
00458 EXMAT_INLINE2 iterator begin()
00459 { return iterator(*this, 0, 0); }
00460 EXMAT_INLINE2 const_iterator begin() const
00461 { return const_iterator(*this, 0, 0); }
00462 EXMAT_INLINE2 iterator end()
00463 { return iterator(*this, rows(), 0); }
00464 EXMAT_INLINE2 const_iterator end() const
00465 { return const_iterator(*this, rows(), 0); }
00466
00467
00468 EXMAT_INLINE2 value_type* getRawData()
00469 { return &data[0][0]; }
00470
00471
00472 EXMAT_INLINE2 T* operator[] (size_t i)
00473 { return &data[i][0]; }
00474 EXMAT_INLINE2 const T* operator[] (size_t i) const
00475 { return &data[i][0]; }
00476
00477
00478 EXMAT_INLINE2 size_t size() const { return ROWS*COLS; }
00479 EXMAT_INLINE2 size_t rows() const { return ROWS; }
00480 EXMAT_INLINE2 size_t cols() const { return COLS; }
00481
00482 EXMAT_INLINE2 size_t rstride() const
00483 { return rStride; }
00484 EXMAT_INLINE2 size_t exstride() const
00485 { return rPadding; }
00486 } EXMAT_TYPE_ALIGN_SUFFIX(EXMAT_SIMD_DEFAULT_ALIGN);
00487
00489 template<class Rep>
00490 struct SSCon : public Rep
00491 {
00492 typedef SSCon<Rep> self_type;
00493
00494 typedef self_type rep_type;
00495 typedef Rep super_type;
00496
00497 enum {
00498 IsLinear = Rep::IsLinear,
00499 IsLinearRecursive = Rep::IsLinearRecursive
00500 };
00501
00503 EXMAT_INLINE2 SSCon() : Rep() {}
00504
00506
00507 template<typename T1>
00508 EXMAT_INLINE2 SSCon(T1& t1) : Rep(t1) {}
00509 template<typename T1, typename T2>
00510 EXMAT_INLINE2 SSCon(T1& t1, T2& t2) : Rep(t1, t2) {}
00511 template<typename T1, typename T2, typename T3>
00512 EXMAT_INLINE2 SSCon(T1& t1, T2& t2, T3& t3) : Rep(t1, t2, t3) {}
00513 #if !EXMAT_VC6 && !EXMAT_VC7
00514 template<typename T1, typename T2>
00515 EXMAT_INLINE2 SSCon(const T1& t1, ScalarCon<T2> t2) : Rep(t1, t2) {}
00516 template<typename T1, typename T2>
00517 EXMAT_INLINE2 SSCon(ScalarCon<T1> t1, const T2& t2) : Rep(t1, t2) {}
00518 #endif // HAVE_PARTIAL_SPECIALIZATION
00519
00520
00522 template<typename T1> EXMAT_INLINE2
00523 SSCon& operator=(const T1& t1) {
00524 (*static_cast<Rep*>(this)) = t1;
00525 return *this;
00526 }
00527 };
00528
00529
00530 };
00531
00532
00537
00538
00539 }
00540
00541 #ifdef _MSC_VER
00542 # pragma warning( pop )
00543 #endif // _MSC_VER
00544
00545 #endif // _EXMAT_SIMDCONTAINER_H