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