fml  0.1-0
Fused Matrix Library
cpuvec.hh
1 // This file is part of fml which is released under the Boost Software
2 // License, Version 1.0. See accompanying file LICENSE or copy at
3 // https://www.boost.org/LICENSE_1_0.txt
4 
5 #ifndef FML_CPU_CPUVEC_H
6 #define FML_CPU_CPUVEC_H
7 #pragma once
8 
9 
10 #include <cmath>
11 #include <cstdint>
12 #include <cstdlib>
13 #include <cstring>
14 #include <stdexcept>
15 
16 #include "../_internals/arraytools/src/arraytools.hpp"
17 
18 #include "../_internals/omp.hh"
19 #include "../_internals/print.hh"
20 #include "../_internals/univec.hh"
21 
22 
23 namespace fml
24 {
30  template <typename T>
31  class cpuvec : public univec<T>
32  {
33  public:
34  cpuvec();
35  cpuvec(len_t size);
36  cpuvec(T *data, len_t size, bool free_on_destruct=false);
37  cpuvec(cpuvec &&x);
38  cpuvec(const cpuvec &x);
39  ~cpuvec();
40 
41  void resize(len_t size);
42  void inherit(T *data, len_t size, bool free_on_destruct=false);
43  cpuvec<T> dupe() const;
44 
45  void print(uint8_t ndigits=4, bool add_final_blank=true) const;
46  void info() const;
47 
48  void fill_zero();
49  void fill_val(const T v);
50  void fill_linspace();
51  void fill_linspace(const T start, const T stop);
52 
53  void subset(const len_t start, const len_t stop, const bool interior=true);
54 
55  void scale(const T s);
56  void pow(const T p);
57  void rev();
58 
59  T sum() const;
60  T max() const;
61  T min() const;
62 
63  T get(const len_t i) const;
64  void set(const len_t i, const T v);
65 
66  bool operator==(const cpuvec<T> &x) const;
67  bool operator!=(const cpuvec<T> &x) const;
69  cpuvec<T>& operator=(const cpuvec<T> &x);
70 
71  protected:
72  bool free_on_destruct() const {return this->free_data;};
73  void dont_free_on_destruct() {this->free_data=false;};
74 
75  private:
76  void free();
77  void check_params(len_t size);
78  };
79 }
80 
81 
82 
83 // -----------------------------------------------------------------------------
84 // public
85 // -----------------------------------------------------------------------------
86 
87 // constructors/destructor
88 
96 template <typename T>
98 {
99  this->_size = 0;
100  this->data = NULL;
101 
102  this->free_data = true;
103 }
104 
105 
106 
119 template <typename T>
121 {
122  check_params(size);
123 
124  this->_size = size;
125  this->free_data = true;
126 
127  if (size == 0)
128  return;
129 
130  const size_t len = (size_t) size * sizeof(T);
131  this->data = (T*) std::malloc(len);
132  if (this->data == NULL)
133  throw std::bad_alloc();
134 }
135 
136 
137 
150 template <typename T>
151 fml::cpuvec<T>::cpuvec(T *data_, len_t size, bool free_on_destruct)
152 {
153  check_params(size);
154 
155  this->_size = size;
156  this->data = data_;
157 
158  this->free_data = free_on_destruct;
159 }
160 
161 
162 
163 template <typename T>
165 {
166  this->_size = x.size();
167  this->data = x.data_ptr();
168 
169  this->free_data = x.free_on_destruct();
170  x.dont_free_on_destruct();
171 }
172 
173 
174 
175 template <typename T>
176 fml::cpuvec<T>::cpuvec(const cpuvec<T> &x)
177 {
178  this->_size = x.size();
179  this->data.resize(this->_size);
180 
181  size_t len = (size_t) this->_size * sizeof(T);
182  std::memcpy(this->data, x.data_ptr(), len);
183 
184  this->free_data = true;
185 }
186 
187 
188 
189 template <typename T>
191 {
192  this->free();
193 }
194 
195 
196 
197 // memory management
198 
209 template <typename T>
210 void fml::cpuvec<T>::resize(len_t size)
211 {
212  check_params(size);
213 
214  if (size == 0)
215  {
216  this->_size = size;
217  return;
218  }
219  else if (this->_size == size)
220  return;
221 
222  const size_t len = (size_t) size * sizeof(T);
223 
224  void *realloc_ptr;
225  if (this->_size == 0)
226  realloc_ptr = malloc(len);
227  else
228  realloc_ptr = realloc(this->data, len);
229 
230  if (realloc_ptr == NULL)
231  throw std::bad_alloc();
232 
233  this->data = (T*) realloc_ptr;
234  this->_size = size;
235 }
236 
237 
238 
251 template <typename T>
252 void fml::cpuvec<T>::inherit(T *data, len_t size, bool free_on_destruct)
253 {
254  check_params(size);
255 
256  this->free();
257 
258  this->_size = size;
259  this->data = data;
260 
261  this->free_data = free_on_destruct;
262 }
263 
264 
265 
267 template <typename T>
269 {
270  fml::cpuvec<T> cpy(this->_size);
271 
272  const size_t len = (size_t) this->_size * sizeof(T);
273  memcpy(cpy.data_ptr(), this->data, len);
274 
275  return cpy;
276 }
277 
278 
279 
280 // printers
281 
288 template <typename T>
289 void fml::cpuvec<T>::print(uint8_t ndigits, bool add_final_blank) const
290 {
291  for (len_t i=0; i<this->_size; i++)
292  this->printval(this->data[i], ndigits);
293 
294  fml::print::putchar('\n');
295  if (add_final_blank)
296  fml::print::putchar('\n');
297 }
298 
299 
300 
302 template <typename T>
304 {
305  fml::print::printf("# cpuvec");
306  fml::print::printf(" %d", this->_size);
307  fml::print::printf(" type=%s", typeid(T).name());
308  fml::print::printf("\n");
309 }
310 
311 
312 
313 // fillers
314 
316 template <typename T>
318 {
319  const size_t len = (size_t) this->_size * sizeof(T);
320  memset(this->data, 0, len);
321 }
322 
323 
324 
330 template <typename T>
332 {
333  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE)
334  for (len_t i=0; i<this->_size; i++)
335  this->data[i] = v;
336 }
337 
338 
339 
346 template <typename T>
348 {
349  T start = 1;
350  T stop = (T) (this->_size);
351  this->fill_linspace(start, stop);
352 }
353 
354 template <typename REAL>
355 void fml::cpuvec<REAL>::fill_linspace(const REAL start, const REAL stop)
356 {
357  if (start == stop)
358  this->fill_val(start);
359  else
360  {
361  const REAL v = (stop-start)/((REAL) this->_size - 1);
362 
363  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE)
364  for (len_t i=0; i<this->_size; i++)
365  this->data[i] = v*((REAL) i) + start;
366  }
367 }
368 
369 template <>
370 inline void fml::cpuvec<int>::fill_linspace(const int start, const int stop)
371 {
372  if (start == stop)
373  this->fill_val(start);
374  else
375  {
376  const float v = (stop-start)/((float) this->_size - 1);
377 
378  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE)
379  for (len_t i=0; i<this->_size; i++)
380  this->data[i] = (int) roundf(v*((float) i) + start);
381  }
382 }
383 
384 
385 
386 template <typename REAL>
387 void fml::cpuvec<REAL>::subset(const len_t start, const len_t stop, const bool interior)
388 {
389  len_t size_new = interior ? stop-start : this->_size - (stop-start);
390  size_t len = size_new * sizeof(REAL);
391  REAL *data_new = (REAL*) malloc(len);
392  if (data_new == NULL)
393  throw std::bad_alloc();
394 
395  if (interior)
396  std::memcpy(data_new, this->data + start, len);
397  else
398  {
399  len_t n = std::max(start-1, 0);
400  std::memcpy(data_new, this->data, n*sizeof(REAL));
401  if (stop < this->_size)
402  {
403  n = this->_size-stop;
404  std::memcpy(data_new, this->data + stop, n*sizeof(REAL));
405  }
406  }
407 
408  std::free(this->data);
409  this->data = data_new;
410  this->_size = size_new;
411 }
412 
413 
414 
420 template <typename T>
421 void fml::cpuvec<T>::scale(const T s)
422 {
423  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE)
424  for (len_t i=0; i<this->_size; i++)
425  this->data[i] *= s;
426 }
427 
428 
429 
435 template <typename T>
436 void fml::cpuvec<T>::pow(const T p)
437 {
438  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE)
439  for (len_t i=0; i<this->_size; i++)
440  this->data[i] = std::pow(this->data[i], p);
441 }
442 
443 
444 
446 template <typename T>
448 {
449  len_t j = this->_size - 1;
450 
451  for (len_t i=0; i<this->_size/2; i++)
452  {
453  const T tmp = this->data[i];
454  this->data[i] = this->data[j];
455  this->data[j] = tmp;
456  j--;
457  }
458 }
459 
460 
461 
463 template <typename T>
465 {
466  T s = 0;
467 
468  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE) reduction(+:s)
469  for (len_t i=0; i<this->_size; i++)
470  s += this->data[i];
471 
472  return s;
473 }
474 
475 
476 
478 template <typename T>
480 {
481  T mx = this->data[0];
482 
483  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE) reduction(max:mx)
484  for (len_t i=1; i<this->_size; i++)
485  {
486  if (mx < this->data[i])
487  mx = this->data[i];
488  }
489 
490  return mx;
491 }
492 
493 
494 
496 template <typename T>
498 {
499  T mn = this->data[0];
500 
501  #pragma omp parallel for simd if(this->_size > fml::omp::OMP_MIN_SIZE) reduction(min:mn)
502  for (len_t i=1; i<this->_size; i++)
503  {
504  if (mn < this->data[i])
505  mn = this->data[i];
506  }
507 
508  return mn;
509 }
510 
511 
512 
513 // operators
514 
523 template <typename T>
524 T fml::cpuvec<T>::get(const len_t i) const
525 {
526  this->check_index(i);
527  return this->data[i];
528 }
529 
539 template <typename T>
540 void fml::cpuvec<T>::set(const len_t i, const T v)
541 {
542  this->check_index(i);
543  this->data[i] = v;
544 }
545 
546 
547 
556 template <typename T>
558 {
559  if (this->_size != x.size())
560  return false;
561  else if (this->data == x.data_ptr())
562  return true;
563 
564  const T *x_d = x.data_ptr();
565  for (len_t i=0; i<this->_size; i++)
566  {
567  const T a = this->data[i];
568  const T b = x_d[i];
569  if (!arraytools::fltcmp::eq(a, b))
570  return false;
571  }
572 
573  return true;
574 }
575 
582 template <typename T>
584 {
585  return !(*this == x);
586 }
587 
588 
589 
596 template <typename T>
598 {
599  this->_size = x.size();
600  this->data = x.data_ptr();
601 
602  this->free_data = x.free_on_destruct();
603  x.dont_free_on_destruct();
604 
605  return *this;
606 }
607 
608 template <typename T>
610 {
611  this->_size = x.size();
612  this->data = x.data_ptr();
613 
614  this->free_data = false;
615 
616  return *this;
617 }
618 
619 
620 
621 // -----------------------------------------------------------------------------
622 // private
623 // -----------------------------------------------------------------------------
624 
625 template <typename T>
627 {
628  if (this->free_data && this->data)
629  {
630  std::free(this->data);
631  this->data = NULL;
632  }
633 }
634 
635 
636 
637 template <typename REAL>
638 void fml::cpuvec<REAL>::check_params(len_t size)
639 {
640  if (size < 0)
641  throw std::runtime_error("invalid dimensions");
642 }
643 
644 
645 #endif
fml::univec
Base vector class. Not meant for direct use. Instead see cpuvec and gpuvec.
Definition: univec.hh:22
fml::cpuvec::print
void print(uint8_t ndigits=4, bool add_final_blank=true) const
Copy data from a CPU object to another.
Definition: cpuvec.hh:289
fml::univec::data_ptr
T * data_ptr()
Pointer to the internal array.
Definition: univec.hh:28
fml::cpuvec::resize
void resize(len_t size)
Resize the internal object storage.
Definition: cpuvec.hh:210
fml::cpuvec::cpuvec
cpuvec()
Construct vector object with no internal allocated storage.
Definition: cpuvec.hh:97
fml::cpuvec::rev
void rev()
Reverse the vector.
Definition: cpuvec.hh:447
fml::cpuvec
Vector class for data held on a single CPU.
Definition: cpuvec.hh:31
fml::cpuvec::get
T get(const len_t i) const
Get the specified value.
Definition: cpuvec.hh:524
fml::cpuvec::fill_linspace
void fill_linspace()
Set values to linearly spaced numbers.
Definition: cpuvec.hh:347
fml::cpuvec::fill_val
void fill_val(const T v)
Set all values to input value.
Definition: cpuvec.hh:331
fml::cpuvec::scale
void scale(const T s)
Multiply all values by the input value.
Definition: cpuvec.hh:421
fml::cpuvec::operator==
bool operator==(const cpuvec< T > &x) const
See if the two objects are the same.
Definition: cpuvec.hh:557
fml::cpuvec::max
T max() const
Maximum value of the vector.
Definition: cpuvec.hh:479
fml
Core namespace.
Definition: dimops.hh:10
fml::cpuvec::pow
void pow(const T p)
Raise every value of the vector to the given power.
Definition: cpuvec.hh:436
fml::univec::size
len_t size() const
Number of elements in the vector.
Definition: univec.hh:26
fml::cpuvec::set
void set(const len_t i, const T v)
Set the storage at the specified index with the provided value.
Definition: cpuvec.hh:540
fml::cpuvec::sum
T sum() const
Sum the vector.
Definition: cpuvec.hh:464
fml::cpuvec::fill_zero
void fill_zero()
Set all values to zero.
Definition: cpuvec.hh:317
fml::cpuvec::operator!=
bool operator!=(const cpuvec< T > &x) const
See if the two objects are not the same. Uses same internal logic as the == method.
Definition: cpuvec.hh:583
fml::cpuvec::inherit
void inherit(T *data, len_t size, bool free_on_destruct=false)
Set the internal object storage to the specified array.
Definition: cpuvec.hh:252
fml::cpuvec::operator=
cpuvec< T > & operator=(cpuvec< T > &x)
Operator that sets the LHS to a shallow copy of the input. Desctruction of the LHS object will not re...
Definition: cpuvec.hh:597
fml::cpuvec::dupe
cpuvec< T > dupe() const
Duplicate the object in a deep copy.
Definition: cpuvec.hh:268
fml::cpuvec::min
T min() const
Minimum value of the vector.
Definition: cpuvec.hh:497
fml::cpuvec::info
void info() const
Print some brief information about the object.
Definition: cpuvec.hh:303