Signal/Geometry Processing Library (SPL) 1.1.24 |

Sequence2.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_Sequence2_hpp
33 #define SPL_Sequence2_hpp
34
36 // Configuration
38
40 //#define SPL_SEQUENCE2_DEBUG
41
43 #define SPL_SEQUENCE2_USE_NEW_CONV
44
45 #if defined(SPL_SEQUENCE2_DEBUG)
46 #define SPL_SEQUENCE2_INLINE
48 #else
49 #define SPL_SEQUENCE2_INLINE inline
51 #endif
52
54 // Include files.
56
57 #include <SPL/config.hpp>
58 #include <iostream>
59 #include <vector>
60 #include <SPL/Array2.hpp>
61 #include <SPL/Sequence.hpp>
62 #include <SPL/Sequence1.hpp>
63 #include <SPL/Sequence.hpp>
64 #include <SPL/math.hpp>
65
66 namespace SPL {
67
69 // Types.
71
82 template <class T>
83 class Sequence2
84 {
85 public:
86
88 // Types
90
92 typedef T ElemType;
93
95 typedef typename Array2<T>::ConstIterator ConstIterator;
96
98 typedef typename Array2<T>::Iterator Iterator;
99
101 typedef typename Array2<T>::ConstXIterator ConstXIterator;
102
104 typedef typename Array2<T>::XIterator XIterator;
105
107 typedef typename Array2<T>::ConstYIterator ConstYIterator;
108
110 typedef typename Array2<T>::YIterator YIterator;
111
113 // Constructors and destructor
115
119 Sequence2();
120
124 Sequence2(int startX, int startY, int width, int height);
125
130 Sequence2(int startX, int startY, int width, int height, const T& data);
131
136 template <class InputIterator>
137 Sequence2(int startX, int startY, int width, int height,
138 InputIterator data);
139
143 Sequence2(const Sequence2& f);
144
149 template <class OtherT>
150 Sequence2(const Sequence2<OtherT>& f);
151
155 Sequence2(const Array2<T>& data);
156
160 Sequence2(int startX, int startY, const Array2<T>& data);
161
165 ~Sequence2();
166
168 // Assignment operators
170
174 Sequence2& operator=(const Sequence2& f);
175
182 template <class OtherT>
183 Sequence2& operator=(const Sequence2<OtherT>& f);
184
186 // Compound assignment operators
188
192 Sequence2& operator+=(const Sequence2& f);
193
197 Sequence2& operator-=(const Sequence2& f);
198
202 Sequence2& operator*=(const Sequence2& f);
203
207 Sequence2& operator/=(const Sequence2& f);
208
212 Sequence2& operator+=(const T& value);
213
217 Sequence2& operator-=(const T& value);
218
222 Sequence2& operator*=(const T& value);
223
227 Sequence2& operator/=(const T& value);
228
230 // Basic queries
232
236 int getStartX() const;
237
241 int getStartY() const;
242
246 int getEndX() const;
247
251 int getEndY() const;
252
256 int getWidth() const;
257
261 int getHeight() const;
262
266 int getSize() const;
267
271 bool isShared() const;
272
274 // Accessors
276
280 T& operator()(int x, int y);
281
285 const T& operator()(int x, int y) const;
286
288 // Iterators
290
294 ConstIterator begin() const;
295
299 Iterator begin();
300
305 ConstIterator end() const;
306
311 Iterator end();
312
317 ConstXIterator rowBegin(int y) const;
318
323 XIterator rowBegin(int y);
324
329 ConstXIterator rowEnd(int y) const;
330
335 XIterator rowEnd(int y);
336
341 ConstYIterator colBegin(int x) const;
342
347 YIterator colBegin(int x);
348
353 ConstYIterator colEnd(int x) const;
354
359 YIterator colEnd(int x);
360
362 // Resizing
364
366 // Get various statistics
368
374 T min() const;
375
381 T max() const;
382
386 T sum() const;
387
389 // Input/ouput
391
396 std::ostream& output(std::ostream& out, int fieldWidth) const;
397
399 // Miscellaneous
401
405 Array2<T> getArray() const;
406
410 void swapArray(Array2<T>& data);
411
415 void fill(const T& value);
416
420 Sequence2& translate(int x, int y);
421
422 private:
423
424 template <class> friend class Sequence2;
425
426 template <class U>
427 friend std::ostream& operator<<(std::ostream& out, const Sequence2<U>&);
428 template <class U>
429 friend Sequence2<U> translate(const Sequence2<U>&, int x, int y);
430
432 typedef Array2<T> Array;
433
435 int startX_;
436
438 int startY_;
439
441 Array data_;
442
443 };
444
446 //
448
450
457 void combineDomains(int firstStartX, int firstStartY, int firstEndX,
458 int firstEndY, int secondStartX, int secondStartY, int secondEndX,
459 int secondEndY, int& startX, int& startY, int& endX, int& endY);
460
462
464 // Constructors and destructor
466
467 template <class T>
468 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2() : startX_(0), startY_(0),
469 data_()
470 {
471 }
472
473 template <class T>
474 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(int startX, int startY,
475 int width, int height) : startX_(startX), startY_(startY),
476 data_(width, height)
477 {
478 assert(width >= 0 && height >= 0);
479 }
480
481 template <class T>
482 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(int startX, int startY,
483 int width, int height, const T& value) : startX_(startX), startY_(startY),
484 data_(width, height, value)
485 {
486 assert(width >= 0 && height >= 0);
487 }
488
489 template <class T>
490 template <class InputIterator>
491 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(int startX, int startY,
492 int width, int height, InputIterator data) : startX_(startX),
493 startY_(startY), data_(width, height, data)
494 {
495 assert(width >= 0 && height >= 0);
496 assert(getWidth() == width && getHeight() == height);
497 }
498
499 template <class T>
500 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(const Sequence2<T>& f) :
501 startX_(f.startX_), startY_(f.startY_), data_(f.data_)
502 {
503 }
504
505 template <class T>
506 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(const Array2<T>& data) :
507 startX_(0), startY_(0), data_(data)
508 {
509 }
510
511 template <class T>
512 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(int startX, int startY,
513 const Array2<T>& data) :
514 startX_(startX), startY_(startY), data_(data)
515 {
516 }
517
518 template <class T>
519 SPL_SEQUENCE2_INLINE Sequence2<T>::~Sequence2()
520 {
521 }
522
523 template <class T>
524 template <class OtherT>
525 SPL_SEQUENCE2_INLINE Sequence2<T>::Sequence2(const Sequence2<OtherT>& f) :
526 startX_(f.startX_), startY_(f.startY_), data_(f.data_)
527 {
528 }
529
531 // Assignment operators
533
534 template <class T>
535 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator=(
536 const Sequence2<T>& f)
537 {
538 startX_ = f.startX_;
539 startY_ = f.startY_;
540 data_ = f.data_;
541 return *this;
542 }
543
544 template <class T>
545 template <class OtherT>
546 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator=(
547 const Sequence2<OtherT>& f)
548 {
549 startX_ = f.startX_;
550 startY_ = f.startY_;
551 data_ = f.data_;
552 return *this;
553 }
554
556 // Compound assignment operators
558
559 template <class T>
560 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator+=(
561 const Sequence2<T>& f)
562 {
563 // Ensure that both sequences have the same domain.
564 assert((!getSize() && !f.getSize()) ||
565 (getStartX() == f.getStartX() && getEndX() == f.getEndX() &&
566 getStartY() == f.getStartY() && getEndY() == f.getEndY()));
567
568 data_ += f.data_;
569 return *this;
570 }
571
572 template <class T>
573 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator-=(
574 const Sequence2<T>& f)
575 {
576 // Ensure that both sequences have the same domain.
577 assert((!getSize() && !f.getSize()) ||
578 (getStartX() == f.getStartX() && getEndX() == f.getEndX() &&
579 getStartY() == f.getStartY() && getEndY() == f.getEndY()));
580
581 data_ -= f.data_;
582 return *this;
583 }
584
585 template <class T>
586 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator*=(
587 const Sequence2<T>& f)
588 {
589 // Ensure that both sequences have the same domain.
590 assert((!getSize() && !f.getSize()) ||
591 (getStartX() == f.getStartX() && getEndX() == f.getEndX() &&
592 getStartY() == f.getStartY() && getEndY() == f.getEndY()));
593
594 data_ *= f.data_;
595 return *this;
596 }
597
598 template <class T>
599 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator/=(
600 const Sequence2<T>& f)
601 {
602 // Ensure that both sequences have the same domain.
603 assert((!getSize() && !f.getSize()) ||
604 (getStartX() == f.getStartX() && getEndX() == f.getEndX() &&
605 getStartY() == f.getStartY() && getEndY() == f.getEndY()));
606
607 data_ /= f.data_;
608 return *this;
609 }
610
611 template <class T>
612 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator+=(
613 const T& value)
614 {
615 data_ += value;
616 return *this;
617 }
618
619 template <class T>
620 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator-=(
621 const T& value)
622 {
623 data_ -= value;
624 return *this;
625 }
626
627 template <class T>
628 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator*=(
629 const T& value)
630 {
631 data_ *= value;
632 return *this;
633 }
634
635 template <class T>
636 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::operator/=(
637 const T& value)
638 {
639 data_ /= value;
640 return *this;
641 }
642
644 // Basic queries
646
647 template <class T>
648 SPL_SEQUENCE2_INLINE int Sequence2<T>::getStartX() const
649 {
650 return startX_;
651 }
652
653 template <class T>
654 SPL_SEQUENCE2_INLINE int Sequence2<T>::getStartY() const
655 {
656 return startY_;
657 }
658
659 template <class T>
660 SPL_SEQUENCE2_INLINE int Sequence2<T>::getEndX() const
661 {
662 return startX_ + getWidth();
663 }
664
665 template <class T>
666 SPL_SEQUENCE2_INLINE int Sequence2<T>::getEndY() const
667 {
668 return startY_ + getHeight();
669 }
670
671 template <class T>
672 SPL_SEQUENCE2_INLINE int Sequence2<T>::getWidth() const
673 {
674 return data_.getWidth();
675 }
676
677 template <class T>
678 SPL_SEQUENCE2_INLINE int Sequence2<T>::getHeight() const
679 {
680 return data_.getHeight();
681 }
682
683 template <class T>
684 SPL_SEQUENCE2_INLINE int Sequence2<T>::getSize() const
685 {
686 return data_.getWidth() * data_.getHeight();
687 }
688
689 template <class T>
690 SPL_SEQUENCE2_INLINE bool Sequence2<T>::isShared() const
691 {
692 return data_.isShared();
693 }
694
696 // Accessors
698
699 template <class T>
700 SPL_SEQUENCE2_INLINE const T& Sequence2<T>::operator()(int x, int y) const
701 {
702 assert(x >= startX_ && x < getEndX() && y >= startY_ && y < getEndY());
703 return data_(x - startX_, y - startY_);
704 }
705
706 template <class T>
707 SPL_SEQUENCE2_INLINE T& Sequence2<T>::operator()(int x, int y)
708 {
709 assert(x >= startX_ && x < getEndX() && y >= startY_ && y < getEndY());
710 return data_(x - startX_, y - startY_);
711 }
712
714 // Iterators
716
717 template <class T>
718 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstIterator Sequence2<T>::begin()
719 const
720 {
721 return data_.begin();
722 }
723
724 template <class T>
725 SPL_SEQUENCE2_INLINE typename Sequence2<T>::Iterator Sequence2<T>::begin()
726 {
727 return data_.begin();
728 }
729
730 template <class T>
731 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstIterator Sequence2<T>::end()
732 const
733 {
734 return data_.end();
735 }
736
737 template <class T>
738 SPL_SEQUENCE2_INLINE typename Sequence2<T>::Iterator Sequence2<T>::end()
739 {
740 return data_.end();
741 }
742
743 template <class T>
744 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstXIterator
745 Sequence2<T>::rowBegin(int y) const
746 {
747 assert(y >= startY_ && y < getEndY());
748 return data_.rowBegin(y - startY_);
749 }
750
751 template <class T>
752 SPL_SEQUENCE2_INLINE typename Sequence2<T>::XIterator
753 Sequence2<T>::rowBegin(int y)
754 {
755 assert(y >= startY_ && y < getEndY());
756 return data_.rowBegin(y - startY_);
757 }
758
759 template <class T>
760 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstXIterator
761 Sequence2<T>::rowEnd(int y) const
762 {
763 assert(y >= startY_ && y < getEndY());
764 return data_.rowEnd(y - startY_);
765 }
766
767 template <class T>
768 SPL_SEQUENCE2_INLINE typename Sequence2<T>::XIterator
769 Sequence2<T>::rowEnd(int y)
770 {
771 assert(y >= startY_ && y < getEndY());
772 return data_.rowEnd(y - startY_);
773 }
774
775 template <class T>
776 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstYIterator
777 Sequence2<T>::colBegin(int x) const
778 {
779 assert(x >= startX_ && x < getEndX());
780 return data_.colBegin(x - startX_);
781 }
782
783 template <class T>
784 SPL_SEQUENCE2_INLINE typename Sequence2<T>::YIterator
785 Sequence2<T>::colBegin(int x)
786 {
787 assert(x >= startX_ && x < getEndX());
788 return data_.colBegin(x - startX_);
789 }
790
791 template <class T>
792 SPL_SEQUENCE2_INLINE typename Sequence2<T>::ConstYIterator
793 Sequence2<T>::colEnd(int x) const
794 {
795 assert(x >= startX_ && x < getEndX());
796 return data_.colEnd(x - startX_);
797 }
798
799 template <class T>
800 SPL_SEQUENCE2_INLINE typename Sequence2<T>::YIterator
801 Sequence2<T>::colEnd(int x)
802 {
803 assert(x >= startX_ && x < getEndX());
804 return data_.colEnd(x - startX_);
805 }
806
808 // Resizing
810
812 // Get various statistics
814
815 template <class T>
816 SPL_SEQUENCE2_INLINE T Sequence2<T>::min() const
817 {
818 assert(getSize() > 0);
819 return data_.min();
820 }
821
822 template <class T>
823 SPL_SEQUENCE2_INLINE T Sequence2<T>::max() const
824 {
825 assert(getSize() > 0);
826 return data_.max();
827 }
828
829 template <class T>
830 SPL_SEQUENCE2_INLINE T Sequence2<T>::sum() const
831 {
832 return data_.sum();
833 }
834
836 // Input/output
838
839 template <class T>
840 std::ostream& Sequence2<T>::output(std::ostream& out, int fieldWidth) const
841 {
842 out << startX_ << " " << startY_ << " ";
843 data_.output(out, fieldWidth);
844 return out;
845 }
846
862 template <class T>
863 std::ostream& operator<<(std::ostream& out, const Sequence2<T>& f)
864 {
865 out << f.getStartX() << " " << f.getStartY() << " ";
866 out << f.data_;
867 return out;
868 }
869
880 template <class T>
881 std::istream& operator>>(std::istream& in, Sequence2<T>& f)
882 {
883 int startX;
884 int startY;
885 int width;
886 int height;
887 if (!(in >> startX)) {
888 return in;
889 }
890 if (!(in >> startY)) {
891 return in;
892 }
893 if (!(in >> width)) {
894 return in;
895 }
896 if (!(in >> height)) {
897 return in;
898 }
899 typename std::vector<T> data;
900 data.reserve(width * height);
901 for (int y = 0; y < height; ++y) {
902 for (int x = 0; x < width; ++x) {
903 T value;
904 if (!(in >> value)) {
905 return in;
906 }
907 data.push_back(value);
908 }
909 }
910 f = Sequence2<T>(startX, startY, width, height, data.begin());
911 return in;
912 }
913
915 // Miscellaneous
917
918 template<class T>
919 SPL_SEQUENCE2_INLINE void Sequence2<T>::fill(const T& value)
920 {
921 data_.fill(value);
922 }
923
924 template <class T>
925 SPL_SEQUENCE2_INLINE void Sequence2<T>::swapArray(Array2<T>& data)
926 {
927 data_.swap(data);
928 }
929
930 template<class T>
931 SPL_SEQUENCE2_INLINE Array2<T> Sequence2<T>::getArray() const
932 {
933 return data_;
934 }
935
936 template<class T>
937 SPL_SEQUENCE2_INLINE Sequence2<T>& Sequence2<T>::translate(int x, int y)
938 {
939 startX_ += x;
940 startY_ += y;
941 return *this;
942 }
943
945 //
947
955 template <class T>
956 SPL_SEQUENCE2_INLINE Sequence2<T> operator+(const Sequence2<T>& f,
957 const Sequence2<T>& g)
958 {
959 return Sequence2<T>(f) += g;
960 }
961
970 template <class T>
971 SPL_SEQUENCE2_INLINE Sequence2<T> operator-(const Sequence2<T>& f,
972 const Sequence2<T>& g)
973 {
974 return Sequence2<T>(f) -= g;
975 }
976
984 template <class T>
985 SPL_SEQUENCE2_INLINE Sequence2<T> operator*(const Sequence2<T>& f,
986 const Sequence2<T>& g)
987 {
988 return Sequence2<T>(f) *= g;
989 }
990
998 template <class T>
999 SPL_SEQUENCE2_INLINE Sequence2<T> operator/(const Sequence2<T>& f,
1000 const Sequence2<T>& g)
1001 {
1002 return Sequence2<T>(f) /= g;
1003 }
1004
1016 template <class T>
1017 Sequence2<T> add(const Sequence2<T>& f, const Sequence2<T>& g)
1018 {
1019 int startX;
1020 int startY;
1021 int endX;
1022 int endY;
1023 combineDomains(f.getStartX(), f.getStartY(), f.getEndX(), f.getEndY(),
1024 g.getStartX(), g.getStartY(), g.getEndX(), g.getEndY(), startX, startY,
1025 endX, endY);
1026 Sequence2<T> result(startX, startY, endX - startX, endY - startY, T(0));
1027 int xMin = std::max(f.getStartX(), startX);
1028 int xMax = std::min(f.getEndX(), endX) - 1;
1029 int yMin = std::max(f.getStartY(), startY);
1030 int yMax = std::min(f.getEndY(), endY) - 1;
1031 for (int y = yMin; y <= yMax; ++y) {
1032 for (int x = xMin; x <= xMax; ++x) {
1033 result(x, y) += f(x, y);
1034 }
1035 }
1036 xMin = std::max(g.getStartX(), startX);
1037 xMax = std::min(g.getEndX(), endX) - 1;
1038 yMin = std::max(g.getStartY(), startY);
1039 yMax = std::min(g.getEndY(), endY) - 1;
1040 for (int y = yMin; y <= yMax; ++y) {
1041 for (int x = xMin; x <= xMax; ++x) {
1042 result(x, y) += g(x, y);
1043 }
1044 }
1045 return result;
1046 }
1047
1055 template <class T>
1056 SPL_SEQUENCE2_INLINE Sequence2<T> operator+(const T& value,
1057 const Sequence2<T>& f)
1058 {
1059 return Sequence2<T>(f) += value;
1060 }
1061
1069 template <class T>
1070 SPL_SEQUENCE2_INLINE Sequence2<T> operator+(const Sequence2<T>& f,
1071 const T& value)
1072 {
1073 return Sequence2<T>(f) += value;
1074 }
1075
1083 template <class T>
1084 SPL_SEQUENCE2_INLINE Sequence2<T> operator-(const Sequence2<T>& f,
1085 const T& value)
1086 {
1087 return Sequence2<T>(f) -= value;
1088 }
1089
1097 template <class T>
1098 SPL_SEQUENCE2_INLINE Sequence2<T> operator*(const T& value,
1099 const Sequence2<T>& f)
1100 {
1101 return Sequence2<T>(f) *= value;
1102 }
1103
1111 template <class T>
1112 SPL_SEQUENCE2_INLINE Sequence2<T> operator*(const Sequence2<T>& f,
1113 const T& value)
1114 {
1115 return Sequence2<T>(f) *= value;
1116 }
1117
1125 template <class T>
1126 SPL_SEQUENCE2_INLINE Sequence2<T> operator/(const Sequence2<T>& f,
1127 const T& value)
1128 {
1129 return Sequence2<T>(f) /= value;
1130 }
1131
1140 template <class T>
1141 bool operator==(const Sequence2<T>& f, const Sequence2<T>& g)
1142 {
1143 bool result;
1144 if (!f.getSize() && !g.getSize()) {
1145 // Both sequences are empty.
1146 result = true;
1147 } else if (f.getStartX() != g.getStartX() ||
1148 f.getEndX() != g.getEndX() || f.getStartY() != g.getStartY() ||
1149 f.getEndY() != g.getEndY()) {
1150 // The sequences are not defined on the same domain.
1151 result = false;
1152 } else {
1153 // The sequences are defined on the same domain.
1154 result = std::equal(f.begin(), f.end(), g.begin());
1155 }
1156 return result;
1157 }
1158
1162 template <class T>
1163 SPL_SEQUENCE2_INLINE bool operator!=(const Sequence2<T>& f,
1164 const Sequence2<T>& g)
1165 {
1166 return !(f == g);
1167 }
1168
1172 template <class T>
1173 SPL_SEQUENCE2_INLINE bool approxEqual(const Sequence2<T>& f,
1174 const Sequence2<T>& g, T threshold = 1e-9)
1175 {
1176 bool result;
1177 if (!f.getSize() && !g.getSize()) {
1178 // Empty sequence.
1179 result = true;
1180 } else if (f.getStartX() != g.getStartX() ||
1181 f.getStartY() != g.getStartY() ||
1182 f.getEndX() != g.getEndX() ||
1183 f.getEndY() != g.getEndY()) {
1184 // Domains do not match.
1185 result = false;
1186 } else {
1187 assert(f.getWidth() == g.getWidth() && f.getHeight() == g.getHeight());
1188 result = true;
1189 typename Sequence2<T>::ConstIterator src = f.begin();
1190 typename Sequence2<T>::ConstIterator dst = g.begin();
1191 while (src != f.end()) {
1192 if (absVal((*src) - (*dst)) > threshold) {
1193 result = false;
1194 break;
1195 }
1196 ++src;
1197 ++dst;
1198 }
1199 }
1200 return result;
1201 }
1202
1204 //
1206
1217 template <class T>
1218 Sequence2<T> subsequence(const Sequence2<T>& f, int startX, int startY,
1219 int width, int height)
1220 {
1221 assert(startX >= f.getStartX() && startX + width <= f.getEndX() &&
1222 startY >= f.getStartY() && startY + height <= f.getEndY());
1223 if (!width || !height) {
1224 width = 0;
1225 height = 0;
1226 }
1227 Sequence2<T> result(startX, startY, width, height);
1228 for (int i = 0; i < height; ++i) {
1229 assert(startX - f.getStartX() >= 0);
1230 typename Sequence2<T>::ConstXIterator src =
1231 f.rowBegin(startY + i) + (startX - f.getStartX());
1232 typename Sequence2<T>::XIterator dst = result.rowBegin(startY + i);
1233 SPL::copy_n(src, width, dst);
1234 }
1235 return result;
1236 }
1237
1247 template <class T>
1248 SPL_SEQUENCE2_INLINE Sequence2<T> translate(const Sequence2<T>& f,
1249 int deltaX, int deltaY)
1250 {
1251 return Sequence2<T>(f).translate(deltaX, deltaY);
1252 }
1253
1255 // Convolution
1257
1259
1265 template<class T>
1266 SPL_SEQUENCE2_INLINE T getExtSeqValue(const Sequence2<T>& f, int x, int y,
1267 int mode)
1268 {
1269 assert(mode == ConvolveMode::full ||
1270 mode == ConvolveMode::sameDomainConstExt ||
1271 mode == ConvolveMode::sameDomainZeroExt ||
1272 mode == ConvolveMode::sameDomainPerExt ||
1273 mode == ConvolveMode::sameDomainSymExt0);
1274 T value;
1275 switch (mode) {
1276 case ConvolveMode::full:
1277 case ConvolveMode::sameDomainZeroExt:
1278 if (x >= f.getStartX() && x < f.getEndX() &&
1279 y >= f.getStartY() && y < f.getEndY()) {
1280 value = f(x, y);
1281 } else {
1282 value = T(0);
1283 }
1284 break;
1285 case ConvolveMode::sameDomainConstExt:
1286 if (x < f.getStartX()) {
1287 x = f.getStartX();
1288 } else if (x >= f.getEndX()) {
1289 x = f.getEndX() - 1;
1290 }
1291 if (y < f.getStartY()) {
1292 y = f.getStartY();
1293 } else if (y >= f.getEndY()) {
1294 y = f.getEndY() - 1;
1295 }
1296 value = f(x, y);
1297 break;
1298 case ConvolveMode::sameDomainPerExt:
1299 if (x < f.getStartX() || x >= f.getEndX()) {
1300 x = f.getStartX() + mod(x - f.getStartX(), f.getWidth());
1301 }
1302 if (y < f.getStartY() || y >= f.getEndY()) {
1303 y = f.getStartY() + mod(y - f.getStartY(), f.getHeight());
1304 }
1305 assert(x >= f.getStartX() && x < f.getEndX());
1306 assert(y >= f.getStartY() && y < f.getEndY());
1307 value = f(x, y);
1308 break;
1309 case ConvolveMode::sameDomainSymExt0:
1310 if (x < f.getStartX() || x >= f.getEndX()) {
1311 int tmp = mod(x - f.getStartX(), 2 * f.getWidth() - 2);
1312 x = f.getStartX() + std::min(tmp, 2 * f.getWidth() - 2 - tmp);
1313 }
1314 if (y < f.getStartY() || y >= f.getEndY()) {
1315 int tmp = mod(y - f.getStartY(), 2 * f.getHeight() - 2);
1316 y = f.getStartY() + std::min(tmp, 2 * f.getHeight() - 2 - tmp);
1317 }
1318 assert(x >= f.getStartX() && x < f.getEndX());
1319 assert(y >= f.getStartY() && y < f.getEndY());
1320 value = f(x, y);
1321 break;
1322 default:
1323 assert(0);
1324 abort();
1325 break;
1326 }
1327 return value;
1328 }
1330
1332
1337 template <class T>
1338 Sequence2<T> convolveSeparableFull(const Sequence2<T>& f,
1339 const Sequence1<T>& horzFilt, const Sequence1<T>& vertFilt)
1340 {
1341 if (!horzFilt.getSize() || !vertFilt.getSize()) {
1342 return Sequence2<T>();
1343 }
1344
1345 // Perform the horizontal filtering.
1346 Sequence2<T> tmpResult(f.getStartX() + horzFilt.getStartInd(),
1347 f.getStartY(), f.getWidth() + horzFilt.getSize() - 1,
1348 f.getHeight());
1349 for (int y = f.getStartY(); y < f.getEndY(); ++y) {
1350 convolveHelper(f.rowBegin(y), f.rowEnd(y), horzFilt.begin(),
1351 horzFilt.end(), tmpResult.rowBegin(y), T());
1352 }
1353
1354 // Perform the vertical filtering.
1355 Sequence2<T> result(tmpResult.getStartX(), tmpResult.getStartY() +
1356 vertFilt.getStartInd(), tmpResult.getWidth(), tmpResult.getHeight() +
1357 vertFilt.getSize() - 1);
1358 for (int x = tmpResult.getStartX(); x < tmpResult.getEndX(); ++x) {
1359 convolveHelper(tmpResult.colBegin(x), tmpResult.colEnd(x),
1360 vertFilt.begin(), vertFilt.end(), result.colBegin(x), T());
1361 }
1362
1363 return result;
1364 }
1366
1368
1373 template <class T>
1374 Sequence2<T> convolveSeparableSameDomainZeroExt(const Sequence2<T>& f,
1375 const Sequence1<T>& horzFilt, const Sequence1<T>& vertFilt)
1376 {
1377 if (!horzFilt.getSize() || !vertFilt.getSize()) {
1378 return Sequence2<T>();
1379 }
1380
1381 int skip;
1382 int shift;
1383
1384 // Perform the horizontal filtering.
1385 Sequence2<T> tmpResult(f.getStartX(), f.getStartY(), f.getWidth(),
1386 f.getHeight());
1387 if (horzFilt.getStartInd() >= 0) {
1388 shift = horzFilt.getStartInd();
1389 skip = 0;
1390 } else {
1391 shift = 0;
1392 skip = -horzFilt.getStartInd();
1393 }
1394 for (int y = f.getStartY(); y < f.getEndY(); ++y) {
1395 convolveHelper2(f.rowBegin(y), f.rowEnd(y), horzFilt.begin(),
1396 horzFilt.end(), tmpResult.rowBegin(y) + shift, skip,
1397 tmpResult.getWidth() - shift, T());
1398 }
1399
1400 // Perform the vertical filtering.
1401 if (vertFilt.getStartInd() >= 0) {
1402 shift = vertFilt.getStartInd();
1403 skip = 0;
1404 } else {
1405 shift = 0;
1406 skip = -vertFilt.getStartInd();
1407 }
1408 Sequence2<T> result(tmpResult.getStartX(), tmpResult.getStartY(),
1409 tmpResult.getWidth(), tmpResult.getHeight());
1410 for (int x = tmpResult.getStartX(); x < tmpResult.getEndX(); ++x) {
1411 convolveHelper2(tmpResult.colBegin(x), tmpResult.colEnd(x),
1412 vertFilt.begin(), vertFilt.end(), result.colBegin(x) + shift,
1413 skip, result.getHeight() - shift, T());
1414 }
1415
1416 return result;
1417 }
1419
1423 template<class T>
1424 Sequence2<T> convolve(const Sequence2<T>& f, const Sequence2<T>& g, int mode)
1425 {
1426 assert(mode == ConvolveMode::full ||
1427 mode == ConvolveMode::sameDomainConstExt ||
1428 mode == ConvolveMode::sameDomainZeroExt ||
1429 mode == ConvolveMode::sameDomainPerExt ||
1430 mode == ConvolveMode::sameDomainSymExt0);
1431 assert(f.getWidth() > 0 && f.getHeight() > 0);
1432 assert(g.getWidth() > 0 && g.getHeight() > 0);
1433
1434 Sequence2<T> result;
1435
1436 switch (mode) {
1437 case ConvolveMode::full:
1438 result = Sequence2<T>(f.getStartX() + g.getStartX(),
1439 f.getStartY() + g.getStartY(), f.getWidth() + g.getWidth() - 1,
1440 f.getHeight() + g.getHeight() - 1);
1441 break;
1442 case ConvolveMode::sameDomainConstExt:
1443 case ConvolveMode::sameDomainZeroExt:
1444 case ConvolveMode::sameDomainPerExt:
1445 case ConvolveMode::sameDomainSymExt0:
1446 result = Sequence2<T>(f.getStartX(), f.getStartY(), f.getWidth(),
1447 f.getHeight());
1448 break;
1449 default:
1450 assert(0);
1451 abort();
1452 break;
1453 }
1454
1455 for (int y = result.getStartY(); y < result.getEndY(); ++y) {
1456 for (int x = result.getStartX(); x < result.getEndX(); ++x) {
1457 T sum = T(0);
1458 for (int j = g.getStartY(); j < g.getEndY(); ++j) {
1459 for (int i = g.getStartX(); i < g.getEndX(); ++i) {
1460 sum += getExtSeqValue(f, x - i, y - j, mode) * g(i, j);
1461 }
1462 }
1463 result(x, y) = sum;
1464 }
1465 }
1466
1467 return result;
1468 }
1469
1474 template <class T>
1475 Sequence2<T> convolveSeparable(const Sequence2<T>& f,
1476 const Sequence1<T>& horzFilt, const Sequence1<T>& vertFilt,
1477 int mode = ConvolveMode::full)
1478 {
1479 #if defined(SPL_SEQUENCE2_USE_NEW_CONV)
1480 switch (mode) {
1481 case ConvolveMode::full:
1482 return convolveSeparableFull(f, horzFilt, vertFilt);
1483 break;
1484 case ConvolveMode::sameDomainZeroExt:
1485 return convolveSeparableSameDomainZeroExt(f, horzFilt, vertFilt);
1486 break;
1487 }
1488 #endif
1489 // The following code is quite inefficient. Rewrite it someday.
1490 Sequence2<T> horzFilt0(horzFilt.getStartInd(), 0, horzFilt.getSize(), 1,
1491 horzFilt.begin());
1492 Sequence2<T> vertFilt0(0, vertFilt.getStartInd(), 1, vertFilt.getSize(),
1493 vertFilt.begin());
1494 Sequence2<T> result = convolve(f, horzFilt0, mode);
1495 result = convolve(result, vertFilt0, mode);
1496 return result;
1497 }
1498
1500 // Downsampling and upsampling
1502
1507 template <class T>
1508 Sequence2<T> downsample(const Sequence2<T>& f, int factorX, int factorY)
1509 {
1510 assert(factorX >= 1 && factorY >= 1);
1511 int startX = ceilDiv(f.getStartX(), factorX) * factorX;
1512 int startY = ceilDiv(f.getStartY(), factorY) * factorY;
1513 int width = ceilDiv(f.getEndX() - startX, factorX);
1514 int height = ceilDiv(f.getEndY() - startY, factorY);
1515 Sequence2<T> result(roundTowardZeroDiv(startX, factorX),
1516 roundTowardZeroDiv(startY, factorY), width, height);
1517
1518 for (int i = 0; i < height; ++i) {
1519 typename Sequence2<T>::ConstXIterator srcIter =
1520 f.rowBegin(startY + factorY * i) + (startX - f.getStartX());
1521 typename Sequence2<T>::XIterator dstIter =
1522 result.rowBegin(result.getStartY() + i);
1523 int n = result.getWidth();
1524 while (--n >= 0) {
1525 *dstIter = *srcIter;
1526 ++dstIter;
1527 srcIter += factorX;
1528 }
1529 }
1530
1531 return result;
1532 }
1533
1541 template <class T>
1542 Sequence2<T> upsample(const Sequence2<T>& f, int factorX, int factorY)
1543 {
1544 return upsample(f, factorX, factorY, 0, 0);
1545 }
1546
1554 template <class T>
1555 Sequence2<T> upsample(const Sequence2<T>& f, int factorX, int factorY,
1556 int padX, int padY)
1557 {
1558 assert(factorX >= 1 && factorY >= 1);
1559 assert(padX >= 0 && padX < factorX);
1560 assert(padY >= 0 && padY < factorY);
1561
1562 Sequence2<T> result(factorX * f.getStartX(), factorY * f.getStartY(),
1563 f.getWidth() + std::max((f.getWidth() - 1), 0) * (factorX - 1) + padX,
1564 f.getHeight() + std::max((f.getHeight() - 1), 0) * (factorY - 1) + padY);
1565 int srcY = f.getStartY();
1566 int dstY = result.getStartY();
1567 int rowCount = f.getHeight();
1568
1569 while (rowCount > 0) {
1570 typename Sequence2<T>::ConstXIterator srcIter = f.rowBegin(srcY);
1571 typename Sequence2<T>::XIterator dstIter = result.rowBegin(dstY);
1572 int count = f.getWidth();
1573
1574 while (count > 0) {
1575 *dstIter = *srcIter;
1576 ++srcIter;
1577 ++dstIter;
1578 for (int k = (count > 1) * (factorX - 1); k > 0; --k) {
1579 *dstIter = T(0);
1580 ++dstIter;
1581 }
1582 --count;
1583 }
1584 for (int k = padX; k > 0; --k) {
1585 *dstIter = T(0);
1586 ++dstIter;
1587 }
1588 ++srcY;
1589 ++dstY;
1590
1591 for (int k = (rowCount > 1) * (factorY - 1); k > 0; --k) {
1592 std::fill_n(result.rowBegin(dstY), result.getWidth(), T(0));
1593 ++dstY;
1594 }
1595 --rowCount;
1596 }
1597
1598 for (int k = padY; k > 0; --k) {
1599 assert(dstY < result.getEndY());
1600 std::fill_n(result.rowBegin(dstY), result.getWidth(), T(0));
1601 ++dstY;
1602 }
1603
1604 return result;
1605 }
1606
1608 // Polyphase decompositions
1610
1623 template <class T>
1624 Array2<Sequence2<T> > polyphaseSplit(const Sequence2<T>& seq, int typeX,
1625 int numPhasesX, int typeY, int numPhasesY)
1626 {
1627 assert(numPhasesX >= 2);
1628 assert(numPhasesY >= 2);
1629 Array2<Sequence2<T> > result(numPhasesX, numPhasesY);
1630 for (int j = 0; j < numPhasesY; ++j) {
1631 for (int i = 0; i < numPhasesX; ++i) {
1632 int offsetX = getCosetOffset(typeX, numPhasesX, i);
1633 int offsetY = getCosetOffset(typeY, numPhasesY, j);
1634 result(i, j) = downsample(translate(seq, offsetX, offsetY),
1635 numPhasesX, numPhasesY);
1636 }
1637 }
1638 return result;
1639 }
1640
1652 template <class T>
1653 Sequence2<T> polyphaseJoin(const Array2<Sequence2<T> >& comps, int typeX,
1654 int typeY)
1655 {
1656 const int numPhasesX = comps.getWidth();
1657 const int numPhasesY = comps.getHeight();
1658 assert(numPhasesX >= 2);
1659 assert(numPhasesY >= 2);
1660 Sequence2<T> seq;
1661 for (int j = 0; j < numPhasesY; ++j) {
1662 for (int i = 0; i < numPhasesX; ++i) {
1663 int offsetX = getCosetOffset(typeX, numPhasesX, i);
1664 int offsetY = getCosetOffset(typeY, numPhasesY, j);
1665 //std::cerr << "XXX " << i << " " << j << " " << upsample(comps(i, j), numPhasesX, numPhasesY) << "\n";
1666 seq = add(seq, translate(upsample(comps(i, j), numPhasesX,
1667 numPhasesY), -offsetX, -offsetY));
1668 }
1669 }
1670 return seq;
1671 }
1672
1674 // Types.
1676
1678 typedef Sequence2<double> RealSequence2;
1679
1681 typedef Sequence2<int> IntSequence2;
1682
1684 //
1686
1691 }
1692
1693 #endif
1694
SPL::roundTowardZeroDiv
long roundTowardZeroDiv(long x, long y)
Compute a quotient with the result rounded towards zero.
Definition: math.hpp:152
Array2.hpp
This file contains the Array2 template class and its supporting code.
SPL::Sequence2::operator()
T & operator()(int x, int y)
Get a mutable reference to the specified element in the sequence.
Definition: Sequence2.hpp:707
SPL::Sequence2::getEndY
int getEndY() const
Get the y-coordinate of the end index for the sequence.
Definition: Sequence2.hpp:666
SPL::Sequence2::YIterator
Array2< T >::YIterator YIterator
The mutable iterator for the elements in a column of the sequence.
Definition: Sequence2.hpp:110
SPL::Sequence2::swapArray
void swapArray(Array2< T > &data)
Swap the data for the underlying array and the specified array.
Definition: Sequence2.hpp:925
SPL::Sequence1
A one-dimensional sequence class with lazy copying and reference counting.
Definition: Sequence1.hpp:85
SPL::Sequence2::ElemType
T ElemType
The type of the element in the sequence.
Definition: Sequence2.hpp:92
SPL::convolveSeparable
Sequence2< T > convolveSeparable(const Sequence2< T > &f, const Sequence1< T > &horzFilt, const Sequence1< T > &vertFilt, int mode=ConvolveMode::full)
Compute the convolution of a sequence with two 1-D filters (i.e., convolution with a separable filter...
Definition: Sequence2.hpp:1475
SPL_SEQUENCE2_INLINE
#define SPL_SEQUENCE2_INLINE
Allow the inlining of functions.
Definition: Sequence2.hpp:50
SPL
Definition: Arcball.hpp:48
SPL::Sequence2::getStartY
int getStartY() const
Get the y-coordinate of the start index for the sequence.
Definition: Sequence2.hpp:654
SPL::Sequence2::end
ConstIterator end() const
Get a const iterator for one past the last element in the sequence.
Definition: Sequence2.hpp:731
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::Sequence2::getStartX
int getStartX() const
Get the x-coordinate of the start index for the sequence.
Definition: Sequence2.hpp:648
SPL::Sequence2::rowEnd
ConstXIterator rowEnd(int y) const
Get a const iterator for one past the end in the specified row of the sequence.
Definition: Sequence2.hpp:761
SPL::Sequence2::fill
void fill(const T &value)
Get a copy of the underlying array.
Definition: Sequence2.hpp:919
SPL::Sequence2::getWidth
int getWidth() const
Get the width of the sequence.
Definition: Sequence2.hpp:672
SPL::Sequence2::max
T max() const
Get the maximum element in the sequence.
Definition: Sequence2.hpp:823
SPL::Sequence2::operator+=
Sequence2 & operator+=(const Sequence2 &f)
Add another sequence to this one.
Definition: Sequence2.hpp:560
SPL::Sequence2::colEnd
ConstYIterator colEnd(int x) const
Get a const iterator for one past the end in the specified column of the sequence.
Definition: Sequence2.hpp:793
SPL::Array2::ConstXIterator
std::vector< T >::const_iterator ConstXIterator
A constant iterator for elements of a row in the array.
Definition: Array2.hpp:231
SPL::ConvolveMode::full
static const int full
The full convolution result (i.e., the same as "full" in MATLAB)
Definition: Sequence.hpp:57
SPL::approxEqual
SPL_SEQUENCE2_INLINE bool approxEqual(const Sequence2< T > &f, const Sequence2< T > &g, T threshold=1e-9)
Test two sequences for approximate equality.
Definition: Sequence2.hpp:1173
SPL::operator/
SPL_SEQUENCE2_INLINE Sequence2< T > operator/(const Sequence2< T > &f, const T &value)
Divide a sequence by a scalar.
Definition: Sequence2.hpp:1126
SPL::Sequence2::operator*=
Sequence2 & operator*=(const Sequence2 &f)
Multiply elementwise this sequence by another one.
Definition: Sequence2.hpp:586
SPL::Sequence2::colBegin
ConstYIterator colBegin(int x) const
Get a const iterator for the first element in the specified column of the sequence.
Definition: Sequence2.hpp:777
SPL::operator+
SPL_SEQUENCE2_INLINE Sequence2< T > operator+(const Sequence2< T > &f, const T &value)
Add a value to a sequence.
Definition: Sequence2.hpp:1070
SPL::ceilDiv
long ceilDiv(long x, long y)
Compute the ceiling of a quotient.
Definition: math.hpp:212
SPL::ConvolveMode::sameDomainPerExt
static const int sameDomainPerExt
Periodic extension.
Definition: Sequence.hpp:66
SPL::Sequence2::getHeight
int getHeight() const
Get the height of the sequence.
Definition: Sequence2.hpp:678
SPL::ConvolveMode::sameDomainConstExt
static const int sameDomainConstExt
Constant extension.
Definition: Sequence.hpp:63
SPL::Sequence2::~Sequence2
~Sequence2()
The destructor.
Definition: Sequence2.hpp:519
SPL::operator==
bool operator==(const Sequence2< T > &f, const Sequence2< T > &g)
Test two sequences for equality.
Definition: Sequence2.hpp:1141
SPL::Sequence2::ConstYIterator
Array2< T >::ConstYIterator ConstYIterator
The const iterator for the elements in a column of the sequence.
Definition: Sequence2.hpp:107
math.hpp
This file contains various mathematical functions/code.
SPL::subsequence
Sequence2< T > subsequence(const Sequence2< T > &f, int startX, int startY, int width, int height)
Extract a subsequence from a sequence.
Definition: Sequence2.hpp:1218
SPL::polyphaseSplit
Array2< Sequence2< T > > polyphaseSplit(const Sequence2< T > &seq, int typeX, int numPhasesX, int typeY, int numPhasesY)
Split a sequence into its polyphase components.
Definition: Sequence2.hpp:1624
SPL::Sequence2::operator=
Sequence2 & operator=(const Sequence2 &f)
The assignment operator.
Definition: Sequence2.hpp:535
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::Array2::Iterator
std::vector< T >::iterator Iterator
A mutable iterator for all elements in the array.
Definition: Array2.hpp:222
SPL::operator>>
std::istream & operator>>(std::istream &in, Sequence2< T > &f)
Input a sequence from a stream.
Definition: Sequence2.hpp:881
SPL::Sequence2::XIterator
Array2< T >::XIterator XIterator
The mutable iterator for the elements in a row of the sequence.
Definition: Sequence2.hpp:104
SPL::Sequence2::rowBegin
ConstXIterator rowBegin(int y) const
Get a const iterator for the first element in the specified row of the sequence.
Definition: Sequence2.hpp:745
SPL::Array2::YIterator
YIter< T > YIterator
A mutable iterator for elements of a column in the array.
Definition: Array2.hpp:234
SPL::ConvolveMode::sameDomainSymExt0
static const int sameDomainSymExt0
Symmetric periodic extension.
Definition: Sequence.hpp:69
SPL::Sequence2::translate
Sequence2 & translate(int x, int y)
Translate (i.e., shift) a sequence by the specified displacement.
Definition: Sequence2.hpp:937
SPL::Sequence2::operator-=
Sequence2 & operator-=(const Sequence2 &f)
Subtract another sequence from this one.
Definition: Sequence2.hpp:573
Sequence1.hpp
This file contains code for the Sequence1 template class.
SPL::operator-
SPL_SEQUENCE2_INLINE Sequence2< T > operator-(const Sequence2< T > &f, const T &value)
Subtract a value from a sequence.
Definition: Sequence2.hpp:1084
SPL::Array2
A two-dimensional array class with lazy copying and reference counting.
Definition: Array2.hpp:83
SPL::Sequence2::Sequence2
Sequence2()
The default constructor.
Definition: Sequence2.hpp:468
SPL::Sequence2::Iterator
Array2< T >::Iterator Iterator
The mutable iterator for all elements in the sequence.
Definition: Sequence2.hpp:98
SPL::ConvolveMode::sameDomainZeroExt
static const int sameDomainZeroExt
The same as "same" in MATLAB.
Definition: Sequence.hpp:60
SPL::Sequence2::min
T min() const
Get the minimum element in the sequence.
Definition: Sequence2.hpp:816
SPL::Array2::ConstYIterator
YIter< const T > ConstYIterator
A constant iterator for elements of a column in the array.
Definition: Array2.hpp:237
SPL::Sequence2::getSize
int getSize() const
Get the number of elements in the sequence.
Definition: Sequence2.hpp:684
SPL::polyphaseJoin
Sequence2< T > polyphaseJoin(const Array2< Sequence2< T > > &comps, int typeX, int typeY)
Reassemble a sequence from its polyphase components.
Definition: Sequence2.hpp:1653
SPL::upsample
Sequence2< T > upsample(const Sequence2< T > &f, int factorX, int factorY, int padX, int padY)
Upsample a sequence in each of the horizontal and vertical directions by the specified factors...
Definition: Sequence2.hpp:1555
SPL::translate
SPL_SEQUENCE2_INLINE Sequence2< T > translate(const Sequence2< T > &f, int deltaX, int deltaY)
Translate a sequence by the specified amount.
Definition: Sequence2.hpp:1248
SPL::operator!=
SPL_SEQUENCE2_INLINE bool operator!=(const Sequence2< T > &f, const Sequence2< T > &g)
Test two sequences for inequality.
Definition: Sequence2.hpp:1163
SPL::convolve
Sequence2< T > convolve(const Sequence2< T > &f, const Sequence2< T > &g, int mode)
Compute the convolution of two sequences.
Definition: Sequence2.hpp:1424
SPL::Sequence1::getSize
int getSize() const
Get the length of the sequence.
Definition: Sequence1.hpp:618
SPL::Sequence2::getArray
Array2< T > getArray() const
Get a copy of the underlying array.
Definition: Sequence2.hpp:931
SPL::Array2::XIterator
Iterator XIterator
A mutable iterator for elements of a row in the array.
Definition: Array2.hpp:228
SPL::Sequence2::sum
T sum() const
Get the sum of the elements in the sequence.
Definition: Sequence2.hpp:830
SPL::Sequence2::operator/=
Sequence2 & operator/=(const Sequence2 &f)
Divide elementwise this sequence by another one.
Definition: Sequence2.hpp:599
SPL::add
Sequence2< T > add(const Sequence2< T > &f, const Sequence2< T > &g)
Compute the sum of two sequences with potentially differing domains.
Definition: Sequence2.hpp:1017
SPL::Sequence2
A two-dimensional sequence class with lazy copying and reference counting.
Definition: Sequence2.hpp:83
SPL::Array2::ConstIterator
std::vector< T >::const_iterator ConstIterator
A constant iterator for all elements in the array.
Definition: Array2.hpp:225
SPL::operator*
SPL_SEQUENCE2_INLINE Sequence2< T > operator*(const Sequence2< T > &f, const T &value)
Compute a scalar multiple of a sequence.
Definition: Sequence2.hpp:1112
SPL::RealSequence2
Sequence2< double > RealSequence2
Real sequence.
Definition: Sequence2.hpp:1678
SPL::Sequence2::getEndX
int getEndX() const
Get the x-coordinate of the end index for the sequence.
Definition: Sequence2.hpp:660
SPL::Sequence2::ConstXIterator
Array2< T >::ConstXIterator ConstXIterator
The const iterator for the elements in a row of the sequence.
Definition: Sequence2.hpp:101
SPL::IntSequence2
Sequence2< int > IntSequence2
Integer sequence.
Definition: Sequence2.hpp:1681
SPL::Sequence2::ConstIterator
Array2< T >::ConstIterator ConstIterator
The const iterator for all elements in the sequence.
Definition: Sequence2.hpp:95
SPL::Sequence2::begin
ConstIterator begin() const
Get a const iterator for the first element in the sequence.
Definition: Sequence2.hpp:718
SPL::Sequence2::isShared
bool isShared() const
Is the array for this sequence shared with another array?
Definition: Sequence2.hpp:690
SPL::Sequence1::begin
ConstIterator begin() const
Get an iterator referencing the first element in the sequence.
Definition: Sequence1.hpp:652
SPL::Sequence2::output
std::ostream & output(std::ostream &out, int fieldWidth) const
Output a sequence to the specified stream using the given field width for each sequence element...
Definition: Sequence2.hpp:840
SPL::downsample
Sequence2< T > downsample(const Sequence2< T > &f, int factorX, int factorY)
Downsample a sequence in each of the horizontal and vertical directions by the specified factors...
Definition: Sequence2.hpp:1508