5 #ifndef FML_CPU_CPUMAT_H
6 #define FML_CPU_CPUMAT_H
17 #include "../_internals/arraytools/src/arraytools.hpp"
19 #include "../_internals/rand.hh"
20 #include "../_internals/omp.hh"
21 #include "../_internals/print.hh"
22 #include "../_internals/types.hh"
23 #include "../_internals/unimat.hh"
35 template <
typename REAL>
51 void print(uint8_t ndigits=4,
bool add_final_blank=
true)
const;
60 void fill_runif(
const uint32_t seed,
const REAL min=0,
const REAL max=1);
61 void fill_runif(
const REAL min=0,
const REAL max=1);
62 void fill_rnorm(
const uint32_t seed,
const REAL mean=0,
const REAL sd=1);
63 void fill_rnorm(
const REAL mean=0,
const REAL sd=1);
67 void scale(
const REAL s);
74 REAL
get(
const len_t i)
const;
75 REAL
get(
const len_t i,
const len_t j)
const;
76 void set(
const len_t i,
const REAL v);
77 void set(
const len_t i,
const len_t j,
const REAL v);
89 bool free_on_destruct()
const {
return this->free_data;};
90 void dont_free_on_destruct() {this->free_data=
false;};
113 template <
typename REAL>
120 this->free_data =
true;
137 template <
typename REAL>
140 check_params(nrows, ncols);
144 this->free_data =
true;
146 if (this->m == 0 || this->n == 0)
149 size_t len = (size_t) nrows * ncols *
sizeof(REAL);
150 this->data = (REAL*) std::malloc(len);
151 if (this->data == NULL)
152 throw std::bad_alloc();
170 template <
typename REAL>
173 check_params(nrows, ncols);
179 this->free_data = free_on_destruct;
184 template <
typename REAL>
189 this->data = x.data_ptr();
191 this->free_data = x.free_on_destruct();
192 x.dont_free_on_destruct();
197 template <
typename REAL>
202 this->data.resize(this->m, this->n);
204 size_t len = (size_t) this->m * this->n *
sizeof(REAL);
205 std::memcpy(this->data, x.data_ptr(), len);
207 this->free_data =
true;
212 template <
typename REAL>
232 template <
typename REAL>
235 check_params(nrows, ncols);
237 const size_t len = (size_t) nrows * ncols *
sizeof(REAL);
238 const size_t oldlen = (size_t) this->m * this->n *
sizeof(REAL);
240 if ((nrows == 0 || ncols == 0) || (len == oldlen))
249 realloc_ptr = malloc(len);
251 realloc_ptr = realloc(this->data, len);
253 if (realloc_ptr == NULL)
254 throw std::bad_alloc();
256 this->data = (REAL*) realloc_ptr;
276 template <
typename REAL>
279 check_params(nrows, ncols);
287 this->free_data = free_on_destruct;
293 template <
typename REAL>
298 this->m = data_.
nrows();
299 this->n = data_.
ncols();
302 this->free_data =
false;
308 template <
typename REAL>
313 const size_t len = (size_t) this->m * this->n *
sizeof(REAL);
314 memcpy(cpy.
data_ptr(), this->data, len);
329 template <
typename REAL>
332 for (len_t i=0; i<this->m; i++)
334 for (len_t j=0; j<this->n; j++)
335 this->printval(this->data[i + this->m*j], ndigits);
337 fml::print::putchar(
'\n');
341 fml::print::putchar(
'\n');
347 template <
typename REAL>
350 fml::print::printf(
"# cpumat");
351 fml::print::printf(
" %dx%d", this->m, this->n);
352 fml::print::printf(
" type=%s",
typeid(REAL).name());
353 fml::print::printf(
"\n");
361 template <
typename REAL>
364 const size_t len = (size_t) this->m * this->n *
sizeof(REAL);
365 memset(this->data, 0, len);
375 template <
typename REAL>
378 #pragma omp parallel for if((this->m)*(this->n) > fml::omp::OMP_MIN_SIZE)
379 for (len_t j=0; j<this->n; j++)
382 for (len_t i=0; i<this->m; i++)
383 this->data[i + this->m*j] = v;
395 template <
typename T>
399 T stop = (T) (this->m * this->n);
400 this->fill_linspace(start, stop);
403 template <
typename REAL>
407 this->fill_val(start);
410 const REAL v = (stop-start)/((REAL) this->m*this->n - 1);
412 #pragma omp parallel for if((this->m)*(this->n) > fml::omp::OMP_MIN_SIZE)
413 for (len_t j=0; j<this->n; j++)
416 for (len_t i=0; i<this->m; i++)
418 const len_t ind = i + this->m*j;
419 this->data[ind] = v*((REAL) ind) + start;
429 this->fill_val(start);
432 const float v = (stop-start)/((
float) this->m*this->n - 1);
434 #pragma omp parallel for if((this->m)*(this->n) > fml::omp::OMP_MIN_SIZE)
435 for (len_t j=0; j<this->n; j++)
438 for (len_t i=0; i<this->m; i++)
440 const len_t ind = i + this->m*j;
441 this->data[ind] = (int) roundf(v*((
float) ind) + start);
450 template <
typename REAL>
469 template <
typename REAL>
475 len_t min = std::min(this->m, this->n);
478 for (len_t i=0; i<min; i++)
479 this->data[i + this->m*i] = v_d[i % v.
size()];
490 template <
typename REAL>
493 std::mt19937 mt(seed);
494 static std::uniform_real_distribution<REAL> dist(min, max);
496 for (len_t j=0; j<this->n; j++)
498 for (len_t i=0; i<this->m; i++)
499 this->data[i + this->m*j] = dist(mt);
504 template <
typename REAL>
507 uint32_t seed = fml::rand::get_seed();
508 this->fill_runif(seed, min, max);
519 template <
typename REAL>
522 std::mt19937 mt(seed);
523 static std::normal_distribution<REAL> dist(mean, sd);
525 for (len_t j=0; j<this->n; j++)
527 for (len_t i=0; i<this->m; i++)
528 this->data[i + this->m*j] = dist(mt);
533 template <
typename REAL>
536 uint32_t seed = fml::rand::get_seed();
537 this->fill_rnorm(seed, mean, sd);
555 template <
typename REAL>
558 const len_t minmn = std::min(this->m, this->n);
562 #pragma omp parallel for simd if(minmn > fml::omp::OMP_MIN_SIZE)
563 for (len_t i=0; i<minmn; i++)
564 v_ptr[i] = this->data[i + this->m*i];
583 template <
typename REAL>
586 const len_t minmn = std::min(this->m, this->n);
590 #pragma omp parallel for simd if(minmn > fml::omp::OMP_MIN_SIZE)
591 for (len_t i=0; i<minmn; i++)
592 v_ptr[i] = this->data[(this->m-1-i) + this->m*i];
602 template <
typename REAL>
605 #pragma omp parallel for if((this->m)*(this->n) > fml::omp::OMP_MIN_SIZE)
606 for (len_t j=0; j<this->n; j++)
609 for (len_t i=0; i<this->m; i++)
610 this->data[i + this->m*j] *= s;
617 template <
typename REAL>
620 for (len_t j=0; j<this->n; j++)
622 len_t last = this->m - 1;
623 for (len_t i=0; i<this->m/2; i++)
625 const REAL tmp = this->data[i + this->m*j];
626 this->data[i + this->m*j] = this->data[last + this->m*j];
627 this->data[last + this->m*j] = tmp;
637 template <
typename REAL>
640 len_t last = this->n - 1;
642 for (len_t j=0; j<this->n/2; j++)
644 for (len_t i=0; i<this->m; i++)
646 const REAL tmp = this->data[i + this->m*j];
647 this->data[i + this->m*j] = this->data[i + this->m*last];
648 this->data[i + this->m*last] = tmp;
658 template <
typename REAL>
661 for (len_t j=0; j<this->n; j++)
663 for (len_t i=0; i<this->m; i++)
665 if (isinf(this->data[i + this->m*j]))
676 template <
typename REAL>
679 for (len_t j=0; j<this->n; j++)
681 for (len_t i=0; i<this->m; i++)
683 if (isnan(this->data[i + this->m*j]))
704 template <
typename REAL>
707 this->check_index(i);
708 return this->data[i];
719 template <
typename REAL>
722 this->check_index(i, j);
723 return this->data[i + (this->m)*j];
736 template <
typename REAL>
739 this->check_index(i);
752 template <
typename REAL>
755 this->check_index(i, j);
756 this->data[i + (this->m)*j] = v;
774 template <
typename REAL>
777 if (i < 0 || i >= this->m)
778 throw std::logic_error(
"invalid matrix row");
783 #pragma omp parallel for simd if(this->n > fml::omp::OMP_MIN_SIZE)
784 for (len_t j=0; j<this->n; j++)
785 v_d[j] = this->data[i + this->m*j];
800 template <
typename REAL>
803 if (i < 0 || i >= this->m)
804 throw std::logic_error(
"invalid matrix row");
805 if (v.
size() != this->n)
806 throw std::runtime_error(
"non-conformable arguments");
809 #pragma omp parallel for simd if(this->n > fml::omp::OMP_MIN_SIZE)
810 for (len_t j=0; j<this->n; j++)
811 this->data[i + this->m*j] = v_d[j];
829 template <
typename REAL>
832 if (j < 0 || j >= this->n)
833 throw std::logic_error(
"invalid matrix column");
838 #pragma omp parallel for if(this->m > fml::omp::OMP_MIN_SIZE)
839 for (len_t i=0; i<this->m; i++)
840 v_d[i] = this->data[i + this->m*j];
855 template <
typename REAL>
858 if (j < 0 || j >= this->n)
859 throw std::logic_error(
"invalid matrix column");
860 if (v.
size() != this->m)
861 throw std::runtime_error(
"non-conformable arguments");
864 #pragma omp parallel for simd if(this->n > fml::omp::OMP_MIN_SIZE)
865 for (len_t i=0; i<this->m; i++)
866 this->data[i + this->m*j] = v_d[i];
879 template <
typename REAL>
882 if (this->m != x.
nrows() || this->n != x.
ncols())
884 else if (this->data == x.
data_ptr())
888 for (len_t j=0; j<this->n; j++)
890 for (len_t i=0; i<this->m; i++)
892 const REAL a = this->data[i + this->m*j];
893 const REAL b = x_d[i + this->m*j];
894 if (!arraytools::fltcmp::eq(a, b))
908 template <
typename REAL>
911 return !(*
this == x);
922 template <
typename REAL>
929 this->free_data = x.free_on_destruct();
930 x.dont_free_on_destruct();
936 template <
typename REAL>
943 this->free_data =
false;
954 template <
typename REAL>
957 if (this->free_data && this->data)
959 std::free(this->data);
966 template <
typename REAL>
969 if (nrows < 0 || ncols < 0)
970 throw std::runtime_error(
"invalid dimensions");