169 static_assert(f_tr::arity == 2,
"det_manip : the function must take two arguments !");
172 using x_type =
typename f_tr::template decay_arg_t<0>;
173 using y_type =
typename f_tr::template decay_arg_t<1>;
174 using value_type =
typename f_tr::result_type;
175 using det_type = value_type;
176 static_assert(std::is_floating_point_v<value_type> || nda::is_complex_v<value_type>,
177 "det_manip : the function must return a floating number or a complex number");
179 using matrix_type = nda::matrix<value_type>;
186 long kmax_tried{1}, k_tried{0};
198 std::vector<long> row_num, col_num;
199 std::vector<x_type> x_values;
200 std::vector<y_type> y_values;
204 uint64_t n_opts_max_before_check = 100;
205 double singular_threshold = -1;
206 double precision_warning = 1.e-8;
207 double precision_error = 1.e-5;
217 auto gr = fg.create_group(subgroup_name);
224 h5_write(gr,
"x_values", g.x_values);
225 h5_write(gr,
"y_values", g.y_values);
227 h5_write(gr,
"n_opts_max_before_check", g.n_opts_max_before_check);
228 h5_write(gr,
"singular_threshold", g.singular_threshold);
239 auto gr = fg.open_group(subgroup_name);
241 h5_read(gr,
"mat_inv", g.mat_inv);
242 g.Nmax = first_dim(g.mat_inv);
246 h5_read(gr,
"row_num", g.row_num);
247 h5_read(gr,
"col_num", g.col_num);
248 h5_read(gr,
"x_values", g.x_values);
249 h5_read(gr,
"y_values", g.y_values);
250 h5_read(gr,
"n_opts", g.n_opts);
251 h5_read(gr,
"n_opts_max_before_check", g.n_opts_max_before_check);
252 h5_read(gr,
"singular_threshold", g.singular_threshold);
256 work_data_type1<x_type, y_type, value_type> w1;
257 work_data_typek<x_type, y_type, value_type> wk;
258 work_data_type_refill<x_type, y_type, value_type> w_refill;
263 void swap_but_f(
det_manip &rhs)
noexcept {
265#define SW(a) swap(this->a, rhs.a)
277 SW(n_opts_max_before_check);
304 if (new_k > kmax_tried) {
306 if (new_N <= Nmax) wk.resize(Nmax, kmax_tried);
311 matrix_type mcpy(mat_inv);
312 mat_inv.resize(Nmax, Nmax);
313 auto Rcpy = range(mcpy.extent(0));
314 mat_inv(Rcpy, Rcpy) = mcpy;
316 row_num.reserve(Nmax);
317 col_num.reserve(Nmax);
318 x_values.reserve(Nmax);
319 y_values.reserve(Nmax);
322 wk.resize(Nmax, kmax_tried);
403 det_manip(FunctionType F,
long init_size) : f(std::move(F)) {
418 template <
typename ArgumentContainer1,
typename ArgumentContainer2>
419 det_manip(FunctionType F, ArgumentContainer1
const &X, ArgumentContainer2
const &Y) : f(std::move(F)) {
428 std::copy(X.begin(), X.end(), std::back_inserter(x_values));
429 std::copy(Y.begin(), Y.end(), std::back_inserter(y_values));
431 for (
long i = 0; i < N; ++i) {
432 row_num.push_back(i);
433 col_num.push_back(i);
434 for (
long j = 0; j < N; ++j) mat_inv(i, j) = f(x_values[i], y_values[j]);
437 det = nda::linalg::det(mat_inv(RN, RN));
438 mat_inv(RN, RN) = nda::linalg::inv(mat_inv(RN, RN));
444 this->swap_but_f(rhs);
447 det_manip &operator=(
const det_manip &) =
delete;
448 det_manip &operator=(det_manip &&rhs)
noexcept {
449 assert((last_try == NoTry) && (rhs.last_try == NoTry));
474 [[nodiscard]]
long size()
const {
return N; }
482 x_type
const &
get_x(
long i)
const {
return x_values[row_num[i]]; }
490 y_type
const &
get_y(
long j)
const {
return y_values[col_num[j]]; }
498 std::vector<x_type> res;
500 for (
long i : range(N)) res.emplace_back(x_values[row_num[i]]);
510 std::vector<y_type> res;
512 for (
long i : range(N)) res.emplace_back(y_values[col_num[i]]);
562 value_type
inverse_matrix(
int i,
int j)
const {
return mat_inv(col_num[i], row_num[j]); }
571 matrix_type res(N, N);
572 for (
long i = 0; i < N; i++)
599 matrix_type res(N, N);
600 for (
long i = 0; i < N; i++)
601 for (
long j = 0; j < N; j++) res(i, j) = f(
get_x(i),
get_y(j));
616 template <
typename LambdaType>
friend void foreach (
det_manip const &d, LambdaType
const &fn) {
617 nda::for_each(std::array{d.N, d.N}, [&fn, &d](
int i,
int j) {
return fn(d.x_values[i], d.y_values[j], d.mat_inv(j, i)); });
637 std::swap(row_num[i], row_num[j]);
657 std::swap(col_num[i], col_num[j]);
681 value_type
try_insert(
long i,
long j, x_type
const &x, y_type
const &y) {
698 return value_type(newdet);
703 for (
long l = 0; l < N; l++) {
704 w1.B(l) = f(x_values[l], y);
705 w1.C(l) = f(x, y_values[l]);
709 blas::gemv(1.0, mat_inv(RN, RN), w1.B(RN), 0.0, w1.MB(RN));
710 w1.ksi = f(x, y) - nda::blas::dot(w1.C(RN), w1.MB(RN));
711 newdet = det * w1.ksi;
712 newsign = ((i + j) % 2 == 0 ? sign : -sign);
713 return w1.ksi * (newsign * sign);
755 for (
long l = 0; l < N; l++) {
756 w1.B(l) = fx(x_values[l]);
757 w1.C(l) = fy(y_values[l]);
761 blas::gemv(1.0, mat_inv(RN, RN), w1.B(RN), 0.0, w1.MB(RN));
762 w1.ksi = ksi - nda::blas::dot(w1.C(RN), w1.MB(RN));
763 newdet = det * w1.ksi;
764 newsign = ((i + j) % 2 == 0 ? sign : -sign);
765 return w1.ksi * (newsign * sign);
771 void complete_insert() {
773 x_values.push_back(w1.x);
774 y_values.push_back(w1.y);
775 row_num.push_back(0);
776 col_num.push_back(0);
781 mat_inv(0, 0) = 1 / value_type(newdet);
787 blas::gemv(1.0, transpose(mat_inv(RN, RN)), w1.C(RN), 0.0, w1.MC(RN));
798 for (
long i = N - 2; i >= w1.i; i--) row_num[i + 1] = row_num[i];
799 row_num[w1.i] = N - 1;
800 for (
long i = N - 2; i >= w1.j; i--) col_num[i + 1] = col_num[i];
801 col_num[w1.j] = N - 1;
808 mat_inv(RN, N - 1) = 0;
809 mat_inv(N - 1, RN) = 0;
811 blas::ger(w1.ksi, w1.MB(RN), w1.MC(RN), mat_inv(RN, RN));
857 value_type
try_insert_k(std::vector<long> i, std::vector<long> j, std::vector<x_type> x, std::vector<y_type> y) {
863 k_tried =
static_cast<long>(i.size());
867 auto const argsort = [](
auto const &vec) {
868 std::vector<long> idx(vec.size());
869 std::iota(idx.begin(), idx.end(),
static_cast<long>(0));
870 std::stable_sort(idx.begin(), idx.end(), [&vec](
long const lhs,
long const rhs) { return vec[lhs] < vec[rhs]; });
873 std::vector<long> idx = argsort(i);
874 std::vector<long> idy = argsort(j);
877 for (
long l = 0; l < k_tried; ++l) {
885 for (
int l = 0; l < k_tried - 1; ++l) {
886 TRIQS_ASSERT(wk.i[l] != wk.i[l + 1] and 0 <= wk.i[l] and wk.i[l] < N + k_tried);
887 TRIQS_ASSERT(wk.j[l] != wk.j[l + 1] and 0 <= wk.j[l] and wk.j[l] < N + k_tried);
891 for (
long m = 0; m < k_tried; ++m) {
892 for (
long n = 0; n < k_tried; ++n) { wk.ksi(m, n) = f(wk.x[m], wk.y[n]); }
897 newdet = wk.det_ksi(k_tried);
899 return value_type(newdet);
904 for (
long n = 0; n < N; n++) {
905 for (
long l = 0; l < k_tried; ++l) {
906 wk.B(n, l) = f(x_values[n], wk.y[l]);
907 wk.C(l, n) = f(wk.x[l], y_values[n]);
910 range RN(N), Rk(k_tried);
912 blas::gemm(1.0, mat_inv(RN, RN), wk.B(RN, Rk), 0.0, wk.MB(RN, Rk));
914 blas::gemm(-1.0, wk.C(Rk, RN), wk.MB(RN, Rk), 1.0, wk.ksi(Rk, Rk));
915 auto ksi = wk.det_ksi(k_tried);
918 for (
long l = 0; l < k_tried; ++l) { idx_sum += wk.i[l] + wk.j[l]; }
919 newsign = (idx_sum % 2 == 0 ? sign : -sign);
920 return ksi * (newsign * sign);
943 value_type
try_insert2(
long i0,
long i1,
long j0,
long j1, x_type
const &x0, x_type
const &x1, y_type
const &y0, y_type
const &y1) {
944 return try_insert_k({i0, i1}, {j0, j1}, {x0, x1}, {y0, y1});
949 template <nda::Array A>
static auto flatten_array(A
const &a) {
950 auto v = std::vector<typename A::value_type>(a.size());
952 nda::for_each(a.shape(), [&](
auto... idx) { v[flat++] = a(idx...); });
973 template <nda::Array X, nda::Array Y>
974 requires(nda::get_rank<X> == nda::get_rank<Y>)
975 auto insert_ratios(
long i,
long j, X
const &xs, Y
const &ys)
const -> nda::array<value_type, nda::get_rank<X>> {
976 constexpr int R = nda::get_rank<X>;
981 long nbatch = xs.size();
982 value_type sign_fac = ((i + j) % 2 == 0 ? 1 : -1);
983 nda::array<value_type, R> result(xs.shape());
985 if (nbatch == 0)
return result;
988 auto xs_flat = flatten_array(xs);
989 auto ys_flat = flatten_array(ys);
992 for (
long m = 0; m < nbatch; ++m) result.data()[m] = sign_fac * f(xs_flat[m], ys_flat[m]);
999 nda::matrix<value_type> B(N, nbatch), C(nbatch, N), MB(N, nbatch);
1000 for (
long l = 0; l < N; ++l)
1001 for (
long m = 0; m < nbatch; ++m) B(l, m) = f(x_values[l], ys_flat[m]);
1002 for (
long m = 0; m < nbatch; ++m)
1003 for (
long l = 0; l < N; ++l) C(m, l) = f(xs_flat[m], y_values[l]);
1006 blas::gemm(1.0, mat_inv(RN, RN), B, 0.0, MB);
1009 for (
long m = 0; m < nbatch; ++m) {
1011 for (
long l = 0; l < N; ++l) dot += C(m, l) * MB(l, m);
1012 result.data()[m] = sign_fac * (f(xs_flat[m], ys_flat[m]) - dot);
1021 void complete_insert_k() {
1024 for (
int l = 0; l < k_tried; ++l) {
1025 x_values.push_back(wk.x[l]);
1026 y_values.push_back(wk.y[l]);
1027 row_num.push_back(0);
1028 col_num.push_back(0);
1031 range Rk(0, k_tried);
1035 mat_inv(Rk, Rk) = nda::linalg::inv(wk.ksi(Rk, Rk));
1036 for (
long l = 0; l < k_tried; ++l) {
1037 row_num[wk.i[l]] = l;
1038 col_num[wk.j[l]] = l;
1045 blas::gemm(1.0, wk.C(Rk, RN), mat_inv(RN, RN), 0.0, wk.MC(Rk, RN));
1046 wk.MC(Rk, range(N, N + k_tried)) = -1;
1047 wk.MB(range(N, N + k_tried), Rk) = -1;
1053 for (
int l = 0; l < k_tried; ++l) {
1055 for (
long i = N - 2; i >= wk.i[l]; i--) row_num[i + 1] = row_num[i];
1056 row_num[wk.i[l]] = N - 1;
1057 for (
long i = N - 2; i >= wk.j[l]; i--) col_num[i + 1] = col_num[i];
1058 col_num[wk.j[l]] = N - 1;
1062 wk.ksi(Rk, Rk) = nda::linalg::inv(wk.ksi(Rk, Rk));
1063 mat_inv(RN, range(N - k_tried, N)) = 0;
1064 mat_inv(range(N - k_tried, N), RN) = 0;
1066 blas::gemm(1.0, wk.MB(RN, Rk), (wk.ksi(Rk, Rk) * wk.MC(Rk, RN)), 1.0, mat_inv(RN, RN));
1069 void complete_insert2() { complete_insert_k(); }
1095 w1.jreal = col_num[w1.j];
1096 w1.ireal = row_num[w1.i];
1100 w1.ksi = mat_inv(w1.jreal, w1.ireal);
1103 newsign = ((i + j) % 2 == 0 ? sign : -sign);
1104 return ksi * (newsign * sign);
1109 void complete_remove() {
1120 if (w1.ireal != N - 1) {
1121 deep_swap(mat_inv(RN, w1.ireal), mat_inv(RN, N - 1));
1122 x_values[w1.ireal] = x_values[N - 1];
1123 auto iitr = std::ranges::find(row_num, w1.ireal);
1124 auto titr = std::ranges::find(row_num, N - 1);
1125 std::swap(*iitr, *titr);
1127 if (w1.jreal != N - 1) {
1128 deep_swap(mat_inv(w1.jreal, RN), mat_inv(N - 1, RN));
1129 y_values[w1.jreal] = y_values[N - 1];
1130 auto jitr = std::ranges::find(col_num, w1.jreal);
1131 auto titr = std::ranges::find(col_num, N - 1);
1132 std::swap(*jitr, *titr);
1137 auto it1 [[maybe_unused]] = std::ranges::remove(row_num, N);
1138 auto it2 [[maybe_unused]] = std::ranges::remove(col_num, N);
1142 x_values.pop_back();
1143 y_values.pop_back();
1146 w1.ksi = -1 / mat_inv(N, N);
1147 ASSERT(std::isfinite(std::abs(w1.ksi)));
1150 blas::ger(w1.ksi, mat_inv(RN, N), mat_inv(N, RN), mat_inv(RN, RN));
1225 std::ranges::sort(i);
1226 std::ranges::sort(j);
1232 k_tried =
static_cast<long>(i.size());
1233 reserve(N - k_tried, k_tried);
1237 for (
int l = 0; l < k_tried - 1; ++l) {
1238 TRIQS_ASSERT(i[l] != i[l + 1] and 0 <= i[l] and i[l] < N);
1239 TRIQS_ASSERT(j[l] != j[l + 1] and 0 <= j[l] and j[l] < N);
1242 for (
long l = 0; l < k_tried; ++l) {
1245 wk.ireal[l] = row_num[wk.i[l]];
1246 wk.jreal[l] = col_num[wk.j[l]];
1250 for (
long l1 = 0; l1 < k_tried; ++l1) {
1251 for (
long l2 = 0; l2 < k_tried; ++l2) { wk.ksi(l1, l2) = mat_inv(wk.jreal[l1], wk.ireal[l2]); }
1253 auto det_ksi = wk.det_ksi(k_tried);
1254 newdet = det * det_ksi;
1256 for (
long l = 0; l < k_tried; ++l) { idx_sum += wk.i[l] + wk.j[l]; }
1257 newsign = (idx_sum % 2 == 0 ? sign : -sign);
1259 return det_ksi * (newsign * sign);
1281 void complete_remove_k() {
1287 std::vector<long> ireal = wk.ireal;
1288 std::vector<long> jreal = wk.jreal;
1289 std::sort(ireal.begin(), ireal.begin() + k_tried);
1290 std::sort(jreal.begin(), jreal.begin() + k_tried);
1297 for (
long m = k_tried - 1, target = N - 1; m >= 0; --m, --target) {
1298 if (ireal[m] != target) {
1299 deep_swap(mat_inv(RN, ireal[m]), mat_inv(RN, target));
1300 x_values[ireal[m]] = x_values[target];
1301 auto iitr = std::ranges::find(row_num, ireal[m]);
1302 auto titr = std::ranges::find(row_num, target);
1303 std::swap(*iitr, *titr);
1305 if (jreal[m] != target) {
1306 deep_swap(mat_inv(jreal[m], RN), mat_inv(target, RN));
1307 y_values[jreal[m]] = y_values[target];
1308 auto jitr = std::ranges::find(col_num, jreal[m]);
1309 auto titr = std::ranges::find(col_num, target);
1310 std::swap(*jitr, *titr);
1317 auto gtN = [&](
auto i) {
return i >= N; };
1319 auto it1 [[maybe_unused]] = std::remove_if(row_num.begin(), row_num.end(), gtN);
1320 auto it2 [[maybe_unused]] = std::remove_if(col_num.begin(), col_num.end(), gtN);
1328 range Rl(N, N + k_tried), Rk(k_tried);
1329 wk.ksi(Rk, Rk) = nda::linalg::inv(mat_inv(Rl, Rl));
1333 blas::gemm(-1.0, mat_inv(RN, Rl), wk.ksi(Rk, Rk) * mat_inv(Rl, RN), 1.0, mat_inv(RN, RN));
1336 void complete_remove2() { complete_remove_k(); }
1379 last_try = ChangeCol;
1380 w1.jreal = col_num[j];
1384 for (
long i = 0; i < N; i++) w1.MC(i) = f(x_values[i], w1.y) - f(x_values[i], y_values[w1.jreal]);
1387 blas::gemv(1.0, mat_inv(RN, RN), w1.MC(RN), 0.0, w1.MB(RN));
1390 w1.ksi = (1 + w1.MB(w1.jreal));
1400 void complete_change_col() {
1402 y_values[w1.jreal] = w1.y;
1408 w1.ksi = -1 / w1.ksi;
1409 w1.MB(w1.jreal) = 0;
1411 blas::ger(w1.ksi, w1.MB(RN), mat_inv(w1.jreal, RN), mat_inv(RN, RN));
1412 mat_inv(w1.jreal, RN) *= -w1.ksi;
1436 last_try = ChangeRow;
1437 w1.ireal = row_num[i];
1441 for (
long idx = 0; idx < N; idx++) w1.MB(idx) = f(w1.x, y_values[idx]) - f(x_values[w1.ireal], y_values[idx]);
1444 blas::gemv(1.0, transpose(mat_inv(RN, RN)), w1.MB(RN), 0.0, w1.MC(RN));
1447 w1.ksi = (1 + w1.MC(w1.ireal));
1456 void complete_change_row() {
1458 x_values[w1.ireal] = w1.x;
1463 w1.ksi = -1 / w1.ksi;
1464 w1.MC(w1.ireal) = 0;
1466 blas::ger(w1.ksi, mat_inv(RN, w1.ireal), w1.MC(RN), mat_inv(RN, RN));
1467 mat_inv(RN, w1.ireal) *= -w1.ksi;
1536 last_try = ChangeRowCol;
1539 w1.ireal = row_num[i];
1540 w1.jreal = col_num[j];
1545 for (
long idx = 0; idx < N; idx++) {
1546 w1.MC(idx) = f(x_values[idx], y) - f(x_values[idx], y_values[w1.jreal]);
1547 w1.MB(idx) = f(x, y_values[idx]) - f(x_values[w1.ireal], y_values[idx]);
1549 w1.MC(w1.ireal) = f(x, y) - f(x_values[w1.ireal], y_values[w1.jreal]);
1550 w1.MB(w1.jreal) = 0;
1555 blas::gemv(1.0, mat_inv(RN, RN), w1.MC(RN), 0.0, w1.C(RN));
1557 blas::gemv(1.0, transpose(mat_inv(RN, RN)), w1.MB(RN), 0.0, w1.B(RN));
1560 auto Xn = w1.C(w1.jreal);
1561 auto Yn = w1.B(w1.ireal);
1562 auto Z = nda::blas::dot(w1.MB(RN), w1.C(RN));
1563 auto Mnn = mat_inv(w1.jreal, w1.ireal);
1564 auto det_ratio = (1 + Xn) * (1 + Yn) - Mnn * Z;
1566 newdet = det * det_ratio;
1573 void complete_change_col_row() {
1575 x_values[w1.ireal] = w1.x;
1576 y_values[w1.jreal] = w1.y;
1579 auto Xn = w1.C(w1.jreal);
1580 auto Yn = w1.B(w1.ireal);
1581 auto Mnn = mat_inv(w1.jreal, w1.ireal);
1584 auto a = -(1 + Yn) / D;
1585 auto b = -(1 + Xn) / D;
1586 auto Z = nda::blas::dot(w1.MB(RN), w1.C(RN));
1589 w1.MB(RN) = mat_inv(w1.jreal, RN);
1590 w1.MC(RN) = mat_inv(RN, w1.ireal);
1592 for (
long i = 0; i < N; ++i)
1593 for (
long j = 0; j < N; ++j) {
1596 auto Mnj = w1.MB(j);
1597 auto Min = w1.MC(i);
1598 mat_inv(i, j) += a * Xi * Mnj + b * Min * Yj + Mnn * Xi * Yj + Z * Min * Mnj;
1624 template <
typename ArgumentContainer1,
typename ArgumentContainer2>
1625 value_type
try_refill(ArgumentContainer1
const &X, ArgumentContainer2
const &Y) {
1634 w_refill.x_values.clear();
1635 w_refill.y_values.clear();
1636 return 1 / (sign * det);
1639 w_refill.reserve(s);
1640 w_refill.x_values.clear();
1641 w_refill.y_values.clear();
1642 std::copy(X.begin(), X.end(), std::back_inserter(w_refill.x_values));
1643 std::copy(Y.begin(), Y.end(), std::back_inserter(w_refill.y_values));
1645 for (
long i = 0; i < s; ++i)
1646 for (
long j = 0; j < s; ++j) w_refill.M(i, j) = f(w_refill.x_values[i], w_refill.y_values[j]);
1648 newdet = nda::linalg::det(w_refill.M(R, R));
1651 return newdet / (sign * det);
1657 void complete_refill() {
1658 N = w_refill.x_values.size();
1669 std::swap(x_values, w_refill.x_values);
1670 std::swap(y_values, w_refill.y_values);
1672 row_num.resize(N, 0);
1673 col_num.resize(N, 0);
1674 std::iota(row_num.begin(), row_num.end(), 0);
1675 std::iota(col_num.begin(), col_num.end(), 0);
1678 mat_inv(RN, RN) = nda::linalg::inv(w_refill.M(RN, RN));
1685 void _regenerate_with_check(
bool do_check,
double prec_warning,
double prec_error) {
1693 matrix_type res(N, N);
1694 for (
int i = 0; i < N; i++)
1695 for (
int j = 0; j < N; j++) res(i, j) = f(x_values[i], y_values[j]);
1696 det = nda::linalg::det(res);
1698 if (is_singular())
TRIQS_RUNTIME_ERROR <<
"ERROR in det_manip regenerate: Determinant is singular";
1699 res = nda::linalg::inv(res);
1702 const bool relative =
true;
1703 double r = max_element(abs(res - mat_inv(RN, RN)));
1704 double r2 = max_element(abs(res + mat_inv(RN, RN)));
1705 bool err = !(r < (relative ? prec_error * r2 : prec_error));
1706 bool war = !(r < (relative ? prec_warning * r2 : prec_warning));
1708 std::cerr <<
"matrix = " <<
matrix() << std::endl;
1709 std::cerr <<
"inverse_matrix = " <<
inverse_matrix() << std::endl;
1712 std::cerr <<
"Warning : det_manip deviation above warning threshold "
1714 <<
"N = " << N <<
" "
1715 <<
"\n max(abs(M^-1 - M^-1_true)) = " << r
1716 <<
"\n precision*max(abs(M^-1 + M^-1_true)) = " << (relative ? prec_warning * r2 : prec_warning) <<
" " << std::endl;
1717 if (err)
TRIQS_RUNTIME_ERROR <<
"Error : det_manip deviation above critical threshold !! ";
1721 mat_inv(RN, RN) = res;
1726 nda::matrix<double> m(N, N);
1728 for (
int i = 0; i < N; i++) m(i, row_num[i]) = 1;
1729 s *= nda::linalg::det(m);
1731 for (
int i = 0; i < N; i++) m(i, col_num[i]) = 1;
1732 s *= nda::linalg::det(m);
1733 sign = (s > 0 ? 1 : -1);
1737 void check_mat_inv() { _regenerate_with_check(
true, precision_warning, precision_error); }
1741 [[nodiscard]]
bool is_singular()
const {
1742 return (singular_threshold < 0 ? not std::isnormal(std::abs(det)) : (std::abs(det) < singular_threshold));
1778 case (Insert): complete_insert();
break;
1779 case (Remove): complete_remove();
break;
1780 case (ChangeCol): complete_change_col();
break;
1781 case (ChangeRow): complete_change_row();
break;
1782 case (ChangeRowCol): complete_change_col_row();
break;
1783 case (InsertK): complete_insert_k();
break;
1784 case (RemoveK): complete_remove_k();
break;
1785 case (Refill): complete_refill();
break;
1786 case (NoTry):
return;
break;
1793 if (n_opts > n_opts_max_before_check) check_mat_inv();
1815 value_type
insert(
long i,
long j, x_type
const &x, y_type
const &y) {
1839 value_type
insert2(
long i0,
long i1,
long j0,
long j1, x_type
const &x0, x_type
const &x1, y_type
const &y0, y_type
const &y1) {
1840 auto r =
try_insert2(i0, i1, j0, j1, x0, x1, y0, y1);
1852 value_type
insert2_at_end(x_type
const &x0, x_type
const &x1, y_type
const &y0, y_type
const &y1) {
1853 return insert2(N, N + 1, N, N + 1, x0, x1, y0, y1);
1883 value_type
remove2(
long i0,
long i1,
long j0,
long j1) {
1968 case (None):
return 1;
1970 tmp = row_num[N - 1];
1971 for (
long i = NN - 2; i >= 0; i--) row_num[i + 1] = row_num[i];
1976 for (
long i = 0; i < N - 1; i++) row_num[i] = row_num[i + 1];
1977 row_num[N - 1] = tmp;
1980 tmp = col_num[N - 1];
1981 for (
long i = NN - 2; i >= 0; i--) col_num[i + 1] = col_num[i];
1986 for (
long i = 0; i < N - 1; i++) col_num[i] = col_num[i + 1];
1987 col_num[N - 1] = tmp;
1992 if ((N - 1) % 2 == 1) {