13#include "basker_decl.hpp"
14#include "basker_scalartraits.hpp"
24namespace BaskerClassicNS{
26 template <
class Int,
class Entry>
27 BaskerClassic<Int, Entry>::BaskerClassic()
31 A =
new basker_matrix<Int,Entry>;
34 L =
new basker_matrix<Int, Entry>;
38 U =
new basker_matrix<Int,Entry>;
49 template <
class Int,
class Entry>
50 BaskerClassic<Int, Entry>::BaskerClassic(Int nnzL, Int nnzU)
54 A =
new basker_matrix<Int, Entry>;
56 L =
new basker_matrix<Int, Entry>;
59 U =
new basker_matrix<Int, Entry>;
70 template <
class Int,
class Entry>
71 BaskerClassic<Int, Entry>::~BaskerClassic()
93 template <
class Int,
class Entry>
94 int BaskerClassic<Int,Entry>:: basker_dfs
110 Int start, end, done, *store ;
115 bool has_elements =
true;
132 BASKERASSERT (color[j] == 1) ;
140 for ( i1 = start ; i1 < end ; i1++ )
154 pattern[--*top] = j ;
158 has_elements =
false;
167 std::cout <<
"Out of DFS: " << j << std::endl;
172 template <
class Int,
class Entry>
173 int BaskerClassic<Int,Entry>::factor(Int nrow, Int ncol , Int nnz, Int *col_ptr, Int *row_idx, Entry *val)
179 BASKERASSERT(nrow > 0);
180 BASKERASSERT(ncol > 0);
181 BASKERASSERT(nnz > 0);
188 A->col_ptr = col_ptr;
189 A->row_idx = row_idx;
209 L->col_ptr =
new Int[ncol+1]();
211 L->row_idx =
new Int[L->nnz]();
213 L->val =
new Entry[L->nnz]();
222 U->col_ptr =
new Int[ncol+1]();
224 U->row_idx =
new Int[U->nnz]();
226 U->val =
new Entry[U->nnz]();
228 if((L->col_ptr ==
nullptr) || (L->row_idx ==
nullptr) || (L->val ==
nullptr) ||
229 (U->col_ptr ==
nullptr) || (U->row_idx ==
nullptr) || (U->val ==
nullptr))
237 Int *color, *pattern, *stack;
239 color =
new Int[ncol]();
240 pattern =
new Int[nrow]();
241 stack =
new Int[2*nrow]();
243 X =
new Entry[2*nrow]();
245 pinv =
new Int[ncol+1]();
248 if( (color ==
nullptr) || (pattern ==
nullptr) || (stack ==
nullptr) || (X ==
nullptr) || (pinv ==
nullptr) )
258 Int top, top1, maxindex, t;
259 Int lnnz, unnz, xnnz, lcnt, ucnt;
260 Int cu_ltop, cu_utop;
263 Entry pivot, value, xj;
273 for(k = 0 ; k < ncol; k++)
279 for (k = 0; k < ncol; k++)
283 std::cout <<
"k = " << k << std::endl;
295 BASKERASSERT (top == ncol);
297 for(i = 0; i < nrow; i++)
299 BASKERASSERT(X[i] == (Entry)0);
301 for(i = 0; i < ncol; i++)
303 BASKERASSERT(color[i] == 0);
307 for( i = col_ptr[k]; i < col_ptr[k+1]; i++)
315 basker_dfs(nrow, j, L->row_idx, L->col_ptr, color, pattern, &top, pinv, stack);
323 std::cout << top << std::endl;
324 std::cout << ncol << std::endl;
325 std::cout << xnnz << std::endl;
330 for(pp = 0; pp < xnnz; pp++)
339 p2 = L->col_ptr[t+1];
340 for(p = L->col_ptr[t]+1; p < p2; p++)
342 X[L->row_idx[p]] -= L->val[p] * xj;
350 for(i = top; i < nrow; i++)
357 absv = BASKER_ScalarTraits<Entry>::approxABS(value);
362 if( BASKER_ScalarTraits<Entry>::gt(absv , maxv))
371 ucnt = nrow - top - lcnt + 1;
373 if(maxindex == ncol || pivot == ((Entry)0))
375 std::cout <<
"Matrix is singular at index: " << maxindex <<
" pivot: " << pivot << std::endl;
384 std::cout <<
"Permuting pivot: " << k <<
" for row: " << maxindex << std::endl;
388 if(lnnz + lcnt >= L->nnz)
391 newsize = L->nnz * 1.1 + 2*nrow + 1;
393 std::cout <<
"Out of memory -- Reallocating. Old Size: " << L->nnz <<
" New Size: " << newsize << std::endl;
396 L->row_idx = int_realloc(L->row_idx , L->nnz, newsize);
399 std::cout <<
"WARNING: Cannot Realloc Memory" << std::endl;
404 L->val = entry_realloc(L->val, L->nnz, newsize);
407 std::cout <<
"WARNING: Cannot Realloc Memory" << std::endl;
415 if(unnz + ucnt >= U->nnz)
417 newsize = U->nnz*1.1 + 2*nrow + 1;
419 std::cout <<
"Out of memory -- Reallocating. Old Size: " << U->nnz <<
" New Size: " << newsize << std::endl;
422 U->row_idx = int_realloc(U->row_idx, U->nnz, newsize);
425 std::cout <<
"WARNING: Cannot Realloc Memory" << std::endl;
431 U->val = entry_realloc(U->val, U->nnz, newsize);
434 std::cout <<
"WARNING: Cannot Realloc Memory" << std::endl;
442 L->row_idx[lnnz] = maxindex;
446 Entry last_v_temp = 0;
448 for(i = top; i < nrow; i++)
456 if(X[j] != ((Entry)0))
463 std::cout <<
"BASKER: Insufficent memory for U" << std::endl;
470 U->row_idx[unnz] = pinv[j];
486 std::cout <<
"BASKER: Insufficent memory for L" << std::endl;
491 L->row_idx[lnnz] = j;
493 L->val[lnnz] = BASKER_ScalarTraits<Entry>::divide(X[j],pivot);
505 U->row_idx[unnz] = k;
506 U->val[unnz] = last_v_temp;
512 L->col_ptr[k] = cu_ltop;
513 L->col_ptr[k+1] = lnnz;
516 U->col_ptr[k] = cu_utop;
517 U->col_ptr[k+1] = unnz;
524 for(k = 0; k < lnnz; k++)
526 printf(
"L[%d]=%g" , k , L->val[k]);
528 std::cout << std::endl;
529 for(k = 0; k < lnnz; k++)
531 printf(
"Li[%d]=%d", k, L->row_idx[k]);
533 std::cout << std::endl;
534 for(k = 0; k < nrow; k++)
536 printf(
"p[%d]=%d", k, pinv[k]);
538 std::cout << std::endl;
539 std::cout << std::endl;
541 for(k = 0; k < ncol; k++)
543 printf(
"Up[%d]=%d", k, U->col_ptr[k]);
545 std::cout << std::endl;
547 for(k = 0; k < unnz; k++)
549 printf(
"U[%d]=%g" , k , U->val[k]);
551 std::cout << std::endl;
552 for(k = 0; k < unnz; k++)
554 printf(
"Ui[%d]=%d", k, U->row_idx[k]);
556 std::cout << std::endl;
561 for( i = 0; i < ncol; i++)
563 for(k = L->col_ptr[i]; k < L->col_ptr[i+1]; k++)
573 std::cout <<
"After Permuting" << std::endl;
574 for(k = 0; k < lnnz; k++)
576 printf(
"Li[%d]=%d", k, L->row_idx[k]);
578 std::cout << std::endl;
595 template <
class Int,
class Entry>
596 Int BaskerClassic<Int, Entry>::get_NnzL()
601 template <
class Int,
class Entry>
602 Int BaskerClassic<Int, Entry>::get_NnzU()
607 template <
class Int,
class Entry>
608 Int BaskerClassic<Int, Entry>::get_NnzLU()
610 return (actual_lnnz + actual_unnz);
613 template <
class Int,
class Entry>
614 int BaskerClassic<Int, Entry>::returnL(Int *dim, Int *nnz, Int **col_ptr, Int **row_idx, Entry **val)
623 *col_ptr =
new Int[L->nrow+1];
625 *row_idx =
new Int[L->nnz];
627 *val =
new Entry[L->nnz];
629 if( (*col_ptr ==
nullptr) || (*row_idx ==
nullptr) || (*val ==
nullptr) )
634 for(i = 0; i < L->nrow+1; i++)
636 (*col_ptr)[i] = L->col_ptr[i];
639 for(i = 0; i < actual_lnnz; i++)
641 (*row_idx)[i] = pinv[L->row_idx[i]];
642 (*val)[i] = L->val[i];
648 template <
class Int,
class Entry>
649 int BaskerClassic<Int, Entry>::returnU(Int *dim, Int *nnz, Int **col_ptr, Int **row_idx, Entry **val)
656 *col_ptr =
new Int[U->nrow+1];
658 *row_idx =
new Int[U->nnz];
660 *val =
new Entry[U->nnz];
662 if( (*col_ptr ==
nullptr) || (*row_idx ==
nullptr) || (*val ==
nullptr) )
667 for(i = 0; i < U->nrow+1; i++)
669 (*col_ptr)[i] = U->col_ptr[i];
671 for(i = 0; i < actual_unnz; i++)
673 (*row_idx)[i] = U->row_idx[i];
674 (*val)[i] = U->val[i];
679 template <
class Int,
class Entry>
680 int BaskerClassic<Int, Entry>::returnP(Int** p)
684 *p =
new Int[A->nrow];
686 if( (*p ==
nullptr ) )
691 for(i = 0; i < A->nrow; i++)
698 template <
class Int,
class Entry>
699 void BaskerClassic<Int, Entry>::free_factor()
719 template <
class Int,
class Entry>
720 void BaskerClassic<Int, Entry>::free_perm_matrix()
727 template <
class Int,
class Entry>
728 int BaskerClassic<Int, Entry>::solveMultiple(Int nrhs, Entry *b, Entry *x)
731 for(i = 0; i < nrhs; i++)
734 int result = solve(&(b[k]), &(x[k]));
737 std::cout <<
"Error in Solving \n";
745 template <
class Int,
class Entry>
746 int BaskerClassic<Int, Entry>::solve(Entry* b, Entry* x)
754 Entry* temp =
new Entry[A->nrow]();
757 for(i = 0 ; i < A->ncol; i++)
763 result = low_tri_solve_csc(L->nrow, L->col_ptr, L->row_idx, L->val, temp, x);
766 result = up_tri_solve_csc(U->nrow, U->col_ptr, U->row_idx, U->val, x, temp);
775 template <
class Int,
class Entry>
776 int BaskerClassic<Int, Entry>::low_tri_solve_csc( Int n, Int *col_ptr, Int *row_idx, Entry* val, Entry *x, Entry *b)
780 for(i = 0; i < n ; i++)
783 BASKERASSERT(val[col_ptr[i]] != (Entry)0);
785 if(val[col_ptr[i]] == (Entry) 0)
790 x[i] = BASKER_ScalarTraits<Entry>::divide(b[i], val[col_ptr[i]]);
792 for(j = col_ptr[i]+1; j < (col_ptr[i+1]); j++)
794 b[pinv[row_idx[j]]] = b[pinv[row_idx[j]]] - (val[j]*x[i]);
800 template <
class Int,
class Entry>
801 int BaskerClassic<Int, Entry>::up_tri_solve_csc( Int n, Int *col_ptr, Int *row_idx, Entry *val, Entry *x, Entry *b)
805 for(i = n; i > 1 ; i--)
809 BASKERASSERT(val[col_ptr[i]-1] != (Entry)0);
811 if(val[col_ptr[i]-1] == (Entry) 0)
813 std::cout <<
"Dig(" << i <<
") = " << val[col_ptr[i]-1] << std::endl;
818 x[ii] = BASKER_ScalarTraits<Entry>::divide(b[ii],val[col_ptr[i]-1]);
820 for(j = (col_ptr[i]-2); j >= (col_ptr[ii]); j--)
822 b[row_idx[j]] = b[row_idx[j]] - (val[j]*x[ii]);
826 x[0] = BASKER_ScalarTraits<Entry>::divide(b[0],val[col_ptr[1]-1]);
830 template <
class Int,
class Entry>
831 int BaskerClassic<Int, Entry>::preorder(Int *row_perm, Int *col_perm)
834 basker_matrix <Int, Entry> *B;
835 B =
new basker_matrix<Int, Entry>;
839 B->col_ptr = (Int *) BASKERCALLOC(A->ncol + 1,
sizeof(Int));
840 B->row_idx = (Int *) BASKERCALLOC(A->nnz,
sizeof(Int));
841 B->val = (Entry *) BASKERCALLOC(A->val,
sizeof(Int));
843 if( (B->col_ptr ==
nullptr) || (B->row_idx ==
nullptr) || (B->val ==
nullptr) )
849 (void) permute_column(col_perm, B);
850 (void) permute_row(row_perm, B);
854 A->col_ptr = B->col_ptr;
855 A->row_idx = B->row_idx;
863 template <
class Int,
class Entry>
864 int BaskerClassic <Int, Entry>::permute_column(Int *p, basker_matrix<Int,Entry> *B)
870 for(j=0; j < B->ncol; j++)
873 B->col_ptr[i+1] = A->col_ptr[j+1] - A->col_ptr[j];
877 for(j=0; j < B->ncol; j++)
879 B->col_ptr[j+1] = B->col_ptr[j+1] + B->col_ptr[j];
884 for(ii = 0 ; ii < B->ncol; ii++)
886 ko = B->col_ptr(p[ii]);
887 for(k = A->col_ptr[ii]; k < A->col_ptr[ii+1]; k++)
889 B->row_index[ko] = A->row_index[k];
890 B->val[ko] = A->val[ko];
897 template <
class Int,
class Entry>
898 int BaskerClassic <Int, Entry>::permute_row(Int *p, basker_matrix<Int,Entry> *B)
901 for(k=0; k < A->nnz; k++)
903 B->row_idx[k] = p[A->row_idx[k]];
908 template <
class Int,
class Entry>
909 int BaskerClassic <Int, Entry>::sort_factors()
916 for(i = 0 ; i < L->ncol; i++)
921 for(j = L->col_ptr[i]+1; j < (L->col_ptr[i+1]); j++)
923 if(L->row_idx[j] < val)
929 Int temp_index = L->row_idx[L->col_ptr[i]];
930 Entry temp_entry = L->val[L->col_ptr[i]];
931 L->row_idx[L->col_ptr[i]] = val;
932 L->val[L->col_ptr[i]] = L->val[p];
933 L->row_idx[p] = temp_index;
934 L->val[p] = temp_entry;
939 for(i = 0 ; i < U->ncol; i++)
941 p = U->col_ptr[i+1]-1;
944 for(j = U->col_ptr[i]; j < (U->col_ptr[i+1]-1); j++)
946 if(U->row_idx[j] > val)
952 Int temp_index = U->row_idx[U->col_ptr[i+1]-1];
953 Entry temp_entry = U->val[U->col_ptr[i+1]-1];
954 U->row_idx[U->col_ptr[i+1]-1] = val;
955 U->val[U->col_ptr[i+1]-1] = U->val[p];
956 U->row_idx[p] = temp_index;
957 U->val[p] = temp_entry;
963 template <
class Int,
class Entry>
964 Entry* BaskerClassic <Int, Entry>::entry_realloc(Entry *old , Int old_size, Int new_size)
966 Entry *new_entry =
new Entry[new_size];
967 for(Int i = 0; i < old_size; i++)
970 new_entry[i] = old[i];
977 template <
class Int,
class Entry>
978 Int* BaskerClassic <Int, Entry>::int_realloc(Int *old, Int old_size, Int new_size)
980 Int *new_int =
new Int[new_size];
981 for(Int i =0; i < old_size; i++)