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