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
21using namespace std;
22
23//#define BASKER_DEBUG 1
24//#undef UDEBUG
25
26namespace 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