1 #include <../../nrnconf.h> 35 static char rcsid[] =
"spbkp.c,v 1.1 1997/12/04 17:55:50 hines Exp";
46 #define alpha 0.6403882032022076 49 #define btos(x) ((x) ? "TRUE" : "FALSE") 52 #define sqr(x) ((x)*(x)) 64 if ( ! r || ! r->elt )
66 for ( idx = 0, e = r->elt; idx < r->len; idx++, e++ )
86 if ( i < 0 || i >=
A->m || j < 0 || j >=
A->n )
102 int i1, j1, idx1, i2, j2, idx2;
104 int tmp_row, tmp_idx;
112 if ( i1 < 0 || j1 < 0 || i2 < 0 || j2 < 0 ||
113 i1 >=
A->m || j1 >=
A->n || i2 >=
A->m || j2 >=
A->n )
118 if ( i1 == i2 && j1 == j2 )
120 if ( idx1 < 0 && idx2 < 0 )
123 r1 = &(
A->row[i1]); r2 = &(
A->row[i2]);
136 tmp_row = -1; tmp_idx = j1;
143 A->start_row[j1] = i1;
144 A->start_idx[j1] = idx1;
150 tmp_e = &(
A->row[tmp_row].elt[tmp_idx]);
157 else if ( r1->
elt[idx1].
col != j1 )
170 tmp_row = -1; tmp_idx = j2;
176 A->start_row[j2] = i2;
177 A->start_idx[j2] = idx2;
183 tmp_e = &(
A->row[tmp_row].elt[tmp_idx]);
190 else if ( r2->
elt[idx2].
col != j2 )
193 e1 = &(r1->
elt[idx1]); e2 = &(r2->
elt[idx2]);
212 *
row =
A->start_row[
j];
213 *idx =
A->start_idx[
j];
227 return &(
A->row[*
row].elt[*idx]);
236 int tmp_row, tmp_idx;
237 int row1, row2, idx1, idx2, tmp_row1, tmp_idx1, tmp_row2, tmp_idx2;
244 if ( i1 < 0 || i1 >=
A->n || i2 < 0 || i2 >=
A->n )
252 { tmp_idx = i1; i1 = i2; i2 = tmp_idx; }
255 for ( tmp_idx = 0; tmp_idx <
A->n; tmp_idx++ )
257 row1 = -1; idx1 = i1;
258 row2 = -1; idx2 = i2;
262 while ( (row1 >= 0 && row1 < i1) || (row2 >= 0 && row2 < i1) )
266 if ( row1 >= 0 && row1 < i1 && ( row1 < row2 || row2 < 0 ) )
268 tmp_row1 = row1; tmp_idx1 = idx1;
270 if ( ! done_list->
ive[row1] )
278 row1 = tmp_row1; idx1 = tmp_idx1;
280 else if ( row2 >= 0 && row2 < i1 && ( row2 < row1 || row1 < 0 ) )
282 tmp_row2 = row2; tmp_idx2 = idx2;
284 if ( ! done_list->
ive[row2] )
292 row2 = tmp_row2; idx2 = tmp_idx2;
294 else if ( row1 == row2 )
296 tmp_row1 = row1; tmp_idx1 = idx1;
298 tmp_row2 = row2; tmp_idx2 = idx2;
300 if ( ! done_list->
ive[row1] )
305 row1 = tmp_row1; idx1 = tmp_idx1;
306 row2 = tmp_row2; idx2 = tmp_idx2;
311 while ( row2 >= 0 && row2 <= i1 )
317 e1 = &(r1->
elt[idx1]);
318 while ( row2 >= 0 && row2 < i2 )
321 tmp_row = row2; tmp_idx = idx2;
322 if ( ! done_list->
ive[row2] )
324 r2 = &(
A->row[row2]);
333 row2 = tmp_row; idx2 = tmp_idx;
334 e2 = ( row2 >= 0 ) ? &(
A->row[row2].elt[idx2]) : (
row_elt *)
NULL;
339 while ( idx1 < r1->len )
341 if ( e1->
col >= i2 || e1->
col <= i1 )
347 if ( ! done_list->
ive[e1->
col] )
360 e1 = &(r1->
elt[idx1]);
363 e2 = &(r2->
elt[idx2]);
364 while ( idx1 < r1->len )
371 if ( ! done_list->
ive[e1->
col] )
381 idx2 = 0; e2 = r2->
elt;
382 while ( idx2 < r2->len )
389 if ( ! done_list->
ive[e2->
col] )
402 if ( idx1 >= 0 || idx2 >= 0 )
418 int i, i_min, min_val, tmp;
425 min_val = iv->ive[0];
426 for ( i = 1; i < iv->dim; i++ )
455 if ( i < 0 || i >
A->n || j < 0 || j >=
A->n )
463 row_num = -1; idx =
j;
469 e = &(
A->row[
i].elt[idx]);
471 while ( row_num >= 0 && row_num <
j )
482 for ( idx = 0, e = r->
elt; idx < r->len; idx++, e++ )
484 if ( e->
col >
j && e->
col != l )
504 for ( i = 0; i <
A->m; i++ )
505 cnt +=
A->row[i].len;
515 int cnt_nz,
j,
row, idx;
524 for ( j = 0; j <
A->n; j++ )
526 row =
A->start_row[
j];
527 idx =
A->start_idx[
j];
530 if ( row >=
A->m || idx < 0 )
554 return e1->
col - e2->col;
564 PERM *pivot, *blocks;
567 int i,
j,
k, l,
n, onebyone=0, r;
568 int idx, idx1, idx_piv;
570 int best_deg=0, best_j, best_l, best_cost, mark_cost, deg, deg_j,
572 int list_idx, list_idx2, old_list_idx;
575 Real aii, aip1, aip1i;
576 Real det, max_j, max_l,
s,
t;
583 if ( !
A || ! pivot || ! blocks )
589 if ( tol <= 0.0 || tol > 1.0 )
616 for ( i = 0; i < n-1; i = onebyone ? i+1 : i+2 )
625 for ( j = i; j <
n; j++ )
626 deg_list->
ive[j-i] = 0;
629 for ( j = i; j <
n; j++ )
630 deg_list->
ive[j-i] = 1;
632 deg_list->
ive[0] = 0;
639 for ( j = i; j <
n; j++ )
645 e = &(row->
elt[idx]);
647 for ( ; idx < row->
len; idx++, e++ )
661 list_idx = 0; r = -1;
662 best_j = best_l = -1;
663 for ( deg = 0; deg <=
n; deg++ )
667 if ( list_idx >= deg_list->
dim )
669 old_list_idx = list_idx;
670 while ( list_idx < deg_list->dim &&
671 deg_list->
ive[list_idx] <= deg )
673 j = i+order->
pe[list_idx];
686 if ( ajj >= tol *max_j )
690 best_deg = deg_list->
ive[list_idx];
698 best_j = best_l = -1;
699 list_idx = old_list_idx;
700 while ( list_idx < deg_list->dim &&
701 deg_list->
ive[list_idx] <= deg )
703 j = i+order->
pe[list_idx];
705 for ( list_idx2 = 0; list_idx2 < list_idx; list_idx2++ )
708 deg_l = deg_list->
ive[list_idx2];
709 l = i+order->
pe[list_idx2];
716 det =
fabs(ajj*all - ajl*ajl);
721 if ( tol*(all*max_j+ajl*max_l) < det &&
722 tol*(ajl*max_j+ajj*max_l) < det )
727 mark_cost = (ajj == 0.0) ?
728 ((all == 0.0) ? deg_j+deg_l : deg_j+2*deg_l) :
729 ((all == 0.0) ? 2*deg_j+deg_l :
731 if ( mark_cost < best_cost )
734 best_cost = mark_cost;
747 if ( best_deg > (
int)
floor(0.8*(n-i)) )
751 if ( best_j >= 0 && onebyone )
756 else if ( best_j >= 0 && best_l >= 0 && ! onebyone )
758 if ( best_j == i || best_j == i+1 )
760 if ( best_l == i || best_l == i+1 )
767 px_transp(pivot,(best_j == i) ? i+1 : i,best_l);
769 else if ( best_l == i || best_l == i+1 )
772 px_transp(pivot,(best_l == i) ? i+1 : i,best_j);
798 int idx_j, idx_k, s_idx, s_idx2;
801 r_piv = &(
A->row[
i]);
807 aii = r_piv->
elt[idx_piv].
val;
817 row_num =
i; s_idx = idx = 0;
818 e = &(r_piv->
elt[idx]);
819 for ( idx = 0; idx < r_piv->
len; idx++, e++ )
823 scan_row->
ive[s_idx] =
i;
824 scan_idx->ive[s_idx] = idx;
825 orig_idx->
ive[s_idx] = idx;
826 col_list->ive[s_idx] = e->
col;
839 for ( idx = 0; idx < order->
size; idx++ )
840 tmp_iv->ive[idx] = scan_idx->ive[order->
pe[idx]];
842 for ( idx = 0; idx < order->
size; idx++ )
843 tmp_iv->
ive[idx] = scan_row->
ive[order->
pe[idx]];
845 for ( idx = 0; idx < scan_row->
dim; idx++ )
846 tmp_iv->
ive[idx] = orig_idx->
ive[order->
pe[idx]];
852 for ( s_idx = 0; s_idx < scan_row->
dim; s_idx++ )
854 idx_j = orig_idx->
ive[s_idx];
857 e_ij = &(r_piv->
elt[idx_j]);
861 scan_to(
A,scan_row,scan_idx,col_list,j);
869 for ( s_idx2 = s_idx; s_idx2 < scan_row->
dim; s_idx2++ )
871 idx_k = orig_idx->
ive[s_idx2];
872 e_ik = &(r_piv->
elt[idx_k]);
876 if ( scan_row->
ive[s_idx2] == j )
878 idx = scan_idx->ive[s_idx2];
884 int old_row, old_idx;
887 old_row = scan_row->
ive[s_idx2];
888 old_idx = scan_idx->ive[s_idx2];
904 new_e = &(row->
elt[idx]);
905 new_e->
val = -t*e_ik->
val;
908 old_e = &(
A->row[old_row].elt[old_idx]);
920 int idx_k, idx1_k, s_idx, s_idx2;
924 r_piv = &(
A->row[
i]);
928 for ( idx_piv = 0; idx_piv < r_piv->
len; idx_piv++, e_tmp++ )
929 if ( e_tmp->
col == i )
931 else if ( e_tmp->
col == i+1 )
934 r1_piv = &(
A->row[i+1]);
937 det = aii*aip1 - aip1i*aip1i;
938 if ( aii == 0.0 && aip1i == 0.0 )
957 s_idx = r_piv->
len + r1_piv->
len;
965 for ( idx = 0; idx < r_piv->
len; idx++, e++ )
967 scan_row->
ive[idx] =
i;
968 scan_idx->ive[idx] = idx;
969 col_list->ive[idx] = e->
col;
970 orig_idx->
ive[idx] = idx;
971 orig1_idx->ive[idx] = -1;
975 for ( idx = 0; idx < r1_piv->
len; idx++, e1++ )
977 scan_row->
ive[idx+r_piv->
len] = i+1;
978 scan_idx->ive[idx+r_piv->
len] = idx;
979 col_list->ive[idx+r_piv->
len] = e1->
col;
980 orig_idx->
ive[idx+r_piv->
len] = -1;
981 orig1_idx->ive[idx+r_piv->
len] = idx;
989 for ( idx = 0; idx < order->
size; idx++ )
990 tmp_iv->ive[idx] = scan_idx->ive[order->
pe[idx]];
992 for ( idx = 0; idx < order->
size; idx++ )
993 tmp_iv->
ive[idx] = scan_row->
ive[order->
pe[idx]];
995 for ( idx = 0; idx < scan_row->
dim; idx++ )
996 tmp_iv->
ive[idx] = orig_idx->
ive[order->
pe[idx]];
998 for ( idx = 0; idx < scan_row->
dim; idx++ )
999 tmp_iv->
ive[idx] = orig1_idx->ive[order->
pe[idx]];
1004 for ( idx = 0; idx < scan_row->
dim; idx++ )
1006 if ( col_list->ive[idx] == old_col )
1008 if ( scan_row->
ive[idx] == i )
1010 scan_row->
ive[s_idx-1] = scan_row->
ive[idx];
1011 scan_idx->ive[s_idx-1] = scan_idx->ive[idx];
1012 col_list->ive[s_idx-1] = col_list->ive[idx];
1013 orig_idx->
ive[s_idx-1] = orig_idx->
ive[idx];
1014 orig1_idx->ive[s_idx-1] = orig1_idx->ive[idx-1];
1018 scan_row->
ive[s_idx-1] = scan_row->
ive[idx-1];
1019 scan_idx->ive[s_idx-1] = scan_idx->ive[idx-1];
1020 col_list->ive[s_idx-1] = col_list->ive[idx-1];
1021 orig_idx->
ive[s_idx-1] = orig_idx->
ive[idx-1];
1022 orig1_idx->ive[s_idx-1] = orig1_idx->ive[idx];
1027 scan_row->
ive[s_idx] = scan_row->
ive[idx];
1028 scan_idx->ive[s_idx] = scan_idx->ive[idx];
1029 col_list->ive[s_idx] = col_list->ive[idx];
1030 orig_idx->
ive[s_idx] = orig_idx->
ive[idx];
1031 orig1_idx->ive[s_idx] = orig1_idx->ive[idx];
1034 old_col = col_list->ive[idx];
1043 for ( s_idx = 0; s_idx < scan_row->
dim; s_idx++ )
1045 int idx_piv, idx1_piv;
1046 Real aip1j, aij, aik, aip1k;
1049 j = col_list->ive[s_idx];
1055 idx_piv = orig_idx->
ive[s_idx];
1056 aij = ( idx_piv < 0 ) ? 0.0 : r_piv->
elt[idx_piv].
val;
1060 idx1_piv = orig1_idx->ive[s_idx];
1061 aip1j = ( idx1_piv < 0 ) ? 0.0 : r1_piv->
elt[idx1_piv].
val;
1065 s = - aip1i*aip1j + aip1*aij;
1066 t = - aip1i*aij + aii*aip1j;
1072 k = col_list->ive[s_idx2];
1073 idx_k = orig_idx->
ive[s_idx2];
1074 idx1_k = orig1_idx->ive[s_idx2];
1076 while ( s_idx2 < scan_row->dim )
1078 k = col_list->ive[s_idx2];
1079 idx_k = orig_idx->
ive[s_idx2];
1080 idx1_k = orig1_idx->ive[s_idx2];
1082 &(r_piv->
elt[idx_k]);
1084 &(r1_piv->
elt[idx1_k]);
1085 aik = ( idx_k >= 0 ) ? e_ik->
val : 0.0;
1086 aip1k = ( idx1_k >= 0 ) ? e_ip1k->
val : 0.0;
1087 if ( scan_row->
ive[s_idx2] == j )
1091 idx = scan_idx->ive[s_idx2];
1094 row->
elt[idx].
val -= s*aik + t*aip1k;
1099 int old_row, old_idx;
1102 tmp = - s*aik - t*aip1k;
1106 old_row = scan_row->
ive[s_idx2];
1107 old_idx = scan_idx->ive[s_idx2];
1117 new_e = &(row->
elt[idx]);
1125 old_e = &(
A->row[old_row].elt[old_idx]);
1139 idx = orig_idx->
ive[s_idx];
1144 else if ( s != 0.0 )
1146 int old_row, old_idx;
1149 old_row = -1; old_idx =
j;
1163 r_piv->
len = idx + 1;
1167 new_e = &(r_piv->
elt[idx]);
1174 A->start_row[
j] =
i;
1175 A->start_idx[
j] = idx;
1182 old_e = &(
A->row[old_row].elt[old_idx]);
1190 idx1 = orig1_idx->ive[s_idx];
1195 else if ( t != 0.0 )
1197 int old_row, old_idx;
1200 old_row = -1; old_idx =
j;
1210 r1_piv->
len = idx1 + 1;
1214 new_e = &(r1_piv->
elt[idx1]);
1219 new_e = &(r1_piv->
elt[idx1]);
1224 A->start_row[
j] = i+1;
1225 A->start_idx[
j] = idx1;
1229 old_idx =
sprow_idx2(&(
A->row[old_row]),j,old_idx);
1232 old_e = &(
A->row[old_row].elt[old_idx]);
1244 for (
i = 0;
i <
A->m;
i++ )
1246 A->flag_col =
A->flag_diag =
FALSE;
1255 PERM *pivot, *block;
1259 int i ,
n, onebyone;
1261 Real a11, a12, a22, b1, b2, det, sum, *tmp_ve, tmp_diag;
1265 if ( !
A || ! pivot || ! block || ! b )
1270 if ( b->
dim != n || pivot->
size != n || block->
size != n )
1278 if ( !
A->flag_col )
1285 for ( i = 0; i <
n; i++ )
1288 if ( block->
pe[i] < i )
1292 row_num = -1; idx =
i;
1294 while ( row_num >= 0 && row_num < i-1 )
1296 sum -= e->
val*tmp_ve[row_num];
1304 row_num = -1; idx =
i;
1306 while ( row_num >= 0 && row_num < i )
1308 sum -= e->
val*tmp_ve[row_num];
1317 for ( i = 0; i <
n; i = onebyone ? i+1 : i+2 )
1319 onebyone = ( block->
pe[
i] ==
i );
1324 if ( tmp_diag == 0.0 )
1326 tmp_ve[
i] /= tmp_diag;
1335 det = a11*a22-a12*a12;
1339 tmp_ve[
i] = det*(a22*b1-a12*b2);
1340 tmp_ve[i+1] = det*(a11*b2-a12*b1);
1346 for ( i = n-2; i >= 0; i-- )
1349 if ( block->
pe[i] > i )
1360 for ( ; idx < r->
len; idx++, e++ )
1361 sum -= e->
val*tmp_ve[e->
col];
1371 for ( ; idx < r->
len; idx++, e++ )
1372 sum -= e->
val*tmp_ve[e->
col];
SPMAT * sp_diag_access(SPMAT *A)
static Object ** v_resize(void *v)
IVEC * iv_resize(IVEC *iv, int new_dim)
SPMAT * bkp_interchange(SPMAT *A, int i1, int i2)
row_elt * chase_col(SPMAT *, int, int *, int *, int)
static philox4x32_key_t k
#define sprow_idx2(r, c, hint)
IVEC * iv_copy(IVEC *in, IVEC *out)
VEC * spBKPsolve(SPMAT *A, PERM *pivot, PERM *block, VEC *b, VEC *x)
VEC * px_vec(PERM *, VEC *, VEC *)
PERM * px_transp(PERM *px, u_int i, u_int j)
IVEC * iv_sort(IVEC *x, PERM *order)
int chk_col_access(SPMAT *A)
int const size_t const size_t n
SPMAT * spBKPfactor(SPMAT *A, PERM *pivot, PERM *blocks, double tol)
static SPMAT * bkp_swap_elt(SPMAT *A, int i1, int j1, int idx1, int i2, int j2, int idx2)
row_elt * chase_past(SPMAT *, int, int *, int *, int)
PERM * px_resize(PERM *, int)
double unord_get_val(SPMAT *A, int i, int j)
int sprow_idx(SPROW *, int)
#define tracecatch(ok_part, function)
int iv_min(IVEC *iv, int *index)
static double max_row_col(SPMAT *A, int i, int j, int l)
row_elt * bkp_bump_col(SPMAT *A, int j, int *row, int *idx)
int unord_get_idx(SPROW *r, int j)
VEC * pxinv_vec(PERM *, VEC *, VEC *)
#define MEM_STAT_REG(var, type)
#define error(err_num, fn_name)
void scan_to(SPMAT *, IVEC *, IVEC *, IVEC *, int)
SPMAT * sp_col_access(SPMAT *A)
SPROW * sprow_xpd(SPROW *r, int n, int type)
PERM * px_ident(PERM *px)
double sp_get_val(SPMAT *A, int i, int j)
static int nonzeros(SPMAT *A)
static int col_cmp(row_elt *e1, row_elt *e2)
row_elt * bump_col(SPMAT *, int, int *, int *)