Signal/Geometry Processing Library (SPL) 1.1.24 |

Sequence1.hpp
Go to the documentation of this file.
1 // Copyright (c) 2011 Michael D. Adams
2 // All rights reserved.
3
4 // __START_OF_LICENSE__
5 //
6 // Copyright (c) 2015 Michael D. Adams
7 // All rights reserved.
8 //
9 // This file is part of the Signal Processing Library (SPL).
10 //
11 // This program is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 3,
14 // or (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public
22 // License along with this program; see the file LICENSE. If not,
23 // see <http://www.gnu.org/licenses/>.
24 //
25 // __END_OF_LICENSE__
26
32 #ifndef SPL_Sequence1_hpp
33 #define SPL_Sequence1_hpp
34
36 //
38
40 #define SPL_SEQUENCE1_DEBUG
41
43 #define SPL_SEQUENCE1_USE_NEW_CONV
44
45 #if defined(SPL_SEQUENCE1_DEBUG)
46 #define SPL_SEQUENCE1_INLINE
48 #else
49 #define SPL_SEQUENCE1_INLINE inline
51 #endif
52
54 // Header Files.
56
57 #include <SPL/config.hpp>
58 #include <iostream>
59 #include <vector>
60 #include <SPL/Array1.hpp>
61 #include <SPL/math.hpp>
62 #include <SPL/Sequence.hpp>
63
65 //
67
68 namespace SPL {
69
71 // One-Dimensional Sequence Template Class.
73
84 template <class T>
85 class Sequence1
86 {
87 public:
88
90 // Types
92
94 typedef T ElemType;
95
97 typedef typename Array1<T>::ConstIterator ConstIterator;
98
100 typedef typename Array1<T>::Iterator Iterator;
101
103 // Constructors and destructor
105
109 Sequence1();
110
119 Sequence1(int startInd, int size);
120
129 Sequence1(int startInd, int size, const T& value);
130
140 template <class InputIterator>
141 Sequence1(int startInd, int size, InputIterator data);
142
146 Sequence1(const Sequence1& f);
147
152 template <class OtherT>
153 Sequence1(const Sequence1<OtherT>& f);
154
158 Sequence1(const Array1<T>& data);
159
163 Sequence1(int startInd, const Array1<T>& data);
164
168 ~Sequence1();
169
171 // Assignment operators
173
177 Sequence1& operator=(const Sequence1& f);
178
185 template <class OtherT>
186 Sequence1& operator=(const Sequence1<OtherT>& f);
187
189 // Compound assignment operators
191
199 Sequence1& operator+=(const Sequence1& f);
200
208 Sequence1& operator-=(const Sequence1& f);
209
217 Sequence1& operator*=(const Sequence1& f);
218
226 Sequence1& operator/=(const Sequence1& f);
227
234 Sequence1& operator+=(const T& value);
235
242 Sequence1& operator-=(const T& value);
243
250 Sequence1& operator*=(const T& value);
251
258 Sequence1& operator/=(const T& value);
259
261 // Basic queries
263
270 int getStartInd() const;
271
278 int getEndInd() const;
279
287 int getSize() const;
288
292 bool isShared() const;
293
295 // Accessors
297
304 const T& operator()(int i) const;
305
312 T& operator()(int i);
313
315 // Iterators
317
325 ConstIterator begin() const;
326
334 Iterator begin();
335
344 ConstIterator end() const;
345
354 Iterator end();
355
357 // Resizing
359
361 // Get various statistics
363
369 T min() const;
370
376 T max() const;
377
381 T sum() const;
382
384 // Input/ouput
386
388 // Miscellaneous
390
394 Array1<T> getArray() const;
395
399 void swapArray(Array1<T>& data);
400
407 void fill(const T& value);
408
412 Sequence1& translate(int delta);
413
414 private:
415
416 // Do not look at the private members.
417 // Doing so will make your eyes bleed.
418
419 template <class> friend class Sequence1;
420
421 template <class U>
422 friend std::ostream& operator<<(std::ostream& out, const Sequence1<U>&);
423 template <class U>
424 friend Sequence1<U> translate(const Sequence1<U>&, int i);
425
427 typedef Array1<T> Array;
428
430 int startInd_;
431
433 Array data_;
434
435 };
436
438 // Constructors and destructor
440
441 template <class T>
442 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1() : startInd_(0), data_()
443 {
444 }
445
446 template <class T>
447 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(int startInd, int size) :
448 startInd_(startInd), data_(size)
449 {
450 assert(size >= 0);
451 }
452
453 template <class T>
454 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(int startInd, int size,
455 const T& data) : startInd_(startInd), data_(size, data)
456 {
457 assert(size >= 0);
458 }
459
460 template <class T>
461 template <class InputIterator>
462 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(int startInd, int size,
463 InputIterator data) : startInd_(startInd), data_(size, data)
464 {
465 assert(size >= 0);
466 }
467
468 template <class T>
469 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(const Array1<T>& f) :
470 startInd_(0), data_(f)
471 {
472 }
473
474 template <class T>
475 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(int startInd,
476 const Array1<T>& data) : startInd_(startInd), data_(data)
477 {
478 }
479
480 template <class T>
481 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(const Sequence1<T>& f) :
482 startInd_(f.startInd_), data_(f.data_)
483 {
484 }
485
486 template <class T>
487 SPL_SEQUENCE1_INLINE Sequence1<T>::~Sequence1()
488 {
489 }
490
491 template <class T>
492 template <class OtherT>
493 SPL_SEQUENCE1_INLINE Sequence1<T>::Sequence1(const Sequence1<OtherT>& f) :
494 startInd_(f.startInd_), data_(f.data_)
495 {
496 }
497
499 // Assignment operators
501
502 template <class T>
503 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator=(
504 const Sequence1<T>& f)
505 {
506 startInd_ = f.startInd_;
507 data_ = f.data_;
508 return *this;
509 }
510
511 template <class T>
512 template <class OtherT>
513 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator=(
514 const Sequence1<OtherT>& f)
515 {
516 startInd_ = f.startInd_;
517 data_ = f.data_;
518 return *this;
519 }
520
522 // Compound assignment operators
524
525 template <class T>
526 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator+=(
527 const Sequence1<T>& f)
528 {
529 // Ensure that both sequences have the same domain.
530 assert((getSize() == 0 && f.getSize() == 0) ||
531 (getStartInd() == f.getStartInd() && getEndInd() == f.getEndInd()));
532
533 data_ += f.data_;
534 return *this;
535 }
536
537 template <class T>
538 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator-=(
539 const Sequence1<T>& f)
540 {
541 // Ensure that both sequences have the same domain.
542 assert((getSize() == 0 && f.getSize() == 0) ||
543 (getStartInd() == f.getStartInd() && getEndInd() == f.getEndInd()));
544
545 data_ -= f.data_;
546 return *this;
547 }
548
549 template <class T>
550 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator*=(
551 const Sequence1<T>& f)
552 {
553 // Ensure that both sequences have the same domain.
554 assert((getSize() == 0 && f.getSize() == 0) ||
555 (getStartInd() == f.getStartInd() && getEndInd() == f.getEndInd()));
556
557 data_ *= f.data_;
558 return *this;
559 }
560
561 template <class T>
562 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator/=(
563 const Sequence1<T>& f)
564 {
565 // Ensure that both sequences have the same domain.
566 assert((getSize() == 0 && f.getSize() == 0) ||
567 (getStartInd() == f.getStartInd() && getEndInd() == f.getEndInd()));
568
569 data_ /= f.data_;
570 return *this;
571 }
572
573 template <class T>
574 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator+=(const T& value)
575 {
576 data_ += value;
577 return *this;
578 }
579
580 template <class T>
581 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator-=(const T& value)
582 {
583 data_ -= value;
584 return *this;
585 }
586
587 template <class T>
588 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator*=(const T& value)
589 {
590 data_ *= value;
591 return *this;
592 }
593
594 template <class T>
595 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::operator/=(const T& value)
596 {
597 data_ /= value;
598 return *this;
599 }
600
602 // Basic queries
604
605 template <class T>
606 SPL_SEQUENCE1_INLINE int Sequence1<T>::getStartInd() const
607 {
608 return startInd_;
609 }
610
611 template <class T>
612 SPL_SEQUENCE1_INLINE int Sequence1<T>::getEndInd() const
613 {
614 return startInd_ + getSize();
615 }
616
617 template <class T>
618 SPL_SEQUENCE1_INLINE int Sequence1<T>::getSize() const
619 {
620 return data_.getSize();
621 }
622
623 template <class T>
624 SPL_SEQUENCE1_INLINE bool Sequence1<T>::isShared() const
625 {
626 return data_.isShared();
627 }
628
630 // Accessors
632
633 template <class T>
634 SPL_SEQUENCE1_INLINE const T& Sequence1<T>::operator()(int i) const
635 {
636 assert(i >= startInd_ && i < startInd_ + getSize());
637 return data_(i - startInd_);
638 }
639
640 template <class T>
641 SPL_SEQUENCE1_INLINE T& Sequence1<T>::operator()(int i)
642 {
643 assert(i >= startInd_ && i < startInd_ + getSize());
644 return data_(i - startInd_);
645 }
646
648 // Iterators
650
651 template <class T>
652 SPL_SEQUENCE1_INLINE typename Sequence1<T>::ConstIterator Sequence1<T>::begin()
653 const
654 {
655 return data_.begin();
656 }
657
658 template <class T>
659 SPL_SEQUENCE1_INLINE typename Sequence1<T>::ConstIterator Sequence1<T>::end()
660 const
661 {
662 return data_.end();
663 }
664
665 template <class T>
666 SPL_SEQUENCE1_INLINE typename Sequence1<T>::Iterator Sequence1<T>::begin()
667 {
668 return data_.begin();
669 }
670
671 template <class T>
672 SPL_SEQUENCE1_INLINE typename Sequence1<T>::Iterator Sequence1<T>::end()
673 {
674 return data_.end();
675 }
676
678 // Resizing
680
682 // Get various statistics
684
685 template <class T>
686 SPL_SEQUENCE1_INLINE T Sequence1<T>::min() const
687 {
688 assert(getSize() > 0);
689 return data_.min();
690 }
691
692 template <class T>
693 SPL_SEQUENCE1_INLINE T Sequence1<T>::max() const
694 {
695 assert(getSize() > 0);
696 return data_.max();
697 }
698
699 template <class T>
700 SPL_SEQUENCE1_INLINE T Sequence1<T>::sum() const
701 {
702 return data_.sum();
703 }
704
705
707 // Input/output
709
724 template <class T>
725 std::ostream& operator<<(std::ostream& out, const Sequence1<T>& f)
726 {
727 out << f.getStartInd() << " ";
728 out << f.data_;
729 return out;
730 }
731
743 template <class T>
744 std::istream& operator>>(std::istream& in, Sequence1<T>& f)
745 {
746 int startInd;
747 int size;
748 if (!(in >> startInd)) {
749 return in;
750 }
751 if (!(in >> size)) {
752 return in;
753 }
754 if (size < 0) {
755 in.setstate(std::ios::failbit);
756 return in;
757 }
758 typename std::vector<T> data;
759 data.reserve(size);
760 for (int i = 0; i < size; ++i) {
761 T value;
762 if (!(in >> value)) {
763 return in;
764 }
765 data.push_back(value);
766 }
767 f = Sequence1<T>(startInd, data.size(), data.begin());
768 return in;
769 }
770
772 // Miscellaneous
774
775 template <class T>
776 SPL_SEQUENCE1_INLINE void Sequence1<T>::swapArray(Array1<T>& data)
777 {
778 data_.swap(data);
779 }
780
781 template<class T>
782 SPL_SEQUENCE1_INLINE void Sequence1<T>::fill(const T& value)
783 {
784 data_.fill(value);
785 }
786
787 template<class T>
788 SPL_SEQUENCE1_INLINE Array1<T> Sequence1<T>::getArray() const
789 {
790 return data_;
791 }
792
793 template<class T>
794 SPL_SEQUENCE1_INLINE Sequence1<T>& Sequence1<T>::translate(int delta)
795 {
796 startInd_ += delta;
797 return *this;
798 }
799
801 //
803
812 template <class T>
813 SPL_SEQUENCE1_INLINE Sequence1<T> operator+(const Sequence1<T>& f,
814 const Sequence1<T>& g)
815 {
816 return Sequence1<T>(f) += g;
817 }
818
828 template <class T>
829 SPL_SEQUENCE1_INLINE Sequence1<T> operator-(const Sequence1<T>& f,
830 const Sequence1<T>& g)
831 {
832 return Sequence1<T>(f) -= g;
833 }
834
843 template <class T>
844 SPL_SEQUENCE1_INLINE Sequence1<T> operator*(const Sequence1<T>& f,
845 const Sequence1<T>& g)
846 {
847 return Sequence1<T>(f) *= g;
848 }
849
858 template <class T>
859 SPL_SEQUENCE1_INLINE Sequence1<T> operator/(const Sequence1<T>& f,
860 const Sequence1<T>& g)
861 {
862 return Sequence1<T>(f) /= g;
863 }
864
877 template <class T>
878 Sequence1<T> add(const Sequence1<T>& f, const Sequence1<T>& g)
879 {
880 int startInd;
881 int endInd;
882 if (!f.getSize()) {
883 startInd = g.getStartInd();
884 endInd = g.getEndInd();
885 } else if (!g.getSize()) {
886 startInd = f.getStartInd();
887 endInd = f.getEndInd();
888 } else {
889 startInd = std::min(f.getStartInd(), g.getStartInd());
890 endInd = std::max(f.getStartInd() + f.getSize(), g.getStartInd() +
891 g.getSize());
892 }
893 Sequence1<T> result(startInd, endInd - startInd, T(0));
894 int i0 = std::max(f.getStartInd(), startInd);
895 int i1 = std::min(f.getStartInd() + f.getSize(), endInd);
896 for (int i = i0; i < i1; ++i) {
897 result(i) += f(i);
898 }
899 i0 = std::max(g.getStartInd(), startInd);
900 i1 = std::min(g.getStartInd() + g.getSize(), endInd);
901 for (int i = i0; i < i1; ++i) {
902 result(i) += g(i);
903 }
904 return result;
905 }
906
914 template <class T>
915 SPL_SEQUENCE1_INLINE Sequence1<T> operator+(const T& a, const Sequence1<T>& f)
916 {
917 return Sequence1<T>(f) += a;
918 }
919
927 template <class T>
928 SPL_SEQUENCE1_INLINE Sequence1<T> operator+(const Sequence1<T>& f, const T& a)
929 {
930 return Sequence1<T>(f) += a;
931 }
932
940 template <class T>
941 SPL_SEQUENCE1_INLINE Sequence1<T> operator-(const Sequence1<T>& f, const T& a)
942 {
943 return Sequence1<T>(f) -= a;
944 }
945
953 template <class T>
954 SPL_SEQUENCE1_INLINE Sequence1<T> operator*(const T& a, const Sequence1<T>& f)
955 {
956 return Sequence1<T>(f) *= a;
957 }
958
966 template <class T>
967 SPL_SEQUENCE1_INLINE Sequence1<T> operator*(const Sequence1<T>& f, const T& a)
968 {
969 return Sequence1<T>(f) *= a;
970 }
971
979 template <class T>
980 SPL_SEQUENCE1_INLINE Sequence1<T> operator/(const Sequence1<T>& f, const T& a)
981 {
982 return Sequence1<T>(f) /= a;
983 }
984
992 template <class T>
993 SPL_SEQUENCE1_INLINE bool operator==(const Sequence1<T>& f,
994 const Sequence1<T>& g)
995 {
996 bool result;
997 if (!f.getSize() && !g.getSize()) {
998 result = true;
999 } else if (f.getStartInd() != g.getStartInd() ||
1000 f.getEndInd() != g.getEndInd()) {
1001 result = false;
1002 } else {
1003 result = std::equal(f.begin(), f.end(), g.begin());
1004 }
1005 return result;
1006 }
1007
1011 template <class T>
1012 SPL_SEQUENCE1_INLINE bool operator!=(const Sequence1<T>& f,
1013 const Sequence1<T>& g)
1014 {
1015 return !(f == g);
1016 }
1017
1021 template <class T>
1022 SPL_SEQUENCE1_INLINE bool approxEqual(const Sequence1<T>& f,
1023 const Sequence1<T>& g, T threshold = 1e-9)
1024 {
1025 bool result;
1026 if (!f.getSize() && !g.getSize()) {
1027 // Empty sequence.
1028 result = true;
1029 } else if (f.getStartInd() != g.getStartInd() ||
1030 f.getEndInd() != g.getEndInd()) {
1031 // Domains do not match.
1032 result = false;
1033 } else {
1034 result = true;
1035 typename Sequence1<T>::ConstIterator src = f.begin();
1036 typename Sequence1<T>::ConstIterator dst = g.begin();
1037 while (src != f.end()) {
1038 if (absVal((*src) - (*dst)) > threshold) {
1039 result = false;
1040 break;
1041 }
1042 ++src;
1043 ++dst;
1044 }
1045 }
1046 return result;
1047 }
1048
1050 //
1052
1064 template <class T>
1065 Sequence1<T> subsequence(const Sequence1<T>& f, int startInd, int size)
1066 {
1067 assert(startInd >= f.getStartInd() && startInd + size <= f.getEndInd());
1068 Sequence1<T> result(startInd, size);
1069 for (int i = 0; i < size; ++i) {
1070 result(startInd + i) = f(startInd + i);
1071 }
1072 return result;
1073 }
1074
1089 template <class T>
1090 SPL_SEQUENCE1_INLINE Sequence1<T> translate(const Sequence1<T>& f, int delta)
1091 {
1092 return Sequence1<T>(f).translate(delta);
1093 }
1094
1096 // Convolution
1098
1100
1105 template<class T>
1106 SPL_SEQUENCE1_INLINE T getExtSeqValue(const Sequence1<T>& f, int i, int mode)
1107 {
1108 assert(mode == ConvolveMode::full ||
1109 mode == ConvolveMode::sameDomainConstExt ||
1110 mode == ConvolveMode::sameDomainZeroExt ||
1111 mode == ConvolveMode::sameDomainPerExt ||
1112 mode == ConvolveMode::sameDomainSymExt0);
1113 T value;
1114 switch (mode) {
1115 case ConvolveMode::full:
1116 case ConvolveMode::sameDomainZeroExt:
1117 if (i >= f.getStartInd() && i < f.getEndInd()) {
1118 value = f(i);
1119 } else {
1120 value = T(0);
1121 }
1122 break;
1123 case ConvolveMode::sameDomainConstExt:
1124 if (i < f.getStartInd()) {
1125 i = f.getStartInd();
1126 } else if (i >= f.getEndInd()) {
1127 i = f.getEndInd() - 1;
1128 }
1129 assert(i >= f.getStartInd() && i < f.getEndInd());
1130 value = f(i);
1131 break;
1132 case ConvolveMode::sameDomainPerExt:
1133 if (i < f.getStartInd() || i >= f.getEndInd()) {
1134 i = f.getStartInd() + mod(i - f.getStartInd(), f.getSize());
1135 }
1136 assert(i >= f.getStartInd() && i < f.getEndInd());
1137 value = f(i);
1138 break;
1139 case ConvolveMode::sameDomainSymExt0:
1140 if (i < f.getStartInd() || i >= f.getEndInd()) {
1141 int tmp = mod(i - f.getStartInd(), 2 * f.getSize() - 2);
1142 i = f.getStartInd() + std::min(tmp, 2 * f.getSize() - 2 - tmp);
1143 }
1144 assert(i >= f.getStartInd() && i < f.getEndInd());
1145 value = f(i);
1146 break;
1147 default:
1148 assert(0);
1149 abort();
1150 break;
1151 }
1152 return value;
1153 }
1155
1157 template <class T>
1158 Sequence1<T> convolveFull(const Sequence1<T>& f, const Sequence1<T>& g)
1159 {
1160 Sequence1<T> seq(f);
1161 Sequence1<T> filt(g);
1162 Sequence1<T> result(f.getStartInd() + g.getStartInd(),
1163 f.getSize() + g.getSize() - 1);
1164 convolveHelper(seq.begin(), seq.end(), filt.begin(), filt.end(),
1165 result.begin(), T());
1166 return result;
1167 }
1169
1171 template <class T>
1172 Sequence1<T> convolveSameDomainZeroExt(const Sequence1<T>& f,
1173 const Sequence1<T>& g)
1174 {
1175 Sequence1<T> result(f.getStartInd(), f.getSize());
1176 int skip;
1177 int shift;
1178 if (g.getStartInd() >= 0) {
1179 shift = g.getStartInd();
1180 skip = 0;
1181 } else {
1182 shift = 0;
1183 skip = -g.getStartInd();
1184 }
1185 convolveHelper2(f.begin(), f.end(), g.begin(), g.end(),
1186 result.begin() + shift, skip, result.getSize() - shift, T());
1187 return result;
1188 }
1190
1204 template <class T>
1205 Sequence1<T> convolve(const Sequence1<T>& f, const Sequence1<T>& g,
1206 int mode = ConvolveMode::full)
1207 {
1208 #if defined(SPL_SEQUENCE1_USE_NEW_CONV)
1209 switch (mode) {
1210 case ConvolveMode::sameDomainZeroExt:
1211 return convolveSameDomainZeroExt(f, g);
1212 break;
1213 case ConvolveMode::full:
1214 return convolveFull(f, g);
1215 break;
1216 default:
1217 assert(0);
1218 abort();
1219 break;
1220 }
1221 #endif
1222
1223 Sequence1<T> result;
1224
1225 switch (mode) {
1226 case ConvolveMode::full:
1227 result = Sequence1<T>(f.getStartInd() + g.getStartInd(),
1228 f.getSize() + g.getSize() - 1);
1229 break;
1230 case ConvolveMode::sameDomainZeroExt:
1231 case ConvolveMode::sameDomainConstExt:
1232 case ConvolveMode::sameDomainPerExt:
1233 case ConvolveMode::sameDomainSymExt0:
1234 result = Sequence1<T>(f.getStartInd(), f.getSize());
1235 break;
1236 default:
1237 assert(0);
1238 abort();
1239 break;
1240 }
1241
1242 typename Sequence1<T>::Iterator resultIter = result.begin();
1243 for (int n = result.getStartInd(); n < result.getEndInd(); ++n) {
1244 T sum = T(0);
1245 for (int k = g.getStartInd(); k < g.getEndInd(); ++k) {
1246 sum += getExtSeqValue(f, n - k, mode) * g(k);
1247 }
1248 *resultIter = sum;
1249 ++resultIter;
1250 }
1251 assert(resultIter == result.end());
1252 return result;
1253 }
1254
1256 // Downsampling and upsampling
1258
1269 template <class T>
1270 Sequence1<T> downsample(const Sequence1<T>& f, int factor)
1271 {
1272 assert(factor >= 1);
1273 int startInd = ceilDiv(f.getStartInd(), factor) * factor;
1274 int n = ceilDiv(f.getEndInd() - startInd, factor);
1275 Sequence1<T> g(roundTowardZeroDiv(startInd, factor), n);
1276 typename Sequence1<T>::ConstIterator srcIter = f.begin() +
1277 (startInd - f.getStartInd());
1278 typename Sequence1<T>::Iterator dstIter = g.begin();
1279 while (--n >= 0) {
1280 *dstIter = *srcIter;
1281 ++dstIter;
1282 srcIter += factor;
1283 }
1284 return g;
1285 }
1286
1302 template <class T>
1303 Sequence1<T> upsample(const Sequence1<T>& f, int factor, int pad = 0)
1304 {
1305 assert(factor >= 1);
1306 assert(pad >= 0 && pad < factor);
1307 int n = f.getSize() + std::max((f.getSize() - 1), 0) * (factor - 1) + pad;
1308 int m = f.getSize();
1309 Sequence1<T> g(factor * f.getStartInd(), n);
1310 typename Sequence1<T>::ConstIterator srcIter = f.begin();
1311 typename Sequence1<T>::Iterator dstIter = g.begin();
1312 while (m > 1) {
1313 *dstIter = *srcIter;
1314 ++dstIter;
1315 ++srcIter;
1316 for (int i = factor - 1; i > 0; --i) {
1317 *dstIter = T(0);
1318 ++dstIter;
1319 }
1320 --m;
1321 }
1322 if (m > 0) {
1323 *dstIter = *srcIter;
1324 ++dstIter;
1325 }
1326 for (int i = pad; i > 0; --i) {
1327 *dstIter = T(0);
1328 ++dstIter;
1329 }
1330 return g;
1331 }
1332
1334 // Polyphase Decompositions.
1336
1338
1345 inline int getCosetOffset(int type, int numPhases, int index)
1346 {
1347 int result;
1348 switch (type) {
1349 case 1:
1350 result = -index;
1351 break;
1352 case 2:
1353 result = index - (numPhases - 1);
1354 break;
1355 case 3:
1356 result = index;
1357 break;
1358 case 4:
1359 result = (numPhases - 1) - index;
1360 break;
1361 default:
1362 assert(0);
1363 abort();
1364 break;
1365 }
1366 return result;
1367 }
1369
1382 template <class T>
1383 Array1<Sequence1<T> > polyphaseSplit(const Sequence1<T>& seq, int type,
1384 int numPhases)
1385 {
1386 assert(numPhases >= 2);
1387 Array1<Sequence1<T> > result(numPhases);
1388 for (int i = 0; i < numPhases; ++i) {
1389 int offset = getCosetOffset(type, numPhases, i);
1390 result(i) = downsample(translate(seq, offset), numPhases);
1391 }
1392 return result;
1393 }
1394
1406 template <class T>
1407 Sequence1<T> polyphaseJoin(const Array1<Sequence1<T> >& comps, int type)
1408 {
1409 const int numPhases = comps.getSize();
1410 assert(numPhases >= 2);
1411 Sequence1<T> seq;
1412 for (int i = 0; i < numPhases; ++i) {
1413 int offset = getCosetOffset(type, numPhases, i);
1414 seq = add(seq, translate(upsample(comps(i), numPhases), -offset));
1415 }
1416 return seq;
1417 }
1418
1420 // Types.
1422
1424 typedef Sequence1<double> RealSequence1;
1425
1427 typedef Sequence1<int> IntSequence1;
1428
1431
1436 }
1437
1438 #endif
SPL::roundTowardZeroDiv
long roundTowardZeroDiv(long x, long y)
Compute a quotient with the result rounded towards zero.
Definition: math.hpp:152
SPL::operator==
SPL_SEQUENCE1_INLINE bool operator==(const Sequence1< T > &f, const Sequence1< T > &g)
Test two sequences for equality.
Definition: Sequence1.hpp:993
SPL::Sequence1::sum
T sum() const
Get the sum of the elements in the sequence.
Definition: Sequence1.hpp:700
SPL::operator!=
SPL_SEQUENCE1_INLINE bool operator!=(const Sequence1< T > &f, const Sequence1< T > &g)
Test two sequences for inequality.
Definition: Sequence1.hpp:1012
SPL::Sequence1
A one-dimensional sequence class with lazy copying and reference counting.
Definition: Sequence1.hpp:85
SPL::translate
SPL_SEQUENCE1_INLINE Sequence1< T > translate(const Sequence1< T > &f, int delta)
Translate a sequence by the specified amount.
Definition: Sequence1.hpp:1090
SPL::Sequence1::operator*=
Sequence1 & operator*=(const Sequence1 &f)
Multiply elementwise this sequence by another one.
Definition: Sequence1.hpp:550
SPL::Sequence1::getEndInd
int getEndInd() const
Get the end index for the sequence.
Definition: Sequence1.hpp:612
SPL
Definition: Arcball.hpp:48
SPL::mod
T mod(T x, T y)
Compute the remainder after division.
Definition: math.hpp:184
SPL::absVal
T absVal(T x)
The absolute value function.
Definition: math.hpp:73
SPL::approxEqual
SPL_SEQUENCE1_INLINE bool approxEqual(const Sequence1< T > &f, const Sequence1< T > &g, T threshold=1e-9)
Test two sequences for approximate equality.
Definition: Sequence1.hpp:1022
SPL::Sequence1::operator=
Sequence1 & operator=(const Sequence1 &f)
The assignment operator.
Definition: Sequence1.hpp:503
SPL::Sequence1::operator+=
Sequence1 & operator+=(const Sequence1 &f)
Add another sequence to this one.
Definition: Sequence1.hpp:526
SPL::subsequence
Sequence1< T > subsequence(const Sequence1< T > &f, int startInd, int size)
Extract a subsequence from a sequence.
Definition: Sequence1.hpp:1065
SPL::Array1::ConstIterator
std::vector< T >::const_iterator ConstIterator
A constant iterator for the array elements.
Definition: Array1.hpp:158
SPL::upsample
Sequence1< T > upsample(const Sequence1< T > &f, int factor, int pad=0)
Upsample a sequence by the specified factor.
Definition: Sequence1.hpp:1303
SPL::convolve
Sequence1< T > convolve(const Sequence1< T > &f, const Sequence1< T > &g, int mode=ConvolveMode::full)
Compute the convolution of two sequences.
Definition: Sequence1.hpp:1205
SPL::ConvolveMode::full
static const int full
The full convolution result (i.e., the same as "full" in MATLAB)
Definition: Sequence.hpp:57
SPL::Sequence1::~Sequence1
~Sequence1()
The destructor.
Definition: Sequence1.hpp:487
SPL::Sequence1::fill
void fill(const T &value)
Set all of the elements in the sequence to the specified value.
Definition: Sequence1.hpp:782
SPL::ceilDiv
long ceilDiv(long x, long y)
Compute the ceiling of a quotient.
Definition: math.hpp:212
SPL::Sequence1::translate
Sequence1 & translate(int delta)
Translate (i.e., shift) a sequence by the specified displacement.
Definition: Sequence1.hpp:794
SPL::Sequence1::operator-=
Sequence1 & operator-=(const Sequence1 &f)
Subtract another sequence from this one.
Definition: Sequence1.hpp:538
SPL::Sequence1::end
ConstIterator end() const
Get an iterator referencing just after the last element in the sequence.
Definition: Sequence1.hpp:659
SPL::ConvolveMode::sameDomainPerExt
static const int sameDomainPerExt
Periodic extension.
Definition: Sequence.hpp:66
SPL::ConvolveMode::sameDomainConstExt
static const int sameDomainConstExt
Constant extension.
Definition: Sequence.hpp:63
SPL::polyphaseSplit
Array1< Sequence1< T > > polyphaseSplit(const Sequence1< T > &seq, int type, int numPhases)
Split a sequence into its polyphase components.
Definition: Sequence1.hpp:1383
SPL::Array1
A one-dimensional array class with lazy copying and reference counting.
Definition: Array1.hpp:83
SPL::Sequence1::operator/=
Sequence1 & operator/=(const Sequence1 &f)
Divide elementwise this sequence by another one.
Definition: Sequence1.hpp:562
SPL::Sequence1::ElemType
T ElemType
The type of the element in the sequence.
Definition: Sequence1.hpp:94
SPL::IntSequence1
Sequence1< int > IntSequence1
Integer sequence.
Definition: Sequence1.hpp:1427
SPL::RealSequence1
Sequence1< double > RealSequence1
Real sequence.
Definition: Sequence1.hpp:1424
SPL::Sequence1::Sequence1
Sequence1()
The default constructor.
Definition: Sequence1.hpp:442
math.hpp
This file contains various mathematical functions/code.
SPL_SEQUENCE1_INLINE
#define SPL_SEQUENCE1_INLINE
Prevent the inlining of functions.
Definition: Sequence1.hpp:47
SPL::downsample
Sequence1< T > downsample(const Sequence1< T > &f, int factor)
Downsample a sequence by the specified factor.
Definition: Sequence1.hpp:1270
SPL::Sequence1::ConstIterator
Array1< T >::ConstIterator ConstIterator
The const iterator for the sequence.
Definition: Sequence1.hpp:97
Sequence.hpp
Common header for sequence classes.
SPL::Sequence1::getStartInd
int getStartInd() const
Get the start index for the sequence.
Definition: Sequence1.hpp:606
SPL::operator>>
std::istream & operator>>(std::istream &in, Sequence1< T > &f)
Input a sequence from a stream.
Definition: Sequence1.hpp:744
SPL::add
Sequence1< T > add(const Sequence1< T > &f, const Sequence1< T > &g)
Compute the sum of two sequences with potentially differing domains.
Definition: Sequence1.hpp:878
SPL::Sequence1::swapArray
void swapArray(Array1< T > &data)
Swap the data for the underlying array and the specified array.
Definition: Sequence1.hpp:776
SPL::ConvolveMode::sameDomainSymExt0
static const int sameDomainSymExt0
Symmetric periodic extension.
Definition: Sequence.hpp:69
SPL::operator*
SPL_SEQUENCE1_INLINE Sequence1< T > operator*(const Sequence1< T > &f, const T &a)
Compute a scalar multiple of a sequence.
Definition: Sequence1.hpp:967
SPL::polyphaseJoin
Sequence1< T > polyphaseJoin(const Array1< Sequence1< T > > &comps, int type)
Reassemble a sequence from its polyphase components.
Definition: Sequence1.hpp:1407
SPL::ConvolveMode::sameDomainZeroExt
static const int sameDomainZeroExt
The same as "same" in MATLAB.
Definition: Sequence.hpp:60
SPL::Sequence1::min
T min() const
Get the minimum element in the sequence.
Definition: Sequence1.hpp:686
SPL::operator/
SPL_SEQUENCE1_INLINE Sequence1< T > operator/(const Sequence1< T > &f, const T &a)
Divide a sequence by a scalar.
Definition: Sequence1.hpp:980
SPL::Sequence1::isShared
bool isShared() const
Is the array for this sequence shared with another array?
Definition: Sequence1.hpp:624
SPL::operator-
SPL_SEQUENCE1_INLINE Sequence1< T > operator-(const Sequence1< T > &f, const T &a)
Subtract a value from a sequence.
Definition: Sequence1.hpp:941
SPL::Sequence1::getSize
int getSize() const
Get the length of the sequence.
Definition: Sequence1.hpp:618
Array1.hpp
This file contains the Array1 template class and supporting code.
SPL::Sequence1::operator()
const T & operator()(int i) const
Get the specified element in the sequence.
Definition: Sequence1.hpp:634
SPL::operator+
SPL_SEQUENCE1_INLINE Sequence1< T > operator+(const Sequence1< T > &f, const T &a)
Add a value to a sequence.
Definition: Sequence1.hpp:928
SPL::Sequence1::getArray
Array1< T > getArray() const
Get a copy of the underlying array.
Definition: Sequence1.hpp:788
SPL::Array1::Iterator
std::vector< T >::iterator Iterator
A mutable iterator for the array elements.
Definition: Array1.hpp:155
SPL::Sequence1::Iterator
Array1< T >::Iterator Iterator
The mutable iterator for the sequence.
Definition: Sequence1.hpp:100
SPL::Sequence1::begin
ConstIterator begin() const
Get an iterator referencing the first element in the sequence.
Definition: Sequence1.hpp:652
SPL::Sequence1::max
T max() const
Get the maximum element in the sequence.
Definition: Sequence1.hpp:693