1 #ifndef CLONEVECTOR_H
2 #define CLONEVECTOR_H
3
4 #include "Vector.h"
5 #include <algorithm>
6
7 namespace ATC_matrix {
8
9 /**
10 * @class CloneVector
11 * @brief Class for creating objects that wrap matrix data for manipulation through vector operations
12 */
13
14 template<typename T>
15 class CloneVector : public Vector<T>
16 {
17 public:
18 CloneVector(); // do not implement
19 CloneVector(const Vector<T> &c);
20 CloneVector(const Matrix<T> &c, int dim, INDEX idx=0);
21 CloneVector(const DiagonalMatrix<T> &c, INDEX idx=0);
22
23 // overloaded virtual functions
24 T& operator[](INDEX i);
25 T operator[](INDEX i) const;
26 T operator()(INDEX i, INDEX j=0) const;
27 T& operator()(INDEX i, INDEX j=0);
28 INDEX nRows() const;
29
30 CloneVector<T>& operator=(const T &v);
31 CloneVector<T>& operator=(const CloneVector<T> &C);
32 CloneVector<T>& operator=(const Matrix<T> &C);
33
34 virtual bool memory_contiguous() const;
35 T* ptr() const;
36 void resize(INDEX nRows, INDEX nCols=0, bool copy=false);
37 void reset(INDEX nRows, INDEX nCols=0, bool zero=true);
38 void copy(const T * ptr, INDEX nRows, INDEX nCols=0);
39
40 private:
41 void _resize(INDEX nRows, INDEX nCols, bool copy, bool zero);
42
43 Vector<T> * const _baseV; // ptr to a base vector
44 Matrix<T> * const _baseM; // ptr to a base matrix
45 int _clone_type; // what to clone (see enum CLONE_TYPE)
46 INDEX _idx; // index of matrix dimension to clone
47 };
48 ///////////////////////////////////////////////////////////////////////////////
49 // Template definitions ///////////////////////////////////////////////////////
50 //-----------------------------------------------------------------------------
51 // Construct from another vector
52 //-----------------------------------------------------------------------------
53 template<typename T>
CloneVector(const Vector<T> & c)54 CloneVector<T>::CloneVector(const Vector<T> &c)
55 : Vector<T>(), _baseV(const_cast<Vector<T>*>(&c)), _baseM(nullptr)
56 {}
57 //-----------------------------------------------------------------------------
58 // Construct from a matrix, the const_cast isn't pretty
59 /* CloneVector(const Matrix<T> &c, int dim, INDEX idx)
60 / attaches to a slice of a matrix
61 / Arguments: c = pointer to the matrix
62 / dim = type of slice CLONE_ROW, CLONE_COL, CLONE_DIAG
63 / idx = index of row or column (no effect on diag currently)
64 */
65 //-----------------------------------------------------------------------------
66 template<typename T>
CloneVector(const Matrix<T> & c,int dim,INDEX idx)67 CloneVector<T>::CloneVector(const Matrix<T> &c, int dim, INDEX idx)
68 : Vector<T>(), _baseV(nullptr), _baseM(const_cast<Matrix<T>*>(&c))
69 , _clone_type(dim), _idx(idx)
70 {}
71 //-----------------------------------------------------------------------------
72 // Construct from a DiagonalMatrix
73 //-----------------------------------------------------------------------------
74 template<typename T>
CloneVector(const DiagonalMatrix<T> & c,INDEX)75 CloneVector<T>::CloneVector(const DiagonalMatrix<T> &c, INDEX /* idx */)
76 : Vector<T>(), _baseV(nullptr), _baseM(const_cast<DiagonalMatrix<T>*>(&c))
77 , _clone_type(CLONE_DIAG), _idx(0)
78 {}
79 //-----------------------------------------------------------------------------
80 // value (const) indexing operator
81 //-----------------------------------------------------------------------------
82 template<typename T>
operator()83 T CloneVector<T>::operator()(INDEX i, INDEX /* j */) const
84 {
85 return (*this)[i];
86 }
87 //-----------------------------------------------------------------------------
88 // reference index operator
89 //-----------------------------------------------------------------------------
90 template<typename T>
operator()91 T& CloneVector<T>::operator()(INDEX i, INDEX /* j */)
92 {
93 return (*this)[i];
94 }
95 //-----------------------------------------------------------------------------
96 // Indexes the cloned vector either from another vector or a matrix
97 //-----------------------------------------------------------------------------
98 template<typename T>
99 T CloneVector<T>::operator[](INDEX i) const
100 {
101 if (_baseV) return (*_baseV)(i);
102 if (_clone_type == CLONE_ROW) return (*_baseM)(_idx, i);
103 else if (_clone_type == CLONE_COL) return (*_baseM)(i,_idx);
104 else if (_clone_type == CLONE_DIAG) return (*_baseM)(i,i);
105 return 0;
106 }
107 //-----------------------------------------------------------------------------
108 // Indexes the cloned vector either from another vector or a matrix
109 //-----------------------------------------------------------------------------
110 template<typename T>
111 T& CloneVector<T>::operator[](INDEX i)
112 {
113 if (_baseV) return (*_baseV)(i);
114 if (_clone_type == CLONE_ROW) return (*_baseM)(_idx, i);
115 if (_clone_type == CLONE_COL) return (*_baseM)(i,_idx);
116 if (_clone_type == CLONE_DIAG) return (*_baseM)(i,i);
117 return (*_baseV)(i);
118 }
119 //-----------------------------------------------------------------------------
120 // Returns the size of the base vector or of the row/col of the base matrix
121 //-----------------------------------------------------------------------------
122 template<typename T>
nRows()123 INDEX CloneVector<T>::nRows() const
124 {
125 if (_baseV) return _baseV->size();
126 if (_clone_type == CLONE_ROW) return _baseM->nCols();
127 if (_clone_type == CLONE_COL) return _baseM->nRows();
128 if (_clone_type == CLONE_DIAG) return std::min(_baseM->nRows(), _baseM->nCols());
129 return 0;
130 }
131 //-----------------------------------------------------------------------------
132 // assigns all elements to a constant
133 //-----------------------------------------------------------------------------
134 template<typename T>
135 CloneVector<T>& CloneVector<T>::operator=(const T &v)
136 {
137 this->set_all_elements_to(v);
138 return *this;
139 }
140 //-----------------------------------------------------------------------------
141 // assigns all elements to the corresponding elements in C
142 //-----------------------------------------------------------------------------
143 template<typename T>
144 CloneVector<T>& CloneVector<T>::operator=(const CloneVector<T> &C)
145 {
146 GCK(*this, C, this->size()!=C.size(), "Error in CloneVector:operator=");
147 int sz = this->size();
148 for (INDEX i = 0; i < sz; i++) (*this)[i] = C[i];
149 return *this;
150 }
151 //-----------------------------------------------------------------------------
152 // assigns all elements to the corresponding elements in C
153 //-----------------------------------------------------------------------------
154 template<typename T>
155 CloneVector<T>& CloneVector<T>::operator=(const Matrix<T> &C)
156 {
157 GCK(*this, C, this->size()!=C.size(), "Error in CloneVector:operator=");
158 int sz = this->size();
159 for (INDEX i = 0; i < sz; i++) (*this)[i] = C[i];
160 return *this;
161 }
162 //-----------------------------------------------------------------------------
163 // returns true only if its guaranteed memory is contiguous
164 //-----------------------------------------------------------------------------
165 template<typename T>
memory_contiguous()166 bool CloneVector<T>::memory_contiguous() const
167 {
168 // drill down through clone of clones
169 if (_baseV) return _baseV->memory_contiguous();
170 // could be okay if DiagonalMatrix, but can't guarantee this
171 if (_clone_type == CLONE_DIAG) return false;
172 #ifdef ROW_STORAGE
173 return _clone_type == CLONE_ROW;
174 #else
175 return _clone_type == CLONE_COL;
176 #endif
177 }
178 //-----------------------------------------------------------------------------
179 // Returns a pointer to the data unless the data is a column of a matrix
180 //-----------------------------------------------------------------------------
181 template<typename T>
ptr()182 T* CloneVector<T>::ptr() const
183 {
184 if (_baseV) return _baseV->ptr();
185 #ifdef ROW_STORAGE
186 if (_clone_type == CLONE_ROW) return _baseM->ptr() + this->size()*_idx;
187 if (_clone_type == CLONE_COL) return _baseM->ptr() + this->size();
188 if (_clone_type == CLONE_DIAG) return _baseM->ptr();
189 #else
190 if (_clone_type == CLONE_COL) return _baseM->ptr() + this->size()*_idx;
191 if (_clone_type == CLONE_ROW) return _baseM->ptr() + this->size();
192 if (_clone_type == CLONE_DIAG) return _baseM->ptr();
193 #endif
194 return 0;
195 }
196 //-----------------------------------------------------------------------------
197 // general resize function, can handle parents that are matrices or vectors
198 //-----------------------------------------------------------------------------
199 template<typename T>
_resize(INDEX nRows,INDEX nCols,bool copy,bool zero)200 void CloneVector<T>::_resize(INDEX nRows, INDEX nCols, bool copy, bool zero)
201 {
202 if (_baseV)
203 {
204 if (copy) _baseV->resize(nRows, nCols, copy);
205 else _baseV->reset (nRows, nCols, zero);
206 return;
207 }
208 // parent is a matrix, need to decide what the Vector is cloning
209 switch (_clone_type)
210 {
211 case CLONE_ROW: // now the leading dimension is rows
212 nCols = nCols ? nCols : _baseM->nCols();
213 break;
214 case CLONE_COL: // now the leading dimension is columns
215 nCols = nCols ? nCols : _baseM->nRows();
216 ATC_Utility::swap(nRows, nCols);
217 break;
218 case CLONE_DIAG: // lets just hope you knew what you were doing
219 break;
220 default:
221 return;
222 }
223 if (zero) _baseM->reset(nRows, nCols, zero); // zero overrides copy
224 else _baseM->resize(nRows, nCols, copy);
225 }
226 //-----------------------------------------------------------------------------
227 // resizes the matrix and optionally copies what fits
228 //-----------------------------------------------------------------------------
229 template<typename T>
resize(INDEX nRows,INDEX nCols,bool copy)230 void CloneVector<T>::resize(INDEX nRows, INDEX nCols, bool copy)
231 {
232 _resize(nRows, nCols, copy, false);
233 }
234 //-----------------------------------------------------------------------------
235 // resizes the matrix and optionally zeros it out
236 //-----------------------------------------------------------------------------
237 template<typename T>
reset(INDEX nRows,INDEX nCols,bool zero)238 void CloneVector<T>::reset(INDEX nRows, INDEX nCols, bool zero)
239 {
240 _resize(nRows, nCols, false, zero);
241 }
242 //-----------------------------------------------------------------------------
243 // resizes the matrix and copies data
244 //-----------------------------------------------------------------------------
245 template<typename T>
copy(const T * ptr,INDEX nRows,INDEX nCols)246 void CloneVector<T>::copy(const T * ptr, INDEX nRows, INDEX nCols)
247 {
248 _resize(nRows, nCols, false, false);
249 memcpy(this->ptr(), ptr, this->size()*sizeof(T));
250 }
251
252 } // end namespace
253 #endif
254