1 /*
2     Scan Tailor - Interactive post-processing tool for scanned pages.
3     Copyright (C)  Joseph Artsimovich <joseph.artsimovich@gmail.com>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef VEC_T_H_
20 #define VEC_T_H_
21 
22 #include <boost/scoped_array.hpp>
23 #include <cassert>
24 #include <cstddef>
25 
26 /**
27  * \brief A (column) vector of elements of type T.
28  */
29 template <typename T>
30 class VecT {
31  public:
32   typedef T type;
33 
34   /**
35    * \brief Constructs an empty vector.
36    */
37   VecT();
38 
39   /**
40    * \brief Constructs a vector of specified size initialized with T().
41    */
42   explicit VecT(size_t size);
43 
44   /**
45    * \brief Constructs a vector of specified size initializing to the provided value.
46    */
47   VecT(size_t size, T initial_value);
48 
49   /**
50    * \brief Construction from an array of elements of possibly different type.
51    *
52    * Conversion is done by static casts.
53    */
54   template <typename OT>
55   explicit VecT(size_t size, const OT* data);
56 
57   /**
58    * Ordinary copy-construction.
59    */
60   VecT(const VecT& other);
61 
62   /**
63    * \brief Construction from a vector of a different type.
64    *
65    * Conversion is done by static casts.
66    */
67   template <typename OT>
68   explicit VecT(const VecT<OT>& other);
69 
70   /**
71    * \brief Ordinary assignment.
72    */
73   VecT& operator=(const VecT& other);
74 
75   /**
76    * \brief Assignment from a vector of a different type.
77    *
78    * Conversion is done by static casts.
79    */
80   template <typename OT>
81   VecT& operator=(const VecT<OT>& other);
82 
83   VecT& operator+=(const VecT& rhs);
84 
85   VecT& operator-=(const VecT& rhs);
86 
87   VecT& operator*=(T scalar);
88 
size()89   size_t size() const { return m_size; }
90 
data()91   const T* data() const { return m_data.get(); }
92 
data()93   T* data() { return m_data.get(); }
94 
95   const T& operator[](size_t idx) const {
96     assert(idx < m_size);
97 
98     return m_data[idx];
99   }
100 
101   T& operator[](size_t idx) {
102     assert(idx < m_size);
103 
104     return m_data[idx];
105   }
106 
107   void fill(const T& value);
108 
109   void swap(VecT& other);
110 
111  private:
112   boost::scoped_array<T> m_data;
113   size_t m_size;
114 };
115 
116 
117 template <typename T>
VecT()118 VecT<T>::VecT() : m_size(0) {}
119 
120 template <typename T>
VecT(size_t size)121 VecT<T>::VecT(size_t size)
122     : m_data(new T[size]()),
123       // The "()" will cause elements to be initialized to T().
124       m_size(size) {}
125 
126 template <typename T>
VecT(size_t size,T initial_value)127 VecT<T>::VecT(size_t size, T initial_value) : m_data(new T[size]), m_size(size) {
128   for (size_t i = 0; i < size; ++i) {
129     m_data[i] = initial_value;
130   }
131 }
132 
133 template <typename T>
134 template <typename OT>
VecT(size_t size,const OT * data)135 VecT<T>::VecT(size_t size, const OT* data) : m_data(new T[size]), m_size(size) {
136   for (size_t i = 0; i < size; ++i) {
137     m_data[i] = static_cast<T>(data[i]);
138   }
139 }
140 
141 template <typename T>
VecT(const VecT & other)142 VecT<T>::VecT(const VecT& other) : m_data(new T[other.m_size]), m_size(other.m_size) {
143   const T* other_data = other.data();
144   for (size_t i = 0; i < m_size; ++i) {
145     m_data[i] = other_data[i];
146   }
147 }
148 
149 template <typename T>
150 template <typename OT>
VecT(const VecT<OT> & other)151 VecT<T>::VecT(const VecT<OT>& other) : m_data(new T[other.m_size]), m_size(other.m_size) {
152   const T* other_data = other.data();
153   for (size_t i = 0; i < m_size; ++i) {
154     m_data[i] = other_data[i];
155   }
156 }
157 
158 template <typename T>
159 VecT<T>& VecT<T>::operator=(const VecT& other) {
160   VecT(other).swap(*this);
161 
162   return *this;
163 }
164 
165 template <typename T>
166 template <typename OT>
167 VecT<T>& VecT<T>::operator=(const VecT<OT>& other) {
168   VecT(other).swap(*this);
169 
170   return *this;
171 }
172 
173 template <typename T>
174 VecT<T>& VecT<T>::operator+=(const VecT& rhs) {
175   assert(m_size == rhs.m_size);
176   for (size_t i = 0; i < m_size; ++i) {
177     m_data[i] += rhs.m_data[i];
178   }
179 
180   return *this;
181 }
182 
183 template <typename T>
184 VecT<T>& VecT<T>::operator-=(const VecT& rhs) {
185   assert(m_size == rhs.m_size);
186   for (size_t i = 0; i < m_size; ++i) {
187     m_data[i] -= rhs.m_data[i];
188   }
189 
190   return *this;
191 }
192 
193 template <typename T>
194 VecT<T>& VecT<T>::operator*=(const T scalar) {
195   for (size_t i = 0; i < m_size; ++i) {
196     m_data[i] *= scalar;
197   }
198 
199   return *this;
200 }
201 
202 template <typename T>
fill(const T & value)203 void VecT<T>::fill(const T& value) {
204   for (size_t i = 0; i < m_size; ++i) {
205     m_data[i] = value;
206   }
207 }
208 
209 template <typename T>
swap(VecT & other)210 void VecT<T>::swap(VecT& other) {
211   size_t tmp = m_size;
212   m_size = other.m_size;
213   other.m_size = tmp;
214   m_data.swap(other.m_data);
215 }
216 
217 template <typename T>
swap(const VecT<T> & o1,const VecT<T> & o2)218 void swap(const VecT<T>& o1, const VecT<T>& o2) {
219   o1.swap(o2);
220 }
221 
222 template <typename T>
223 VecT<T> operator*(const VecT<T>& vec, double scalar) {
224   VecT<T> res(vec);
225   res *= scalar;
226 
227   return res;
228 }
229 
230 template <typename T>
231 VecT<T> operator*(double scalar, const VecT<T>& vec) {
232   VecT<T> res(vec);
233   res *= scalar;
234 
235   return res;
236 }
237 
238 #endif  // ifndef VEC_T_H_
239