Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
basker_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Basker: A Direct Linear Solver package
4 //
5 // Copyright 2011 NTESS and the Basker contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef BASKER_DEF_HPP
11 #define BASKER_DEF_HPP
12 
13 #include "basker_decl.hpp"
14 #include "basker_scalartraits.hpp"
15 //#include "basker.hpp"
16 
17 //#include <cassert>
18 #include <iostream>
19 #include <cstdio>
20 
21 using namespace std;
22 
23 //#define BASKER_DEBUG 1
24 //#undef UDEBUG
25 
26 namespace BaskerClassicNS{
27 
28  template <class Int, class Entry>
29  BaskerClassic<Int, Entry>::BaskerClassic()
30  {
31 
32  //A = (basker_matrix<Int,Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
33  A = new basker_matrix<Int,Entry>;
34 
35  //L = (basker_matrix<Int,Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
36  L = new basker_matrix<Int, Entry>;
37  L->nnz = 0;
38 
39  //U = (basker_matrix<Int,Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
40  U = new basker_matrix<Int,Entry>;
41  U->nnz = 0;
42 
43  actual_lnnz = Int(0);
44  actual_unnz = Int(0);
45 
46  been_fact = false;
47  perm_flag = false;
48  }
49 
50 
51  template <class Int, class Entry>
52  BaskerClassic<Int, Entry>::BaskerClassic(Int nnzL, Int nnzU)
53  {
54 
55  //A = (basker_matrix<Int, Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
56  A = new basker_matrix<Int, Entry>;
57  //L = (basker_matrix<Int, Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
58  L = new basker_matrix<Int, Entry>;
59  L->nnz = nnzL;
60  //U = (basker_matrix<Int, Entry> *) malloc(sizeof(basker_matrix<Int,Entry>));
61  U = new basker_matrix<Int, Entry>;
62  U->nnz = nnzU;
63 
64  actual_lnnz = Int(0);
65  actual_unnz = Int(0);
66 
67  been_fact = false;
68  perm_flag = false;
69  }
70 
71 
72  template <class Int, class Entry>
73  BaskerClassic<Int, Entry>::~BaskerClassic()
74  {
75  //free factor
76  if(been_fact)
77  {
78  free_factor();
79  //BASKERFREE(pinv);
80  delete [] pinv;
81  }
82  if(perm_flag)
83  {
84  //free_perm_matrix();
85  }
86  //BASKERFREE(A);
87  delete A;
88  //BASKERFREE(L);
89  delete L;
90  //BASKERFREE(U);
91  delete U;
92  }
93 
94 
95  template <class Int, class Entry>
96  int BaskerClassic<Int,Entry>:: basker_dfs
97  (
98  Int n,
99  Int j,
100  Int *Li,
101  Int *Lp,
102  Int *color,
103  Int *pattern, /* o/p */
104  Int *top, /* o/p */
105  //Int k,
106  Int *tpinv,
107  Int *stack
108  )
109  {
110 
111  Int i, t, i1, head ;
112  Int start, end, done, *store ;
113 
114  store = stack + n ;
115  head = 0;
116  stack[head] = j;
117  bool has_elements = true;
118 
119  while(has_elements)
120  {
121  j = stack[head] ;
122 #ifdef BASKER_DEBUG
123  //std::cout << "DFS: " << j << "COLOR: " << color[j] << std::endl;
124 #endif
125  t = tpinv [j] ;
126  if (color[j] == 0)
127  {
128  /* Seeing this column for first time */
129  color[j] = 1 ;
130  start = Lp[t] ;
131  }
132  else
133  {
134  BASKERASSERT (color[j] == 1) ; /* color cannot be 2 when we are here */
135  start = store[j];
136  }
137  done = 1;
138 
139  if ( t != n )
140  {
141  end = Lp[t+1] ;
142  for ( i1 = start ; i1 < end ; i1++ )
143  {
144  i = Li[i1] ;
145  if ( color[i] == 0 )
146  {
147  stack[++head] = i;
148  store[j] = i1+1;
149  done = 0;
150  break;
151  }
152  }
153  }
154  if (done)
155  {
156  pattern[--*top] = j ;
157  color[j] = 2 ;
158  if(head == 0)
159  {
160  has_elements = false;
161  }
162  else
163  {
164  head--;
165  }
166  }
167  }
168 #ifdef BASKER_DEBUG
169  std::cout << "Out of DFS: " << j << std::endl;
170 #endif
171  return 0;
172  } //End dfs
173 
174  template <class Int, class Entry>
175  int BaskerClassic<Int,Entry>::factor(Int nrow, Int ncol , Int nnz, Int *col_ptr, Int *row_idx, Entry *val)
176  {
177  int ierr = 0;
178  /*Initalize A basker matrix struc */
179 #ifdef BASKER_DEBUG
180 
181  BASKERASSERT(nrow > 0);
182  BASKERASSERT(ncol > 0);
183  BASKERASSERT(nnz > 0);
184 
185 #endif
186 
187  A->nrow = nrow;
188  A->ncol = ncol;
189  A->nnz = nnz;
190  A->col_ptr = col_ptr;
191  A->row_idx = row_idx;
192  A->val = val;
193  /*End initalize A*/
194 
195  //free factor
196  if(been_fact)
197  {
198  free_factor();
199  //BASKERFREE(pinv);
200  delete [] pinv;
201  }
202 
203  /*Creating space for L and U*/
204  L->nrow = nrow;
205  L->ncol = ncol;
206  if(L->nnz == 0)
207  {
208  L->nnz = 2*A->nnz;
209  }
210  //L->col_ptr = (Int *) BASKERCALLOC(ncol+1, sizeof(Int));
211  L->col_ptr = new Int[ncol+1]();
212  //L->row_idx = (Int *) BASKERCALLOC(L->nnz, sizeof(Int));
213  L->row_idx = new Int[L->nnz]();
214  //L->val = (Entry *) BASKERCALLOC(L->nnz, sizeof(Entry));
215  L->val = new Entry[L->nnz]();
216 
217  U->nrow = nrow;
218  U->ncol = ncol;
219  if(U->nnz == 0)
220  {
221  U->nnz = 2*A->nnz;
222  }
223  //U->col_ptr = (Int *) BASKERCALLOC(ncol+1, sizeof(Int));
224  U->col_ptr = new Int[ncol+1]();
225  //U->row_idx = (Int *) BASKERCALLOC(U->nnz, sizeof(Int));
226  U->row_idx = new Int[U->nnz]();
227  //U->val = (Entry *) BASKERCALLOC(U->nnz, sizeof(Entry));
228  U->val = new Entry[U->nnz]();
229 
230  if((L->col_ptr == nullptr) || (L->row_idx == nullptr) || (L->val == nullptr) ||
231  (U->col_ptr == nullptr) || (U->row_idx == nullptr) || (U->val == nullptr))
232  {
233  ierr = -1;
234  return ierr;
235  }
236  /*End creating space for L and U*/
237 
238  /*Creating working space*/
239  Int *color, *pattern, *stack;
240  Entry *X;
241  color = new Int[ncol]();
242  pattern = new Int[nrow]();
243  stack = new Int[2*nrow]();
244  //X = (Entry *) BASKERCALLOC(2*nrow, sizeof(Entry));
245  X = new Entry[2*nrow]();
246  //pinv = (Int * ) BASKERCALLOC(ncol+1, sizeof(Int)); //Note extra pad
247  pinv = new Int[ncol+1]();
248 
249 
250  if( (color == nullptr) || (pattern == nullptr) || (stack == nullptr) || (X == nullptr) || (pinv == nullptr) )
251  {
252  ierr = -2;
253  return ierr;
254  }
255 
256  /*End creating working space */
257 
258  /*Defining Variables Used*/
259  Int i, j, k;
260  Int top, top1, maxindex, t; // j1, j2;
261  Int lnnz, unnz, xnnz, lcnt, ucnt;
262  Int cu_ltop, cu_utop;
263  Int pp, p2, p;
264  Int newsize;
265  Entry pivot, value, xj;
266  Entry absv, maxv;
267 
268  cu_ltop = 0;
269  cu_utop = 0;
270  top = ncol;
271  top1 = ncol;
272  lnnz = 0; //real found lnnz
273  unnz = 0; //real found unnz
274 
275  for(k = 0 ; k < ncol; k++)
276  {
277  pinv[k] = ncol;
278  }
279 
280  /*For all columns in A .... */
281  for (k = 0; k < ncol; k++)
282  {
283 
284 #ifdef BASKER_DEBUG
285  cout << "k = " << k << endl;
286 #endif
287 
288  value = 0.0;
289  pivot = 0.0;
290  maxindex = ncol;
291  //j1 = 0;
292  //j2 = 0;
293  lcnt = 0;
294  ucnt = 0;
295 
296 #ifdef BASKER_DEBUG
297  BASKERASSERT (top == ncol);
298 
299  for(i = 0; i < nrow; i++)
300  {
301  BASKERASSERT(X[i] == (Entry)0);
302  }
303  for(i = 0; i < ncol; i++)
304  {
305  BASKERASSERT(color[i] == 0);
306  }
307 #endif
308  /* Reachability for every nonzero in Ak */
309  for( i = col_ptr[k]; i < col_ptr[k+1]; i++)
310  {
311  j = row_idx[i];
312  X[j] = val[i];
313 
314  if(color[j] == 0)
315  {
316  //do dfs
317  basker_dfs(nrow, j, L->row_idx, L->col_ptr, color, pattern, &top, pinv, stack);
318 
319  }
320 
321  }//end reachable
322 
323  xnnz = ncol - top;
324 #ifdef BASKER_DEBUG
325  cout << top << endl;
326  cout << ncol << endl;
327  cout << xnnz << endl;
328  //BASKERASSERT(xnnz <= nrow);
329 #endif
330  /*Lx = b where x will be the column k in L and U*/
331  top1 = top;
332  for(pp = 0; pp < xnnz; pp++)
333  {
334  j = pattern[top1++];
335  color[j] = 0;
336  t = pinv[j];
337 
338  if(t!=ncol) //it has not been assigned
339  {
340  xj = X[j];
341  p2 = L->col_ptr[t+1];
342  for(p = L->col_ptr[t]+1; p < p2; p++)
343  {
344  X[L->row_idx[p]] -= L->val[p] * xj;
345  }//over all rows
346  }
347 
348  }
349 
350  /*get the pivot*/
351  maxv = 0.0;
352  for(i = top; i < nrow; i++)
353  {
354  j = pattern[i];
355  t = pinv[j];
356  value = X[j];
357  /*note may want to change this to traits*/
358  //absv = (value < 0.0 ? -value : value);
359  absv = BASKER_ScalarTraits<Entry>::approxABS(value);
360 
361  if(t == ncol)
362  {
363  lcnt++;
364  if( BASKER_ScalarTraits<Entry>::gt(absv , maxv))
365  //if(absv > BASKER_ScalarTraits<Entry>::approxABS(maxv))
366  {
367  maxv = absv;
368  pivot = value;
369  maxindex= j;
370  }
371  }
372  }
373  ucnt = nrow - top - lcnt + 1;
374 
375  if(maxindex == ncol || pivot == ((Entry)0))
376  {
377  cout << "Matrix is singular at index: " << maxindex << " pivot: " << pivot << endl;
378  ierr = maxindex;
379  return ierr;
380  }
381 
382  pinv[maxindex] = k;
383 #ifdef BASKER_DEBUG
384  if(maxindex != k )
385  {
386  cout << "Permuting pivot: " << k << " for row: " << maxindex << endl;
387  }
388 #endif
389 
390  if(lnnz + lcnt >= L->nnz)
391  {
392 
393  newsize = L->nnz * 1.1 + 2*nrow + 1;
394 #ifdef BASKER_DEBUG
395  cout << "Out of memory -- Reallocating. Old Size: " << L->nnz << " New Size: " << newsize << endl;
396 #endif
397  //L->row_idx = (Int *) BASKERREALLOC(L->row_idx, newsize*sizeof(Int));
398  L->row_idx = int_realloc(L->row_idx , L->nnz, newsize);
399  if(!(L->row_idx))
400  {
401  cout << "WARNING: Cannot Realloc Memory" << endl;
402  ierr = -3;
403  return ierr;
404  }
405  //L->val = (Entry *) BASKERREALLOC(L->val, newsize*sizeof(Entry));
406  L->val = entry_realloc(L->val, L->nnz, newsize);
407  if(!(L->val))
408  {
409  cout << "WARNING: Cannot Realloc Memory" << endl;
410  ierr = -3;
411  return ierr;
412  }
413  L->nnz = newsize;
414 
415  }//realloc if L is out of memory
416 
417  if(unnz + ucnt >= U->nnz)
418  {
419  newsize = U->nnz*1.1 + 2*nrow + 1;
420 #ifdef BASKER_DEBUG
421  cout << "Out of memory -- Reallocating. Old Size: " << U->nnz << " New Size: " << newsize << endl;
422 #endif
423  //U->row_idx = (Int *) BASKERREALLOC(U->row_idx, newsize*sizeof(Int));
424  U->row_idx = int_realloc(U->row_idx, U->nnz, newsize);
425  if(!(U->row_idx))
426  {
427  cout << "WARNING: Cannot Realloc Memory" << endl;
428  ierr = -3;
429  return ierr;
430  }
431 
432  //U->val = (Entry *) BASKERREALLOC(U->val, newsize*sizeof(Entry));
433  U->val = entry_realloc(U->val, U->nnz, newsize);
434  if(!(U->val))
435  {
436  cout << "WARNING: Cannot Realloc Memory" << endl;
437  ierr = -3;
438  return ierr;
439  }
440  U->nnz = newsize;
441  }//realloc if U is out of memory
442 
443  //L->col_ptr[lnnz] = maxindex;
444  L->row_idx[lnnz] = maxindex;
445  L->val[lnnz] = 1.0;
446  lnnz++;
447 
448  Entry last_v_temp = 0;
449 
450  for(i = top; i < nrow; i++)
451  {
452  j = pattern[i];
453  t = pinv[j];
454 
455  /* check for numerical cancellations */
456 
457 
458  if(X[j] != ((Entry)0))
459  {
460 
461  if(t != ncol)
462  {
463  if(unnz >= U->nnz)
464  {
465  cout << "BASKER: Insufficent memory for U" << endl;
466  ierr = -3;
467  return ierr;
468  }
469  if(t < k)
470  //if(true)
471  {
472  U->row_idx[unnz] = pinv[j];
473  U->val[unnz] = X[j];
474  unnz++;
475  }
476  else
477  {
478 
479  last_v_temp = X[j];
480  //cout << "Called. t: " << t << "Val: " << last_v_temp << endl;
481  }
482 
483  }
484  else if (t == ncol)
485  {
486  if(lnnz >= L->nnz)
487  {
488  cout << "BASKER: Insufficent memory for L" << endl;
489  ierr = -3;
490  return ierr;
491  }
492 
493  L->row_idx[lnnz] = j;
494  //L->val[lnnz] = X[j]/pivot;
495  L->val[lnnz] = BASKER_ScalarTraits<Entry>::divide(X[j],pivot);
496  lnnz++;
497 
498  }
499 
500  }
501 
502 
503  X[j] = 0;
504 
505  }
506  //cout << "Value added at end: " << last_v_temp << endl;
507  U->row_idx[unnz] = k;
508  U->val[unnz] = last_v_temp;
509  unnz++;
510 
511  xnnz = 0;
512  top = ncol;
513 
514  L->col_ptr[k] = cu_ltop;
515  L->col_ptr[k+1] = lnnz;
516  cu_ltop = lnnz;
517 
518  U->col_ptr[k] = cu_utop;
519  U->col_ptr[k+1] = unnz;
520  cu_utop = unnz;
521 
522  } //end for every column
523 
524 #ifdef BASKER_DEBUG
525  /*Print out found L and U*/
526  for(k = 0; k < lnnz; k++)
527  {
528  printf("L[%d]=%g" , k , L->val[k]);
529  }
530  cout << endl;
531  for(k = 0; k < lnnz; k++)
532  {
533  printf("Li[%d]=%d", k, L->row_idx[k]);
534  }
535  cout << endl;
536  for(k = 0; k < nrow; k++)
537  {
538  printf("p[%d]=%d", k, pinv[k]);
539  }
540  cout << endl;
541  cout << endl;
542 
543  for(k = 0; k < ncol; k++)
544  {
545  printf("Up[%d]=%d", k, U->col_ptr[k]);
546  }
547  cout << endl;
548 
549  for(k = 0; k < unnz; k++)
550  {
551  printf("U[%d]=%g" , k , U->val[k]);
552  }
553  cout << endl;
554  for(k = 0; k < unnz; k++)
555  {
556  printf("Ui[%d]=%d", k, U->row_idx[k]);
557  }
558  cout << endl;
559 
560 
561 #endif
562  /* Repermute */
563  for( i = 0; i < ncol; i++)
564  {
565  for(k = L->col_ptr[i]; k < L->col_ptr[i+1]; k++)
566  {
567  //L->row_idx[k] = pinv[L->row_idx[k]];
568  }
569  }
570  //Max sure correct location of min in L and max in U for CSC format//
571  //Speeds up tri-solve//
572  //sort_factors();
573 
574 #ifdef BASKER_DEBUG
575  cout << "After Permuting" << endl;
576  for(k = 0; k < lnnz; k++)
577  {
578  printf("Li[%d]=%d", k, L->row_idx[k]);
579  }
580  cout << endl;
581 #endif
582 
583  // Cleanup workspace allocations
584  delete [] X;
585  delete [] color;
586  delete [] pattern;
587  delete [] stack;
588 
589  actual_lnnz = lnnz;
590  actual_unnz = unnz;
591 
592  been_fact = true;
593  return 0;
594  }//end factor
595 
596 
597  template <class Int, class Entry>
598  Int BaskerClassic<Int, Entry>::get_NnzL()
599  {
600  return actual_lnnz;
601  }
602 
603  template <class Int, class Entry>
604  Int BaskerClassic<Int, Entry>::get_NnzU()
605  {
606  return actual_unnz;
607  }
608 
609  template <class Int, class Entry>
610  Int BaskerClassic<Int, Entry>::get_NnzLU()
611  {
612  return (actual_lnnz + actual_unnz);
613  }
614 
615  template <class Int, class Entry>
616  int BaskerClassic<Int, Entry>::returnL(Int *dim, Int *nnz, Int **col_ptr, Int **row_idx, Entry **val)
617  {
618  int i;
619  *dim = L->nrow;
620  *nnz = L->nnz;
621 
622  /*Does a bad copy*/
623 
624  //*col_ptr = (Int *) BASKERCALLOC(L->nrow+1, sizeof(Int));
625  *col_ptr = new Int[L->nrow+1];
626  //*row_idx = (Int *) BASKERCALLOC(L->nnz, sizeof(Int));
627  *row_idx = new Int[L->nnz];
628  //*val = (Entry *) BASKERCALLOC(L->nnz, sizeof(Entry));
629  *val = new Entry[L->nnz];
630 
631  if( (*col_ptr == nullptr) || (*row_idx == nullptr) || (*val == nullptr) )
632  {
633  return -1;
634  }
635 
636  for(i = 0; i < L->nrow+1; i++)
637  {
638  (*col_ptr)[i] = L->col_ptr[i];
639  }
640 
641  for(i = 0; i < actual_lnnz; i++)
642  {
643  (*row_idx)[i] = pinv[L->row_idx[i]];
644  (*val)[i] = L->val[i];
645  }
646  return 0;
647 
648  }
649 
650  template <class Int, class Entry>
651  int BaskerClassic<Int, Entry>::returnU(Int *dim, Int *nnz, Int **col_ptr, Int **row_idx, Entry **val)
652  {
653  int i;
654  *dim = U->nrow;
655  *nnz = U->nnz;
656  /*Does a bad copy*/
657  //*col_ptr = (Int *) BASKERCALLOC(U->nrow+1, sizeof(Int));
658  *col_ptr = new Int[U->nrow+1];
659  //*row_idx = (Int *) BASKERCALLOC(U->nnz, sizeof(Int));
660  *row_idx = new Int[U->nnz];
661  //*val = (Entry *) BASKERCALLOC(U->nnz, sizeof(Entry));
662  *val = new Entry[U->nnz];
663 
664  if( (*col_ptr == nullptr) || (*row_idx == nullptr) || (*val == nullptr) )
665  {
666  return -1;
667  }
668 
669  for(i = 0; i < U->nrow+1; i++)
670  {
671  (*col_ptr)[i] = U->col_ptr[i];
672  }
673  for(i = 0; i < actual_unnz; i++)
674  {
675  (*row_idx)[i] = U->row_idx[i];
676  (*val)[i] = U->val[i];
677  }
678  return 0;
679  }
680 
681  template <class Int, class Entry>
682  int BaskerClassic<Int, Entry>::returnP(Int** p)
683  {
684  Int i;
685  //*p = (Int *) BASKERCALLOC(A->nrow, sizeof(Int));
686  *p = new Int[A->nrow];
687 
688  if( (*p == nullptr ) )
689  {
690  return -1;
691  }
692 
693  for(i = 0; i < A->nrow; i++)
694  {
695  (*p)[pinv[i]] = i; //Matlab perm-style
696  }
697  return 0;
698  }
699 
700  template <class Int, class Entry>
701  void BaskerClassic<Int, Entry>::free_factor()
702  {
703  //BASKERFREE L
704  //BASKERFREE(L->col_ptr);
705  delete[] L->col_ptr;
706  //BASKERFREE(L->row_idx);
707  delete[] L->row_idx;
708  //BASKERFREE(L->val);
709  delete[] L->val;
710 
711  //BASKERFREE U
712  //BASKERFREE(U->col_ptr);
713  delete[] U->col_ptr;
714  //BASKERFREE(U->row_idx);
715  delete[] U->row_idx;
716  //BASKERFREE(U->val);
717  delete[] U->val;
718 
719  been_fact = false;
720  }
721  template <class Int, class Entry>
722  void BaskerClassic<Int, Entry>::free_perm_matrix()
723  {
724  //BASKERFREE(A->col_ptr);
725  //BASKERFREE(A->row_idx);
726  //BASKERFREE(A->val);
727  }
728 
729  template <class Int, class Entry>
730  int BaskerClassic<Int, Entry>::solveMultiple(Int nrhs, Entry *b, Entry *x)
731  {
732  Int i;
733  for(i = 0; i < nrhs; i++)
734  {
735  Int k = i*A->nrow;
736  int result = solve(&(b[k]), &(x[k]));
737  if(result != 0)
738  {
739  cout << "Error in Solving \n";
740  return result;
741  }
742  }
743  return 0;
744  }
745 
746 
747  template <class Int, class Entry>
748  int BaskerClassic<Int, Entry>::solve(Entry* b, Entry* x)
749  {
750 
751  if(!been_fact)
752  {
753  return -10;
754  }
755  //Entry* temp = (Entry *)BASKERCALLOC(A->nrow, sizeof(Entry));
756  Entry* temp = new Entry[A->nrow]();
757  Int i;
758  int result = 0;
759  for(i = 0 ; i < A->ncol; i++)
760  {
761  Int k = pinv[i];
762  x[k] = b[i];
763  }
764 
765  result = low_tri_solve_csc(L->nrow, L->col_ptr, L->row_idx, L->val, temp, x);
766  if(result == 0)
767  {
768  result = up_tri_solve_csc(U->nrow, U->col_ptr, U->row_idx, U->val, x, temp);
769  }
770 
771 
772  //BASKERFREE(temp);
773  delete[] temp;
774  return 0;
775  }
776 
777  template < class Int, class Entry>
778  int BaskerClassic<Int, Entry>::low_tri_solve_csc( Int n, Int *col_ptr, Int *row_idx, Entry* val, Entry *x, Entry *b)
779  {
780  Int i, j;
781  /*for each column*/
782  for(i = 0; i < n ; i++)
783  {
784 #ifdef BASKER_DEBUG
785  BASKERASSERT(val[col_ptr[i]] != (Entry)0);
786 #else
787  if(val[col_ptr[i]] == (Entry) 0)
788  {
789  return i;
790  }
791 #endif
792  x[i] = BASKER_ScalarTraits<Entry>::divide(b[i], val[col_ptr[i]]);
793 
794  for(j = col_ptr[i]+1; j < (col_ptr[i+1]); j++) //update all rows
795  {
796  b[pinv[row_idx[j]]] = b[pinv[row_idx[j]]] - (val[j]*x[i]);
797  }
798  }
799  return 0;
800  }
801 
802  template < class Int, class Entry>
803  int BaskerClassic<Int, Entry>::up_tri_solve_csc( Int n, Int *col_ptr, Int *row_idx, Entry *val, Entry *x, Entry *b)
804  {
805  Int i, j;
806  /*for each column*/
807  for(i = n; i > 1 ; i--)
808  {
809  int ii = i-1;
810 #ifdef BASKER_DEBUG
811  BASKERASSERT(val[col_ptr[i]-1] != (Entry)0);
812 #else
813  if(val[col_ptr[i]-1] == (Entry) 0)
814  {
815  cout << "Dig(" << i << ") = " << val[col_ptr[i]-1] << endl;
816  return i;
817  }
818 #endif
819  //x[ii] = b[ii]/val[col_ptr[i]-1]; //diag
820  x[ii] = BASKER_ScalarTraits<Entry>::divide(b[ii],val[col_ptr[i]-1]);
821 
822  for(j = (col_ptr[i]-2); j >= (col_ptr[ii]); j--)
823  {
824  b[row_idx[j]] = b[row_idx[j]] - (val[j]*x[ii]);
825  }
826  }
827  //x[0] = b[0]/val[col_ptr[1]-1];
828  x[0] = BASKER_ScalarTraits<Entry>::divide(b[0],val[col_ptr[1]-1]);
829  return 0;
830  }
831 
832  template <class Int, class Entry>
833  int BaskerClassic<Int, Entry>::preorder(Int *row_perm, Int *col_perm)
834  {
835 
836  basker_matrix <Int, Entry> *B;
837  B = new basker_matrix<Int, Entry>;
838  B->nrow = A->nrow;
839  B->ncol = A->ncol;
840  B->nnz = A->nnz;
841  B->col_ptr = (Int *) BASKERCALLOC(A->ncol + 1, sizeof(Int));
842  B->row_idx = (Int *) BASKERCALLOC(A->nnz, sizeof(Int));
843  B->val = (Entry *) BASKERCALLOC(A->val, sizeof(Int));
844 
845  if( (B->col_ptr == nullptr) || (B->row_idx == nullptr) || (B->val == nullptr) )
846  {
847  perm_flag = false;
848  return -1;
849  }
850 
851  /* int resultcol = (unused) */ (void) permute_column(col_perm, B);
852  /* int resultrow = (unused) */ (void) permute_row(row_perm, B);
853 
854  /*Note: the csc matrices of A are the problem of the user
855  therefore we will not free them*/
856  A->col_ptr = B->col_ptr;
857  A->row_idx = B->row_idx;
858  A->val = A->val;
859 
860  perm_flag = true; /*Now we will free A at the end*/
861 
862  return 0;
863  }
864 
865  template <class Int, class Entry>
866  int BaskerClassic <Int, Entry>::permute_column(Int *p, basker_matrix<Int,Entry> *B)
867  {
868  /*p(i) contains the destination of row i in the permuted matrix*/
869  Int i,j, ii, jj;
870 
871  /*Determine column pointer of output matrix*/
872  for(j=0; j < B->ncol; j++)
873  {
874  i = p[j];
875  B->col_ptr[i+1] = A->col_ptr[j+1] - A->col_ptr[j];
876  }
877  /*get pointers from lengths*/
878  B->col_ptr[0] = 0;
879  for(j=0; j < B->ncol; j++)
880  {
881  B->col_ptr[j+1] = B->col_ptr[j+1] + B->col_ptr[j];
882  }
883 
884  /*copy idxs*/
885  Int k, ko;
886  for(ii = 0 ; ii < B->ncol; ii++)
887  {// old colum ii new column p[ii] k->pointer
888  ko = B->col_ptr(p[ii]);
889  for(k = A->col_ptr[ii]; k < A->col_ptr[ii+1]; k++)
890  {
891  B->row_index[ko] = A->row_index[k];
892  B->val[ko] = A->val[ko];
893  ko++;
894  }
895  }
896  return 0;
897  }
898 
899  template <class Int, class Entry>
900  int BaskerClassic <Int, Entry>::permute_row(Int *p, basker_matrix<Int,Entry> *B)
901  {
902  Int k,i;
903  for(k=0; k < A->nnz; k++)
904  {
905  B->row_idx[k] = p[A->row_idx[k]];
906  }
907  return 0;
908  }
909 
910  template <class Int, class Entry>
911  int BaskerClassic <Int, Entry>::sort_factors()
912  {
913 
914  /*Sort CSC of L - just make sure min_index is in lowest position*/
915  Int i, j;
916  Int p;
917  Int val;
918  for(i = 0 ; i < L->ncol; i++)
919  {
920  p = L->col_ptr[i];
921  val = L->row_idx[p];
922 
923  for(j = L->col_ptr[i]+1; j < (L->col_ptr[i+1]); j++)
924  {
925  if(L->row_idx[j] < val)
926  {
927  p = j;
928  val = L->row_idx[p];
929  }
930  }
931  Int temp_index = L->row_idx[L->col_ptr[i]];
932  Entry temp_entry = L->val[L->col_ptr[i]];
933  L->row_idx[L->col_ptr[i]] = val;
934  L->val[L->col_ptr[i]] = L->val[p];
935  L->row_idx[p] = temp_index;
936  L->val[p] = temp_entry;
937  }//end for all columns
938 
939 
940  /* Sort CSC U --- just make sure max is in right location*/
941  for(i = 0 ; i < U->ncol; i++)
942  {
943  p = U->col_ptr[i+1]-1;
944  val = U->row_idx[p];
945 
946  for(j = U->col_ptr[i]; j < (U->col_ptr[i+1]-1); j++)
947  {
948  if(U->row_idx[j] > val)
949  {
950  p = j;
951  val = U->row_idx[p];
952  }
953  }
954  Int temp_index = U->row_idx[U->col_ptr[i+1]-1];
955  Entry temp_entry = U->val[U->col_ptr[i+1]-1];
956  U->row_idx[U->col_ptr[i+1]-1] = val;
957  U->val[U->col_ptr[i+1]-1] = U->val[p];
958  U->row_idx[p] = temp_index;
959  U->val[p] = temp_entry;
960  }//end for all columns
961 
962  return 0;
963  }
964 
965  template <class Int, class Entry>
966  Entry* BaskerClassic <Int, Entry>::entry_realloc(Entry *old , Int old_size, Int new_size)
967  {
968  Entry *new_entry = new Entry[new_size];
969  for(Int i = 0; i < old_size; i++)
970  {
971  /*Assumption that Entry was own defined copy constructor*/
972  new_entry[i] = old[i];
973  }
974  delete[] old;
975  return new_entry;
976 
977 
978  }
979  template <class Int, class Entry>
980  Int* BaskerClassic <Int, Entry>::int_realloc(Int *old, Int old_size, Int new_size)
981  {
982  Int *new_int = new Int[new_size];
983  for(Int i =0; i < old_size; i++)
984  {
985  /*Assumption that Int was own defined copy constructor*/
986  new_int[i] = old[i];
987  }
988  delete[] old;
989  return new_int;
990 
991  }
992 
993 
994 }//end namespace
995 #endif