19 #include "base_utility.h"
20 #include "lapack_connector.h"
25 typedef std::function<int(
const int& nr,
const int& ir,
const int& nc,
const int& ic)> Indx_picker_2d;
26 typedef std::function<void(
const int& indx,
const int& nr,
int& ir,
const int& nc,
int& ic)> Indx_folder_2d;
29 inline int flatid_rm(
const int &nr,
const int &ir,
const int &nc,
const int &ic) {
return ir*nc+ic; }
31 inline int flatid_cm(
const int &nr,
const int &ir,
const int &nc,
const int &ic) {
return ic*nr+ir; }
35 inline void foldid_rm(
const int& indx,
const int &nr,
int &ir,
const int &nc,
int &ic) { ir = indx / nc; ic = indx % nc; }
37 inline void foldid_cm(
const int& indx,
const int &nr,
int &ir,
const int &nc,
int &ic) { ir = indx % nr; ic = indx / nr; }
45 const Indx_picker_2d Indx_pickers_2d[]
50 const Indx_folder_2d Indx_folders_2d[]
58 void get_nr_nc_from_nested_vector(
const std::vector<std::vector<T>> &nested_vec,
int &nr,
int &nc)
60 nr = nested_vec.size();
62 for (
const auto& v: nested_vec)
63 nc_ = v.size() > nc_? v.size() : nc_;
68 void expand_nested_vector_to_pointer(
const std::vector<std::vector<T>> &nested_vector,
const int &nr,
const int &nc, T* c,
bool row_major =
true)
71 get_nr_nc_from_nested_vector(nested_vector, nr_, nc_);
72 if (nr < nr_) nr_ = nr;
73 if (nc < nc_) nc_ = nc;
75 const Indx_picker_2d picker = Indx_pickers_2d[int(!row_major)];
79 for (
int ir = 0; ir < nr_; ir++)
80 for (
int ic = 0; ic < std::min(
size_t(nc_), nested_vector[ir].size()); ic++)
81 c[picker(nr, ir, nc, ic)] = nested_vector[ir][ic];
90 std::shared_ptr<std::array<int, 2>> dim =
nullptr;
91 std::shared_ptr<std::valarray<T>> data =
nullptr;
98 mrank_ = std::min((*dim)[0], (*dim)[1]);
99 size_ = (*dim)[0] * (*dim)[1];
105 dim = std::make_shared<std::array<int, 2>>();
110 dim = std::make_shared<std::array<int, 2>>(dim_in);
113 data = std::make_shared<std::valarray<T>>(size());
115 matrix_data(
const std::array<int, 2> &dim_in,
const std::valarray<T> &data_in)
117 dim = std::make_shared<std::array<int, 2>>(dim_in);
118 data = std::make_shared<std::valarray<T>>(data_in);
121 matrix_data(
const std::array<int, 2> &dim_in,
const T*
const pdata)
123 dim = std::make_shared<std::array<int, 2>>(dim_in);
126 data = std::make_shared<std::valarray<T>>(pdata, size());
129 const std::shared_ptr<std::valarray<T>> &data_in)
132 dim = std::make_shared<std::array<int, 2>>(dim_in);
135 matrix_data(
const std::shared_ptr<std::array<int, 2>> &dim_in,
136 const std::shared_ptr<std::valarray<T>> &data_in)
137 : dim(dim_in), data(data_in)
142 inline int nr()
const {
return (*dim)[0]; }
143 inline int nc()
const {
return (*dim)[1]; }
144 inline int size()
const {
return size_; }
145 inline int mrank()
const {
return mrank_; }
148 inline T &operator[](
const int i) {
return (*data)[i]; }
149 inline const T &operator[](
const int i)
const {
return (*data)[i]; }
151 inline T* ptr() {
return &(*this->data)[0]; }
152 inline const T* ptr()
const {
return &(*this->data)[0]; }
153 inline std::shared_ptr<std::valarray<T>> sptr() {
return data; }
154 inline const std::shared_ptr<std::valarray<T>> sptr()
const {
return data; }
156 void resize(
const std::array<int, 2>& dim_new)
163 data = std::make_shared<std::valarray<T>>(0, size());
168 data->resize(size());
174 void reshape(
const std::array<int, 2>& dim_new)
176 assert(dim_new[0] * dim_new[1] == size());
183 if (data !=
nullptr && mdata.data !=
nullptr)
184 *data += *(mdata.data);
189 if (data !=
nullptr && mdata.data !=
nullptr)
190 *data -= *(mdata.data);
194 template <
typename T>
197 if (mdata1.nr() != mdata2.nr() || mdata1.nc() != mdata2.nc())
199 if (mdata1.sptr() ==
nullptr || mdata2.sptr() ==
nullptr)
201 using real_t =
typename to_real<T>::type;
202 const bool is_double = std::is_same<T, double>::value;
203 const real_t thres = is_double ? 1e-14 : 1e-6;
204 auto diff = std::abs(*(mdata1.data) - *(mdata2.data));
205 for (
int i = 0; i < mdata1.size(); i++)
206 if (::get_real(diff[i]) > thres)
211 template <
typename T>
217 static const bool is_double = std::is_same<T, double>::value;
224 Indx_picker_2d indx_picker_2d_;
226 Indx_folder_2d indx_folder_2d_;
232 void assign_value(
const T &v)
237 void assign_value(
const T*
const pv, MAJOR major_pv)
239 if (major_ == major_pv)
241 for (
int i = 0; i < size(); i++) dataobj[i] = pv[i];
245 const Indx_picker_2d pv_picker = Indx_pickers_2d[major_pv];
246 for (
int ir = 0; ir < nr(); ir++)
247 for (
int ic = 0; ic < nc(); ic++)
248 this->at(ir, ic) = pv[pv_picker(nr(), ir, nc(), ic)];
254 ld_ = (major_ == MAJOR::ROW ? nc() : nr());
257 void set_indx_picker_folder()
259 indx_picker_2d_ = Indx_pickers_2d[major_];
260 indx_folder_2d_ = Indx_folders_2d[major_];
265 using real_t =
typename to_real<T>::type;
266 using cplx_t =
typename to_cplx<T>::type;
269 matrix_m() : major_(MAJOR::ROW), ld_(0), dataobj()
272 set_indx_picker_folder();
274 matrix_m(
const int &nrows,
const int &ncols, MAJOR major = MAJOR::ROW): major_(major), ld_(0), dataobj({nrows, ncols})
277 set_indx_picker_folder();
280 matrix_m(
const int &nrows,
const int &ncols,
const T *
const parr, MAJOR major = MAJOR::ROW): major_(major), ld_(0), dataobj({nrows, ncols}, parr)
283 set_indx_picker_folder();
285 matrix_m(
const int &nrows,
const int &ncols,
const T *
const parr, MAJOR major_arr, MAJOR major): major_(major), ld_(0), dataobj({nrows, ncols})
288 set_indx_picker_folder();
290 assign_value(parr, major_arr);
292 matrix_m(
const int &nrows,
const int &ncols,
const std::shared_ptr<std::valarray<T>> &valarr, MAJOR major_valarr): major_(major_valarr), ld_(0), dataobj({nrows, ncols}, valarr)
295 set_indx_picker_folder();
298 matrix_m(
const std::vector<std::vector<T>> &nested_vector, MAJOR major = MAJOR::ROW): major_(major), ld_(0), dataobj()
301 get_nr_nc_from_nested_vector(nested_vector, nr_, nc_);
302 dataobj.resize({nr_, nc_});
304 set_indx_picker_folder();
306 expand_nested_vector_to_pointer(nested_vector, nr_, nc_, dataobj.ptr(), is_row_major());
327 void set_diag(
const T& v)
329 for (
int i = 0; i < mrank(); i++)
333 void scale_row(
int irow,
const T &scale)
335 for (
int ic = 0; ic < nc(); ic++)
336 this->at(irow, ic) *= scale;
339 void scale_col(
int icol,
const T &scale)
341 for (
int ir = 0; ir < nr(); ir++)
342 this->at(ir, icol) *= scale;
346 void randomize(
const T &lb = 0,
const T &ub = 1,
bool symmetrize =
false,
bool hermitian =
false)
348 static std::default_random_engine e(time(0));
349 std::uniform_real_distribution<real_t> dr(::get_real(lb), ::get_real(ub));
352 std::uniform_real_distribution<real_t> di(::get_imag(lb), ::get_imag(ub));
355 for (
int i = 0; i != mrank(); i++)
357 join_re_im((*
this)(i, i), dr(e), di(e));
358 for (
int j = i + 1; j < mrank(); j++)
360 join_re_im((*
this)(i, j), dr(e), di(e));
361 (*this)(j, i) = (*
this)(i, j);
367 for (
int i = 0; i != mrank(); i++)
369 join_re_im((*
this)(i, i), dr(e), real_t(0.0));
370 for (
int j = i + 1; j < mrank(); j++)
372 join_re_im((*
this)(i, j), dr(e), di(e));
373 (*this)(j, i) = ::get_conj((*
this)(i, j));
378 for (
int i = 0; i != size(); i++)
379 join_re_im(this->dataobj[i], dr(e), di(e));
384 for (
int i = 0; i != mrank(); i++)
386 this->at(i, i) = dr(e);
387 for (
int j = i + 1; j < mrank(); j++)
389 this->at(i, j) = dr(e);
390 this->at(j, i) = this->at(i, j);
395 for (
int i = 0; i != size(); i++)
396 this->dataobj[i] = dr(e);
402 int nr()
const {
return dataobj.nr(); }
403 int nc()
const {
return dataobj.nc(); }
405 int ld()
const {
return ld_; }
406 MAJOR major()
const {
return major_; }
407 int size()
const {
return dataobj.size(); }
408 int mrank()
const {
return dataobj.mrank(); }
410 bool is_row_major()
const {
return major_ == MAJOR::ROW; }
411 bool is_col_major()
const {
return major_ == MAJOR::COL; }
414 T &operator()(
const int ir,
const int ic) {
return this->at(ir, ic); }
415 const T &operator()(
const int ir,
const int ic)
const {
return this->at(ir, ic); }
416 T &at(
const int ir,
const int ic) {
return dataobj[indx_picker_2d_(nr(), ir, nc(), ic)]; }
417 const T &at(
const int ir,
const int ic)
const {
return dataobj[indx_picker_2d_(nr(), ir, nc(), ic)]; }
419 T* ptr() {
return dataobj.ptr(); }
420 const T* ptr()
const {
return dataobj.ptr(); }
421 std::shared_ptr<std::valarray<T>> sptr() {
return dataobj.sptr(); }
422 const std::shared_ptr<std::valarray<T>> sptr()
const {
return dataobj.sptr(); }
431 void swap_to_row_major()
435 int nr_old = nr(), nc_old = nc();
437 reshape(nr_old, nc_old);
440 set_indx_picker_folder();
443 void swap_to_col_major()
447 int nr_old = nr(), nc_old = nc();
449 reshape(nr_old, nc_old);
452 set_indx_picker_folder();
463 (dataobj.data)->fill(cnum);
467 template <
typename T1>
470 assert(size() == m.size() && major() == m.major());
471 for (
int i = 0; i < size(); i++)
472 dataobj[i] += m.dataobj[i];
474 template <
typename T1>
475 void operator+=(
const std::vector<T1> &v)
477 assert(nc() == v.size());
478 for (
int i = 0; i < nr(); i++)
479 for (
int ic = 0; ic < nc(); ic++)
480 this->at(i, ic) += v[ic];
482 template <
typename T1>
483 void operator+=(
const T1 &cnum)
485 for (
int i = 0; i < size(); i++)
489 template <
typename T1>
492 assert(size() == m.size() && major() == m.major());
493 for (
int i = 0; i < size(); i++)
494 dataobj[i] -= m.dataobj[i];
496 template <
typename T1>
497 void operator-=(
const std::vector<T1> &v)
499 assert(nc() == v.size());
500 for (
int i = 0; i < nr(); i++)
501 for (
int ic = 1; ic < nc(); ic++)
502 this->at(i, ic) += v[ic];
504 template <
typename T1>
505 void operator-=(
const T1 &cnum)
507 for (
int i = 0; i < size(); i++)
510 template <
typename T1>
511 void operator*=(
const T1 &cnum)
513 for (
int i = 0; i < size(); i++)
516 template <
typename T1>
517 void operator/=(
const T1 &cnum)
519 for (
int i = 0; i < size(); i++)
523 void reshape(
int nrows_new,
int ncols_new)
525 assert(size() == nrows_new * ncols_new);
526 dataobj.reshape({nrows_new, ncols_new});
530 dataobj.resize({nrows_new, ncols_new});
536 matrix_m<T>& resize(
int nrows_new,
int ncols_new, MAJOR major)
539 set_indx_picker_folder();
540 return this->resize(nrows_new, ncols_new);
546 for (
int i = 0; i < this->size(); i++)
547 dataobj[i] = get_conj(dataobj[i]);
551 matrix_m<T> get_transpose(
bool conjugate =
false)
const
554 for (
int i = 0; i < nr(); i++)
555 for (
int j = 0; j < nc(); j++)
556 m_trans(j, i) = this->at(i, j);
557 if (conjugate) m_trans.conj();
567 for (
int i = 0; i != n; i++)
568 for (
int j = i + 1; j < n; j++)
570 T temp = dataobj[i * n + j];
571 dataobj[i * n + j] = dataobj[j * n + i];
572 dataobj[j * n + i] = temp;
580 std::valarray<T> a_new(size());
581 for (
int i = 0; i < nr(); i++)
582 for (
int j = 0; j < nc(); j++)
583 a_new[indx_picker_2d_(nc(), j, nr(), i)] = this->at(i, j);
584 *(dataobj.data) = a_new;
587 if (conjugate) conj();
594 for (
int i = 0; i < size(); i++)
595 m.dataobj[i] = dataobj[i];
602 for (
int i = 0; i < size(); i++)
603 m.dataobj[i] = ::get_real(dataobj[i]);
610 for (
int i = 0; i < size(); i++)
611 m.dataobj[i] = ::get_imag(dataobj[i]);
615 int count_absle(real_t thres)
const
618 for (
int i = 0; i < size(); i++)
619 if (std::abs(dataobj[i]) <= thres) count++;
623 int count_absge(real_t thres)
const
626 for (
int i = 0; i < size(); i++)
627 if (std::abs(dataobj[i]) >= thres) count++;
631 void argmin(
int &ir,
int &ic)
const
634 const std::function<real_t(T)> filter =
636 real_t value = std::numeric_limits<real_t>::max();
638 for (
int i = 0; i < size(); i++)
639 if (filter(dataobj[i]) < value)
642 value = filter(dataobj[i]);
644 indx_folder_2d_(indx, nr(), ir, nc(), ic);
647 void argmax(
int &ir,
int &ic)
const
650 const std::function<real_t(T)> filter =
652 real_t value = std::numeric_limits<real_t>::min();
654 for (
int i = 0; i < size(); i++)
655 if (filter(dataobj[i]) > value)
658 value = filter(dataobj[i]);
660 indx_folder_2d_(indx, nr(), ir, nc(), ic);
666 const std::function<real_t(T)> filter =
668 real_t value = std::numeric_limits<real_t>::max();
669 for (
int i = 0; i < size(); i++)
670 if (filter(dataobj[i]) < value)
672 value = filter(dataobj[i]);
680 const std::function<real_t(T)> filter =
682 real_t value = std::numeric_limits<real_t>::min();
683 for (
int i = 0; i < size(); i++)
684 if (filter(dataobj[i]) > value)
686 value = filter(dataobj[i]);
691 real_t absmin()
const
694 for (
int i = 0; i < size(); i++)
695 value = std::min(value, std::abs(dataobj[i]));
699 real_t absmax()
const
702 for (
int i = 0; i < size(); i++)
703 value = std::max(value, std::abs(dataobj[i]));
713 template <
typename T1,
typename T2>
716 return m1.major() == m2.major();
719 template <
typename T1,
typename T2>
722 return std::is_same<T1, T2>::value;
726 template <
typename T1,
typename T2>
729 assert(src.size() == dest.size() && same_major(src, dest));
730 for (
int i = 0; i < src.size(); i++)
731 dest.dataobj[i] = src.dataobj[i];
735 template <
typename T>
738 assert(src.size() == dest.size() && same_major(src, dest));
739 memcpy(dest.ptr(), src.ptr(), src.size() *
sizeof(T));
742 template <
typename T1,
typename T2>
745 assert(m1.nc() == m2.nc() && m1.nr() == m2.nr() && same_major(m1, m2));
746 auto sum = m1.copy();
751 template <
typename T1,
typename T2>
754 assert(m.nc() == v.size());
755 auto mnew = m.copy();
760 template <
typename T,
typename T2>
768 template <
typename T1,
typename T2>
774 template <
typename T1,
typename T2>
777 assert(m1.nc() == m2.nc() && m1.nr() == m2.nr());
778 auto mnew = m1.copy();
783 template <
typename T1,
typename T2>
786 assert(m.nc() == v.size());
787 auto mnew = m.copy();
793 template <
typename T>
796 assert(m1.nc() == m2.nr());
797 assert(m1.nr() == prod.nr());
798 assert(m2.nc() == prod.nc());
799 assert(m1.major() == m2.major() && m1.major() == prod.major());
801 if (m1.is_row_major())
803 LapackConnector::gemm(
'N',
'N', m1.nr(), m2.nc(), m1.nc(),
804 T(1.0), m1.ptr(), m1.nc(), m2.ptr(), m2.nc(), T(0.0), prod.ptr(), prod.nc());
808 LapackConnector::gemm_f(
'N',
'N', m1.nr(), m2.nc(), m1.nc(),
809 T(1.0), m1.ptr(), m1.nr(), m2.ptr(), m2.nr(), T(0.0), prod.ptr(), prod.nr());
813 template <
typename T>
816 assert(m1.nc() == m2.nr());
817 assert(m1.major() == m2.major());
819 auto major = m1.major();
822 matmul<T>(m1, m2, prod);
830 assert(m1.nc() == m2.nr());
832 for (
int ir = 0; ir < m1.nr(); ir++)
833 for (
int ik = 0; ik < m1.nc(); ik++)
834 for (
int ic = 0; ic < m2.nc(); ic++)
835 prod(ir, ic) += m1(ir, ik) * m2(ik, ic);
839 template <
typename T1,
typename T2>
847 template <
typename T1,
typename T2>
853 template <
typename T>
854 std::ostream& operator<<(std::ostream& os,
const matrix_m<T> &m)
861 template <
typename T>
864 assert(m.major() == m_inv.major());
868 int ipiv[std::min(m.nr(), m.nc())];
869 m_inv.resize(m.nr(), m.nc());
873 if (m.is_row_major())
875 LapackConnector::getrf(m_inv.nr(), m_inv.nc(), m_inv.ptr(), m_inv.nr(), ipiv, info);
876 LapackConnector::getri(m_inv.nr(), m_inv.ptr(), m_inv.nr(), ipiv, work, lwork, info);
880 LapackConnector::getrf_f(m_inv.nr(), m_inv.nc(), m_inv.ptr(), m_inv.nr(), ipiv, info);
881 LapackConnector::getri_f(m_inv.nr(), m_inv.ptr(), m_inv.nr(), ipiv, work, lwork, info);
883 m_inv.reshape(m_inv.nc(), m_inv.nr());
887 template <
typename T>
890 return m.get_transpose(conjugate);
894 template <
typename T>
897 return m.copy().conj();
901 template <
typename T>
905 int lwork = m_copy.nr();
907 int mrank = std::min(m_copy.nr(), m_copy.nc());
911 if (m_copy.is_row_major())
912 LapackConnector::getrf(m_copy.nr(), m_copy.nc(), m_copy.ptr(), m_copy.nr(), ipiv, info);
914 LapackConnector::getrf_f(m_copy.nr(), m_copy.nc(), m_copy.ptr(), m_copy.nr(), ipiv, info);
916 for (
int i = 0; i < mrank; i++)
919 det *=
static_cast<T
>(2*int(ipiv[i] == (i+1))-1) * m_copy(i, i);
924 template <
typename T>
926 T power,
bool filter_original,
927 const T &threshold = -1.e5)
931 assert (mat.nr() == mat.nc());
932 const char jobz =
'V';
933 const char uplo =
'U';
934 const int n = mat.nr();
937 nb = LapackConnector::ilaenv(1,
"zheev",
"VU", n, -1, -1, -1);
939 nb = LapackConnector::ilaenv(1,
"cheev",
"VU", n, -1, -1, -1);
941 int lwork = mat.nc() * (nb+1);
945 std::complex<T> work[lwork];
946 if (mat.is_row_major())
947 LapackConnector::heev(jobz, uplo, n, mat.ptr(), n, w, work, lwork, rwork, info);
949 LapackConnector::heev_f(jobz, uplo, n, mat.ptr(), n, w, work, lwork, rwork, info);
950 bool is_int_power = fabs(power -
int(power)) < 1e-8;
958 for (
int i = 0; i != n; i++ )
960 if (w[i] < 0 && w[i] > threshold && !is_int_power)
961 lib_printf(
"Warning! kept negative eigenvalue with non-integer power: # %d ev = %f , pow = %f\n", i, w[i], power);
962 if (fabs(w[i]) < 1e-10 && power < 0)
963 lib_printf(
"Warning! nearly-zero eigenvalue with negative power: # %d ev = %f , pow = %f\n", i, w[i], power);
964 if (w[i] < threshold)
972 wpow[i] = pow(wpow[i], power);
974 auto evconj = transpose(mat,
true);
975 auto temp = evconj.copy();
976 for (
int i = 0; i != n; i++)
977 temp.scale_row(i, wpow[i]);
978 auto pmat = mat * temp;
981 for (
int i = 0; i != n; i++)
982 evconj.scale_row(i, w[i]);
983 matmul(temp, evconj, mat);
987 template <
typename T>
990 return m1.dataobj == m2.dataobj;
994 template <
typename T>
998 for (
int i = 0; i < m.nr(); i++)
1000 if (m.nc() > 0) s = s + std::to_string(m(i, 0));
1001 for (
int j = 1; j < m.nc(); j++)
1002 s = s +
" " + std::to_string(m(i, j));
1009 template <
typename T>
1010 std::string str(
const matrix_m<std::complex<T>> &m)
1013 for (
int i = 0; i != m.nr(); i++)
1016 s = s +
"(" + std::to_string(m(i, 0).real()) +
"," + std::to_string(m(i, 0).imag()) +
")";
1017 for (
int j = 1; j != m.nc(); j++)
1018 s = s +
" (" + std::to_string(m(i, j).real()) +
"," + std::to_string(m(i, j).imag()) +
")";
1025 template <
typename T>
1026 inline matrix_m<T> random(
int nr,
int nc,
const T &lb,
const T &ub, MAJOR major = MAJOR::ROW)
1034 template <
typename T>
1035 inline matrix_m<T> random_sy(
int n,
const T &lb,
const T &ub, MAJOR major = MAJOR::ROW)
1043 template <
typename T>
1044 inline matrix_m<std::complex<T>> random_he(
int n,
const std::complex<T> &lb,
const std::complex<T> &ub, MAJOR major = MAJOR::ROW)
1052 template <
typename T>
1057 auto mat = random_he<T>(n, {-1.0, -1.0}, {1.0, 1.0}, MAJOR::COL);
1058 const char *name = mat.is_double?
"ZHETRD" :
"CHETRD";
1060 int nb = LapackConnector::ilaenv(1, name,
"VU", n, -1, -1, -1);
1061 if (nb <= 1) nb = std::max(1, n);
1062 const int lwork = n * (nb + 1);
1065 std::complex<T> *work =
new std::complex<T>[lwork];
1066 T *rwork =
new T[std::max(1, 3 * n - 2)];
1068 LapackConnector::heev_f(
'V',
'U', n, mat.ptr(), mat.nr(), w, work, lwork, rwork, info);
1069 delete [] rwork, w, work;
1076 template <
typename T>
1077 inline matrix_m<std::complex<T>> random_he_selected_ev(
int n,
const vector<T> &evs, MAJOR major = MAJOR::ROW,
const T& padding_zero = 1e-14)
1079 const int nvec = evs.size();
1082 auto eigvec = random_unitary<T>(n, major);
1083 auto eigvec_H = eigvec.get_transpose(
true);
1084 for (
int ie = 0; ie != n; ie++)
1085 eigvec_H.scale_row(ie, ie < nvec? evs[ie]: padding_zero);
1086 return eigvec * eigvec_H;
1090 template <typename T, typename Treal = typename to_real<T>::type>
1091 void print_matrix_mm(
const matrix_m<T> &mat, ostream &os, Treal threshold = 1e-15,
bool row_first =
true)
1093 const int nr = mat.nr(), nc = mat.nc();
1095 for (
int i = 0; i != mat.size(); i++)
1097 if (fabs(mat.dataobj[i]) > threshold)
1100 os <<
"%%MatrixMarket matrix coordinate "
1101 << (is_complex<T>()?
"complex" :
"real") <<
" general" << endl
1103 os << nr <<
" " << nc <<
" " << nnz << endl;
1107 for (
int i = 0; i != nr; i++)
1108 for (
int j = 0; j != nc; j++)
1110 auto &v = mat(i, j);
1111 if (fabs(v) > threshold)
1113 os << i + 1 <<
" " << j + 1 <<
" " << showpoint << scientific << setprecision(15) << get_real(v);
1114 if (is_complex<T>())
1115 os <<
" " << showpoint << scientific << setprecision(15) << get_imag(v);
1122 for (
int j = 0; j != nc; j++)
1123 for (
int i = 0; i != nr; i++)
1125 auto &v = mat(i, j);
1126 if (fabs(v) > threshold)
1128 os << i + 1 <<
" " << j + 1 <<
" " << showpoint << scientific << setprecision(15) << get_real(v);
1129 if (is_complex<T>())
1130 os <<
" " << showpoint << scientific << setprecision(15) << get_imag(v);
1137 template <typename T, typename Treal = typename to_real<T>::type>
1138 void print_whole_matrix(
const char *desc,
const matrix_m<T> &mat)
1148 for (
int i = 0; i < nr; i++)
1150 for (
int j = 0; j < nc; j++)
1151 lib_printf(
"%10.6f,%9.6f ", mat.c[i * nc + j].real(), mat.c[i * nc + j].imag());
1157 for (
int i = 0; i < nr; i++)
1159 for (
int j = 0; j < nc; j++)
1160 lib_printf(
"%10.6f", mat.c[i * nc + j].real());
1166 template <typename T, typename Treal = typename to_real<T>::type>
1167 void print_matrix_mm_file(
const matrix_m<T> &mat,
const std::string &fn, Treal threshold = 1e-15,
bool row_first =
true)
1171 print_matrix_mm(mat, fs, threshold, row_first);
Definition: matrix_m.h:213
void randomize(const T &lb=0, const T &ub=1, bool symmetrize=false, bool hermitian=false)
Randomize the matrix elements with lower and upper bound and symmetry constraint.
Definition: matrix_m.h:346
static const bool is_complex
Flag of whether the instantialized matrix class is complex-typed.
Definition: matrix_m.h:216
void lib_printf(const char *format, Args &&... args)
printf that handles the stdout redirect
Definition: utils_io.h:13
Definition: base_utility.h:11
struct to store the shared data and dimension
Definition: matrix_m.h:88