00001
00016 #ifndef _DLR_SUBARRAY1D_H_
00017 #define _DLR_SUBARRAY1D_H_
00018
00019 #include <dlrNumeric/array1D.h>
00020 #include <dlrNumeric/slice.h>
00021
00022 namespace dlr {
00023
00024 namespace numeric {
00025
00036 template <class Type>
00037 class SubArray1D {
00038 public:
00039
00046 SubArray1D(const Array1D<Type>& source);
00047
00048
00060 SubArray1D(const Array1D<Type>& source, const Slice& slice0);
00061
00062
00071 SubArray1D(const SubArray1D<Type> &other);
00072
00073
00077 virtual
00078 ~SubArray1D() {}
00079
00080
00089 operator Array1D<Type>() const;
00090
00091
00099 inline size_t
00100 size() const {return this->m_size;}
00101
00102
00111 inline size_t
00112 start() const {return this->m_start;}
00113
00114
00123 inline size_t
00124 stride() const {return this->m_stride;}
00125
00126
00135 inline Array1D<Type>
00136 getArray() const {return this->m_source;}
00137
00138
00150 SubArray1D<Type>&
00151 operator=(const SubArray1D<Type>& other);
00152
00153
00165 SubArray1D<Type>&
00166 operator=(Type value);
00167
00179 SubArray1D<Type>&
00180 operator+=(const SubArray1D<Type>& other);
00181
00193 SubArray1D<Type>&
00194 operator-=(const SubArray1D<Type>& other);
00195
00196 private:
00205 inline int
00206 abs(int argument) {return (argument >= 0) ? argument : -argument;}
00207
00208 inline void
00209 checkArray1DSize(const Array1D<Type>& other) const;
00210
00211 inline void
00212 checkSubArray1DSize(const SubArray1D<Type>& other) const;
00213
00214 SubArray1D<Type>&
00215 copy(const SubArray1D<Type>& other);
00216
00217 Array1D<Type> m_source;
00218 int m_start;
00219 int m_stop;
00220 int m_stride;
00221 size_t m_size;
00222 };
00223
00224
00225
00226
00238 template <class Type>
00239 inline SubArray1D<Type>
00240 subArray(const Array1D<Type>& source) {return SubArray1D<Type>(source);}
00241
00242
00262 template <class Type>
00263 inline SubArray1D<Type>
00264 subArray(const Array1D<Type>& source,
00265 const Slice& rowSlice) {
00266 return SubArray1D<Type>(source, rowSlice);
00267 }
00268
00269
00280 template <class Type>
00281 std::ostream&
00282 operator<<(std::ostream& stream, const SubArray1D<Type>& subArray0);
00283
00284 }
00285
00286 }
00287
00288
00289
00290
00291 namespace dlr {
00292
00293 using numeric::SubArray1D;
00294 using numeric::subArray;
00295
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 #include <cmath>
00305 #include <dlrCommon/stridedPointer.h>
00306
00307 namespace dlr {
00308
00309 namespace numeric {
00310
00311 template <class Type>
00312 SubArray1D<Type>::
00313 SubArray1D(const Array1D<Type>& source)
00314 : m_source(source),
00315 m_start(0),
00316 m_stop(source.size()),
00317 m_stride(1),
00318 m_size(source.size())
00319 {
00320
00321 }
00322
00323 template <class Type>
00324 SubArray1D<Type>::
00325 SubArray1D(const Array1D<Type>& source, const Slice& slice0)
00326 : m_source(source),
00327 m_start(slice0.start()),
00328 m_stop(slice0.stop()),
00329 m_stride(slice0.stride()),
00330 m_size(0)
00331 {
00332
00333
00334
00335 if((this->m_stop == 0) && (this->m_stride > 0)) {
00336 this->m_stop = source.size();
00337 }
00338
00339
00340 while(this->m_start < 0) {
00341 this->m_start += source.size();
00342 }
00343 while(this->m_stop < 0) {
00344 this->m_stop += source.size();
00345 }
00346
00347
00348 this->m_size = ((this->m_stop - this->m_start)
00349 / this->m_stride);
00350 if(this->m_size < 0) {
00351 this->m_size = 0;
00352 } else {
00353
00354 if(this->abs(this->m_size * this->m_stride)
00355 < this->abs(this->m_stop - this->m_start)) {
00356 ++this->m_size;
00357 }
00358 }
00359
00360
00361 this->checkArray1DSize(source);
00362 }
00363
00364
00365 template <class Type>
00366 SubArray1D<Type>::
00367 SubArray1D(const SubArray1D<Type> &other)
00368 : m_source(other.m_source),
00369 m_start(other.m_start),
00370 m_stop(other.m_stop),
00371 m_stride(other.m_stride),
00372 m_size(other.m_size)
00373 {
00374
00375 }
00376
00377
00378 template <class Type>
00379 SubArray1D<Type>::operator Array1D<Type>() const
00380 {
00381 Array1D<Type> returnVal(this->size());
00382 subArray(returnVal) = *this;
00383 return returnVal;
00384 }
00385
00386
00387 template <class Type>
00388 SubArray1D<Type>& SubArray1D<Type>::
00389 operator=(const SubArray1D<Type>& other)
00390 {
00391 this->checkSubArray1DSize(other);
00392 return this->copy(other);
00393 }
00394
00395
00396 template <class Type>
00397 SubArray1D<Type>& SubArray1D<Type>::
00398 operator=(Type value)
00399 {
00400 StridedPointer<Type> outPtr0(this->m_source.data(m_start), this->m_stride);
00401 StridedPointer<Type> outPtr1 = outPtr0 + this->size();
00402 std::fill(outPtr0, outPtr1, value);
00403 return *this;
00404 }
00405
00406
00407 template <class Type>
00408 SubArray1D<Type>& SubArray1D<Type>::
00409 operator+=(const SubArray1D<Type>& other)
00410 {
00411 this->checkSubArray1DSize(other);
00412 StridedPointer<Type> thisDataPtr0(this->m_source.data(this->m_start),
00413 this->m_stride);
00414 StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->size();
00415 StridedPointer<const Type>
00416 otherDataPtr0(other.m_source.data(other.m_start), other.m_stride);
00417 std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00418 std::plus<Type>());
00419 return *this;
00420 }
00421
00422
00423 template <class Type>
00424 SubArray1D<Type>& SubArray1D<Type>::
00425 operator-=(const SubArray1D<Type>& other)
00426 {
00427 this->checkSubArray1DSize(other);
00428 StridedPointer<Type> thisDataPtr0(this->m_source.data(this->m_start),
00429 this->m_stride);
00430 StridedPointer<Type> thisDataPtr1 = thisDataPtr0 + this->size();
00431 StridedPointer<const Type>
00432 otherDataPtr0(other.m_source.data(other.m_start), other.m_stride);
00433 std::transform(thisDataPtr0, thisDataPtr1, otherDataPtr0, thisDataPtr0,
00434 std::minus<Type>());
00435 return *this;
00436 }
00437
00438 template <class Type>
00439 inline void SubArray1D<Type>::
00440 checkArray1DSize(const Array1D<Type>& other) const
00441 {
00442 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00443 if((m_start < 0) || (m_start >= static_cast<int>(other.size()))) {
00444 std::ostringstream message;
00445 message << "Invalid start index: " << m_start << std::endl;
00446 DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00447 message.str().c_str());
00448 }
00449 if(m_stride > 0) {
00450 if(m_stop > static_cast<int>(other.size())) {
00451 std::ostringstream message;
00452 message << "Invalid stop index: " << m_stop << std::endl;
00453 DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00454 message.str().c_str());
00455 }
00456 } else if(m_stride < 0) {
00457 if(m_stop < -1) {
00458 std::ostringstream message;
00459 message << "Invalid stop index: " << m_stop << std::endl;
00460 DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00461 message.str().c_str());
00462 }
00463 } else {
00464
00465 DLR_THROW(IndexException, "SubArray1D::checkArray1DSize()",
00466 "Invalid stride: 0");
00467 }
00468 #endif
00469 }
00470
00471
00472 template <class Type>
00473 inline void SubArray1D<Type>::
00474 checkSubArray1DSize(const SubArray1D<Type>& other) const
00475 {
00476 #ifdef _DLRNUMERIC_CHECKBOUNDS_
00477 if(other.size() != this->size()) {
00478 std::ostringstream message;
00479 message << "Size mismatch: " << other.size() << " vs. "
00480 << this->size() << std::endl;
00481 DLR_THROW(IndexException, "SubArray1D::checkSubArray1DSize()",
00482 message.str().c_str());
00483 }
00484 #endif
00485 }
00486
00487
00488 template <class Type>
00489 SubArray1D<Type>& SubArray1D<Type>::
00490 copy(const SubArray1D<Type>& other)
00491 {
00492 StridedPointer<const Type>
00493 inPtr0(other.m_source.data(other.m_start), other.stride());
00494 StridedPointer<const Type> inPtr1 = inPtr0 + other.size();
00495 StridedPointer<Type>
00496 outPtr0(this->m_source.data(this->m_start), this->m_stride);
00497 std::copy(inPtr0, inPtr1, outPtr0);
00498 return *this;
00499 }
00500
00501
00502
00503 template <class Type>
00504 std::ostream& operator<<(std::ostream& stream,
00505 const SubArray1D<Type>& subArray)
00506 {
00507 Array1D<Type> array(subArray.size());
00508 subArray1D(array) = subArray;
00509 stream << "SubArray1D([";
00510 for(int index0 = 0; index < array.size() - 1; ++index0) {
00511 stream << array(index0) << ", ";
00512 }
00513 stream << array(array.size() - 1) << "])";
00514 stream.flush();
00515 return stream;
00516 }
00517
00518 }
00519
00520 }
00521
00522 #endif // #ifdef _DLR_SUBARRAY1D_H_
00523