PtrVector.h
1 /* Copyright (C) 2012-2020 IBM Corp.
2  * This program is Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0
6  * Unless required by applicable law or agreed to in writing, software
7  * distributed under the License is distributed on an "AS IS" BASIS,
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and
10  * limitations under the License. See accompanying LICENSE file.
11  */
12 #ifndef HELIB_PTRVECTOR_H
13 #define HELIB_PTRVECTOR_H
14 
19 #include <stdexcept>
20 #include <climits>
21 #include <vector>
22 #include <NTL/vector.h>
23 
24 #include <helib/assertions.h>
25 #include <helib/apiAttributes.h>
26 
27 namespace helib {
28 
30 template <typename T>
31 struct PtrVector
32 {
33  virtual T* operator[](long) const = 0;
34  // NOTE: the PtrVector is const, but the pointer T* is not
35  virtual long size() const = 0;
36 
37  virtual void resize(long newSize, UNUSED const PtrVector* another = nullptr)
38  {
39  if (size() != newSize)
40  throw LogicError("Cannot resize a generic PtrVector");
41  }
42  virtual ~PtrVector() {}
43 
44  bool isSet(long i) const
45  {
46  if (i < 0 || i >= size())
47  return false;
48  return ((*this)[i] != nullptr);
49  }
50 
51  // How many non-null entries there are (beginning at startFrom)
52  virtual long numNonNull(long first = 0, long last = LONG_MAX) const
53  {
54  if (first < 0)
55  first = 0;
56  if (last > size())
57  last = size();
58  long count = 0;
59  for (long i = first; i < last; i++)
60  if ((*this)[i] != nullptr)
61  count++;
62  return count;
63  }
64 
65  // Return a pointer to some non-Null T, if it can find one.
66  // This is convenient since T may not have an empty constructor
67  virtual const T* ptr2nonNull() const
68  {
69  for (long i = 0; i < size(); i++) {
70  T* pt = (*this)[i];
71  if (pt != nullptr)
72  return pt;
73  }
74  return nullptr;
75  }
76 };
77 
78 // This header provides five implementations of these interfaces, but
79 // users can define their own as needed. The ones defined here are:
80 
81 // struct PtrVector_VecT; // constructed as PtrVector_VecT(NTL::Vec<T>)
82 // struct PtrVector_VecPt; // constructed as PtrVector_VecPt(NTL::Vec<T*>)
83 // struct PtrVector_vectorT; // constructed as PtrVector_vectorT(std::vector<T>)
84 // struct PtrVector_vectorPt;// constructed PtrVector_vectorPt(std::vector<T*>)
85 
86 // struct PtrVector_slice;// A slice, PtrVector_slice(PtrVector, start, length)
87 
88 template <typename T>
89 long lsize(const PtrVector<T>& v)
90 {
91  return v.size();
92 }
93 template <typename T>
95 {
96  v.resize(0);
97 }
98 template <typename T>
99 void resize(PtrVector<T>& v, long newSize, const T& val);
100 // implementation of resize function below
101 template <typename T>
102 void resize(PtrVector<T>& v, long newSize, const T* val)
103 {
104  resize<T>(v, newSize, *val);
105 }
106 
107 // Templates for element-wise vector-copy
108 
109 // Generic version for std::vector, NTL::Vec
110 template <typename V1, typename V2>
111 void vecCopy(V1& v1, const V2& v2, long sizeLimit = 0)
112 {
113  int n = lsize(v2);
114  if (sizeLimit > 0 && sizeLimit < n)
115  n = sizeLimit;
116  if (n == 0)
117  setLengthZero(v1);
118  else {
119  resize(v1, n, v2[0]);
120  for (int i = 0; i < n; i++)
121  v1[i] = v2[i];
122  }
123 }
124 
125 // Specializations for PtrVector
126 template <typename V, typename T> // V is either Vec<T> or vector<T>
127 void vecCopy(V& v1, const PtrVector<T>& v2, long sizeLimit = 0)
128 {
129  int n = lsize(v2);
130  if (sizeLimit > 0 && sizeLimit < n)
131  n = sizeLimit;
132  if (n == 0)
133  setLengthZero(v1);
134  else {
135  resize(v1, n, *(v2[0]));
136  for (int i = 0; i < n; i++)
137  v1[i] = *(v2[i]);
138  }
139 }
140 template <typename V, typename T> // V is either Vec<T> or vector<T>
141 void vecCopy(PtrVector<T>& v1, const V& v2, long sizeLimit = 0)
142 {
143  int n = lsize(v2);
144  if (sizeLimit > 0 && sizeLimit < n)
145  n = sizeLimit;
146  if (n == 0)
147  setLengthZero(v1);
148  else {
149  resize(v1, n, v2[0]);
150  for (int i = 0; i < n; i++)
151  *(v1[i]) = v2[i];
152  }
153 }
154 template <typename T> // V is either Vec<T> or vector<T>
155 void vecCopy(PtrVector<T>& v1, const PtrVector<T>& v2, long sizeLimit = 0)
156 {
157  int n = lsize(v2);
158  if (sizeLimit > 0 && sizeLimit < n)
159  n = sizeLimit;
160  if (n == 0)
161  setLengthZero(v1);
162  else {
163  resize(v1, n, *(v2[0]));
164  for (int i = 0; i < n; i++)
165  *(v1[i]) = *(v2[i]);
166  }
167 }
168 
169 /*******************************************************************/
170 /* Implementation details: applications should not care about them */
171 /*******************************************************************/
172 
174 template <typename T>
176 {
177  NTL::Vec<T*>& v;
178  PtrVector_VecPt(NTL::Vec<T*>& _v) : v(_v) {}
179  T* operator[](long i) const override { return v[i]; }
180  long size() const override { return v.length(); }
181 
182  void resize(long newSize,
183  UNUSED const PtrVector<T>* another = nullptr) override
184  {
185  v.SetLength(newSize, nullptr);
186  }
187 };
188 
190 template <typename T>
192 {
193  std::vector<T*>& v;
194  PtrVector_vectorPt(std::vector<T*>& _v) : v(_v) {}
195  T* operator[](long i) const override { return v[i]; }
196  long size() const override { return long(v.size()); }
197 
198  void resize(long newSize,
199  UNUSED const PtrVector<T>* another = nullptr) override
200  {
201  v.resize(newSize, nullptr);
202  }
203 };
204 
206 template <typename T>
208 {
209  NTL::Vec<T>& v;
210  PtrVector_VecT(NTL::Vec<T>& _v) : v(_v) {}
211  T* operator[](long i) const override { return &(v[i]); }
212  long size() const override { return v.length(); }
213 
214  void resize(long newSize, const PtrVector<T>* another) override
215  {
216  if (newSize == 0)
217  setLengthZero(v);
218  else {
219  // Try to find a non-null pointer to T that you can give to resize
220  if (another == nullptr)
221  another = this;
222  const T* pt = another->ptr2nonNull();
223  assertNotNull(pt, "another->ptr2nonNull() returned a null ptr");
224  v.SetLength(newSize, *pt); // Do the actual resize
225  }
226  }
227 
228  long numNonNull(long first = 0, long last = LONG_MAX) const override
229  {
230  if (first < 0)
231  first = 0;
232  if (last > v.length())
233  last = v.length();
234  return last - first;
235  }
236  const T* ptr2nonNull() const override
237  {
238  return ((v.length() > 0) ? &(v[0]) : nullptr);
239  }
240 };
241 
243 template <typename T>
245 {
246  std::vector<T>& v;
247  PtrVector_vectorT(std::vector<T>& _v) : v(_v) {}
248  T* operator[](long i) const override { return &(v[i]); }
249  long size() const override { return long(v.size()); }
250 
251  void resize(long newSize, const PtrVector<T>* another) override
252  {
253  if (newSize == 0)
254  setLengthZero(v);
255  else {
256  // Try to find a non-null pointer to T that you can give to resize
257  if (another == nullptr)
258  another = this;
259  const T* pt = another->ptr2nonNull();
260  assertNotNull(pt, "another->ptr2nonNull() returned a null ptr");
261  v.resize(newSize, *pt); // do the actual resize
262  }
263  }
264  long numNonNull(long first = 0, long last = LONG_MAX) const override
265  {
266  if (first < 0)
267  first = 0;
268  if (last > long(v.size()))
269  last = long(v.size());
270  return last - first;
271  }
272 };
273 
275 template <typename T>
277 {
279  long start, sz;
280  // Special case for a slice of a slice
281  PtrVector_slice(const PtrVector_slice<T>& slice, long from, long _sz = -1) :
282  orig(slice.orig)
283  {
284  if (from < 0)
285  from = 0;
286  if (_sz == 0 || from >= slice.size()) { // empty slice
287  start = slice.orig.size();
288  sz = 0;
289  return;
290  }
291  // If we got here then 0 <= from < slice.size()
292  start = slice.start + from;
293 
294  if (_sz < 0 || from + _sz > slice.size()) // slice goes to end of slice
295  _sz = slice.size() - from;
296  sz = _sz;
297  }
298  // The general case: slice of a PtrVector
299  PtrVector_slice(const PtrVector<T>& _orig, long from, long _sz = -1) :
300  orig(_orig), start(from), sz(_sz)
301  {
302  if (start < 0)
303  start = 0;
304  else if (start > _orig.size())
305  start = _orig.size();
306  if (sz < 0 || sz > _orig.size() - start)
307  sz = _orig.size() - start;
308  }
309  T* operator[](long i) const override { return orig[i + start]; }
310  long size() const override { return sz; }
311 
312  long numNonNull(long first = 0, long last = LONG_MAX) const override
313  {
314  return orig.numNonNull(start + first, start + std::min(sz, last));
315  }
316  const T* ptr2nonNull() const override { return orig.ptr2nonNull(); }
317 };
318 
320 template <typename T>
322 {
323  const T* v;
324  PtrVector_Singleton(const T* _v) : v(_v) {}
325  T* operator[](long i) const override { return (i == 0) ? ((T*)v) : nullptr; }
326  long size() const override { return 1L; }
327 };
328 
329 template <typename T>
330 void resize(PtrVector<T>& v, long newSize, const T& val)
331 {
332  PtrVector_Singleton<T> t(&val);
333  v.resize(newSize, &t);
334 }
335 
336 } // namespace helib
337 
338 #endif // ifndef HELIB_PTRVECTOR_H
long start
Definition: PtrVector.h:279
long lsize(const std::vector< T > &v)
Size of STL vector as a long (rather than unsigned long)
Definition: NumbTh.h:702
PtrVector_slice(const PtrVector_slice< T > &slice, long from, long _sz=-1)
Definition: PtrVector.h:281
PtrVector_VecPt(NTL::Vec< T * > &_v)
Definition: PtrVector.h:178
const T * v
Definition: PtrVector.h:323
long size() const override
Definition: PtrVector.h:326
T * operator[](long i) const override
Definition: PtrVector.h:195
long numNonNull(long first=0, long last=LONG_MAX) const override
Definition: PtrVector.h:264
virtual T * operator[](long) const =0
void resize(long newSize, const PtrVector< T > *another) override
Definition: PtrVector.h:251
PtrVector_VecT(NTL::Vec< T > &_v)
Definition: PtrVector.h:210
Inherits from Exception and std::logic_error.
Definition: exceptions.h:68
PtrVector_vectorPt(std::vector< T * > &_v)
Definition: PtrVector.h:194
long size() const override
Definition: PtrVector.h:212
long numNonNull(long first=0, long last=LONG_MAX) const override
Definition: PtrVector.h:312
long size() const override
Definition: PtrVector.h:249
T * operator[](long i) const override
Definition: PtrVector.h:325
std::vector< T > & v
Definition: PtrVector.h:246
T * operator[](long i) const override
Definition: PtrVector.h:179
long size() const override
Definition: PtrVector.h:196
const T * ptr2nonNull() const override
Definition: PtrVector.h:236
long numNonNull(long first=0, long last=LONG_MAX) const override
Definition: PtrVector.h:228
An implementation of PtrVector using Vec<T>
Definition: PtrVector.h:208
const T * ptr2nonNull() const override
Definition: PtrVector.h:316
virtual ~PtrVector()
Definition: PtrVector.h:42
void resize(long newSize, UNUSED const PtrVector< T > *another=nullptr) override
Definition: PtrVector.h:182
void assertNotNull(const T &p, const std::string &message)
Definition: assertions.h:156
void setLengthZero(std::vector< T > &vec)
Definition: NumbTh.h:724
An implementation of PtrVector using vector<T*>
Definition: PtrVector.h:192
void resize(NTL::Vec< T > &v, long sz, const T &val)
Definition: NumbTh.h:744
PtrVector_vectorT(std::vector< T > &_v)
Definition: PtrVector.h:247
virtual long size() const =0
void resize(long newSize, UNUSED const PtrVector< T > *another=nullptr) override
Definition: PtrVector.h:198
long size() const override
Definition: PtrVector.h:310
virtual long numNonNull(long first=0, long last=LONG_MAX) const
Definition: PtrVector.h:52
Abstract class for an array of objects.
Definition: PtrVector.h:32
Definition: apiAttributes.h:21
virtual void resize(long newSize, UNUSED const PtrVector *another=nullptr)
Definition: PtrVector.h:37
void resize(long newSize, const PtrVector< T > *another) override
Definition: PtrVector.h:214
NTL::Vec< T * > & v
Definition: PtrVector.h:177
bool isSet(long i) const
Definition: PtrVector.h:44
void vecCopy(V1 &v1, const V2 &v2, long sizeLimit=0)
Definition: PtrVector.h:111
An implementation of PtrVector as a slice of another PtrVector.
Definition: PtrVector.h:277
T * operator[](long i) const override
Definition: PtrVector.h:211
An implementation of PtrVector using vector<T>
Definition: PtrVector.h:245
An implementation of PtrVector using Vec<T*>
Definition: PtrVector.h:176
std::vector< T * > & v
Definition: PtrVector.h:193
PtrVector_Singleton(const T *_v)
Definition: PtrVector.h:324
An implementation of PtrVector from a single T object.
Definition: PtrVector.h:322
long sz
Definition: PtrVector.h:279
T * operator[](long i) const override
Definition: PtrVector.h:309
NTL::Vec< T > & v
Definition: PtrVector.h:209
PtrVector_slice(const PtrVector< T > &_orig, long from, long _sz=-1)
Definition: PtrVector.h:299
T * operator[](long i) const override
Definition: PtrVector.h:248
const PtrVector< T > & orig
Definition: PtrVector.h:278
virtual const T * ptr2nonNull() const
Definition: PtrVector.h:67
long size() const override
Definition: PtrVector.h:180