2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * Sparse matrix package
23 * Bump and spike - bordered block diagonal pattern
24 * -------------------------------------------------
25 * To use it (simple method) .....
28 * 2. Then tell it what slots to allocate, in a loop ...
29 * for (all pairs i,j that might exist)
31 * 3. Then do the actual allocation ...
33 * 4. If you want, you can add an offset to the diagonal ...
35 * 5. You probably should set a minimum pivot value ...
36 * a.set_min_pivot(gmin);
37 * 6. Fill in the matrix ...
38 * for (all pairs i,j you want to fill in)
40 * 7. Then do the LU decomposition ...
42 * 8. Then get the solution by applying the right side vector (v)
43 * and doing the fwd and back substitution.
45 * The solution is now in v.
46 * -------------------------------------------------
48 * Get rid of the old data ...
50 * Restore the offset, if you want ...
52 * Then fill and solve as before. (steps 6-8)
53 * -------------------------------------------------
54 * In the above case, LU replaced the matrix and the solution replaced
55 * the right side, losing the data.
56 * To keep the matrix, and keep the right side ...
57 * 1. Declare two matrices ...
59 * BSMATRIX<double> lu;
61 * 2a. Say the lu has the same structure as a.
64 * 6. Fill in "a" only.
65 * 7. Do the LU decomposition, keeping a, with result in lu ...
66 * lu.lu_decomp(a, false);
67 * 8. Do the f&B sub, keeping b (the right side), with result in x ...
69 * -------------------------------------------------
70 * To make a change to the matrix and re-solve ...
71 * Apply the change to a ...
72 * for (all changes you want to make)
73 * a.m(i,j) += delta; a.set_changed(i).set_changed(j)
74 * Then solve again .. step 7 above for a full solution,
75 * or for an update ...
76 * lu.lu_decomp(a, true);
77 * Then do the same step 8 as above.
78 * -------------------------------------------------
79 * some other functions that might be useful ....
80 * reinit(newsize) -- change the size (and lose the contents and structure)
81 * size()const -- return the size (# of rows & cols)
82 * density()const -- return the matrix density, as a number between 0 and 1
83 * sparsity()const -- 1-density
84 * -------------------------------------------------
85 * individual element access ...
86 * 5 access functions are provided.
87 * All return lvalues (references to the actual entry).
88 * All take 2 args, row and column. They differ in speed and generality.
89 * Since they are used in equations, they all have 1 letter names.
90 * s(r,c) -- "safe" -- most general case, with bounds checking
91 * if completely out of bounds, returns trash
92 * if in the matrix but out of band, returns a reference to zero
93 * Changing it will corrupt the matrix.
94 * All others have no bounds checking.
95 * m(r,c) -- "matrix" -- known to be within the allocated band
96 * r,c) -- "upper" -- known to be in the upper triangle. (c>=r)
97 * l(r,c) -- "lower" -- known to be in the lower triangle. (r>=c)
98 * d(r,c) -- "diagonal" -- known to be on the diagonal. (r==c)
99 * Using s() will always work, but will be slower than the other methods.
100 * You should use the most restricted function that you know is correct.
101 * -------------------------------------------------
103 * The numbering starts at 1 (Fortran style).
104 * When using "s" access, it is ok to load row and column 0, then ignore it.
105 * This may simplify load functions, at the expense of run speed.
106 * "s" will let you change the value of zero,
107 * but you will find out about it later.
109 //testing=script 2016.09.14
112 /*--------------------------------------------------------------------------*/
113 #include "l_stlextra.h"
118 /*--------------------------------------------------------------------------*/
119 enum needed_t
{nNO
=0, nYES
, nFILL
};
120 /*--------------------------------------------------------------------------*/
125 friend class BSMATRIX
<double>;
126 friend class BSMATRIX
<std::complex<double> >;
128 mutable bool* _changed
; // flag: this node changed value
129 unsigned* _lownode
; // lowest node connecting to this one
130 T
* _space
; // ptr to actual memory space used
131 T
** _rowptr
; // ptrs to col 0 of every row
132 T
** _colptr
; // ptrs to row 0 of every col
133 T
** _diaptr
; // ptrs to diagonal
134 unsigned _nzcount
; // count of non-zero elements
135 unsigned _size
; // # of rows and columns
136 T _zero
; // always 0 but not const
137 T _trash
; // depository for row and col 0, write only
138 T _min_pivot
; // minimum pivot value
139 unsigned _bandwidth
; // (0=diagonal)
140 std::vector
<std::set
<unsigned> > _adj
;
141 std::vector
<std::set
<unsigned> > _adj_ordered
;
146 BSMATRIX(const BSMATRIX
<T
>&);
148 explicit BSMATRIX(REAL
, const BSMATRIX
<std::complex<double> >&);
149 explicit BSMATRIX(IMAG
, const BSMATRIX
<std::complex<double> >&);
150 explicit BSMATRIX(SUM
, const BSMATRIX
<std::complex<double> >&);
152 void init(unsigned s
=0);
153 T
& subtract_dot_product(uint_t r
, uint_t c
, uint_t d
);
154 T
& subtract_dot_product(uint_t r
, uint_t c
, uint_t d
, const T
& in
);
155 unsigned lownode(unsigned i
)const {return _lownode
[i
];}
156 bool is_changed(unsigned n
)const {return _changed
[n
];}
157 void set_changed(uint_t n
, bool x
= true)const {_changed
[n
] = x
;}
159 explicit BSMATRIX(unsigned ss
=0);
160 ~BSMATRIX() {uninit();}
161 void reinit(unsigned ss
=0) {uninit(); init(ss
);}
162 //void clone(const BSMATRIX<T>&);
163 BSMATRIX
<T
>* copy()const // also copy contents
164 { return new BSMATRIX(*this); }
165 BSMATRIX
<double> real()const
166 { return( BSMATRIX
<double>(BSMATRIX
< double >::_REAL
, *this) ) ; }
167 BSMATRIX
<double> imag()const
168 { return( BSMATRIX
<double>(BSMATRIX
< double >::_IMAG
, *this) ) ; }
169 BSMATRIX
<double> sum()const
170 { return( BSMATRIX
<double>(BSMATRIX
< double >::_SUM
, *this) ) ; }
171 T
* row(T
*, unsigned);
172 T
* col(T
*, unsigned);
173 void iwant(unsigned, unsigned);
174 void iwant(unsigned*);
176 void i_do_want(unsigned, unsigned);
178 void rcm(); // used by allocate.
181 void allocate(unsigned*nm
=NULL
);
182 void reallocate() {unallocate(); allocate();}
183 void set_min_pivot(double x
) {_min_pivot
= x
;}
186 unsigned size()const {return _size
;}
188 inline T
* rmul(T
* b
, const T
* x
)const; // returns A*x
189 T
d(unsigned r
, unsigned )const;
190 T
s(unsigned r
, unsigned c
)const;
191 needed_t
n(unsigned row
, unsigned col
)const;
193 T
u(unsigned r
, unsigned c
)const;
194 T
l(unsigned r
, unsigned c
)const;
195 T
& d(unsigned r
, unsigned c
);
196 T
& u(unsigned r
, unsigned c
);
197 T
& l(unsigned r
, unsigned c
);
198 T
& m(unsigned r
, unsigned c
);
199 T
& s(unsigned r
, unsigned c
);
201 template <class S
,class X
>
202 friend S
& operator<< ( S
&o
, const BSMATRIX
<X
>& m
);
204 BSMATRIX
& operator*=( const T
& s
);
205 BSMATRIX
& operator+=( const BSMATRIX
& s
);
206 BSMATRIX
& operator=( const BSMATRIX
& s
);
207 // BSMATRIX& operator-( BSMATRIX& s);
208 // template <class X>
209 // friend OMSTREAM& operator<< ( OMSTREAM &o, const BSMATRIX<X>& m);
210 void load_diagonal_point(uint_t i
, T value
);
211 void load_point(uint_t i
, uint_t j
, T value
);
212 void load_couple(uint_t i
, uint_t j
, T value
);
213 void load_symmetric(uint_t i
, uint_t j
, T value
);
214 void load_asymmetric(uint_t r1
, uint_t r2
, uint_t c1
, uint_t c2
, T value
);
216 void lu_decomp(const BSMATRIX
<T
>&, bool do_partial
=false);
218 void fbsub(T
* v
) const;
219 void fbsub(std::complex<T
>* v
) const;
220 void fbsub(T
* x
, const T
* b
, T
* c
) const;
221 T
* fbsub(T
* x
, const T
* b
) const { fbsub(x
,b
,x
); return x
; }
222 void fbsubt(T
* v
) const;
224 void sink_forward(unsigned* nm
);
225 void sink_reverse(unsigned* nm
);
226 public: //eigenvalue stuff
227 void augment(T
*, T
*row
=0);
230 /*--------------------------------------------------------------------------*/
231 // private implementations
232 /*--------------------------------------------------------------------------*/
234 void BSMATRIX
<T
>::uninit()
242 /*--------------------------------------------------------------------------*/
244 void BSMATRIX
<T
>::init(unsigned ss
)
253 _min_pivot
= _trash
= 0.;
256 _lownode
= new unsigned[size()+1];
258 for (unsigned ii
= 0; ii
<= size(); ++ii
) {
261 _changed
= new bool[size()+1];
263 for (unsigned ii
= 0; ii
<= size(); ++ii
) {
264 set_changed(ii
, false);
268 _adj
.resize(size()+1);
270 /*--------------------------------------------------------------------------*/
272 T
& BSMATRIX
<T
>::subtract_dot_product(uint_t rr
, uint_t cc
, uint_t dd
)
275 uint_t kk
= std::max(_lownode
[rr
], _lownode
[cc
]);
277 unsigned len
= unsigned(dd
- kk
);
280 T
* row_
= &(l(rr
,kk
));
281 T
* col_
= &(u(kk
,cc
));
282 /* for (ii = kk; ii < dd; ++ii) */
283 for (unsigned ii
= 0; ii
< len
; ++ii
) {
284 dot
-= *(row_
-ii
) * col_
[ii
];
290 /*--------------------------------------------------------------------------*/
292 T
& BSMATRIX
<T
>::subtract_dot_product(uint_t rr
, uint_t cc
, uint_t dd
, const T
& in
)
295 unsigned kk
= std::max(_lownode
[rr
], _lownode
[cc
]);
296 int len
= int(dd
) - int(kk
);
300 T
* row_
= &(l(rr
,kk
));
301 T
* col_
= &(u(kk
,cc
));
302 /* for (ii = kk; ii < dd; ++ii) */
303 for (int ii
= 0; ii
< len
; ++ii
) {
304 dot
-= *(row_
-ii
) * col_
[ii
];
310 /*--------------------------------------------------------------------------*/
311 // public implementations
312 /*--------------------------------------------------------------------------*/
314 BSMATRIX
<T
>::BSMATRIX(unsigned ss
)
330 /*--------------------------------------------------------------------------*/
332 /* clone: copy to self the structure of another BSMATRIX
333 * this does not copy the values stored in the matrix
336 void BSMATRIX
<T
>::clone(const BSMATRIX
<T
> & aa
)
339 for (int ii
= 0; ii
<= size(); ++ii
) {untested();
340 _lownode
[ii
] = aa
.lownode(ii
);
344 /*--------------------------------------------------------------------------*/
345 /* iwant: indicate that "iwant" to allocate this spot in the matrix
348 void BSMATRIX
<T
>::iwant(unsigned node1
, unsigned node2
)
350 trace2("BSMATRIX::iwant", node1
, node2
);
352 assert(node1
<= size());
353 assert(node2
<= size());
355 // _adj.resize( std::max(std::max(node1, node2), unsigned(_adj.size())));
356 assert(node1
< _adj
.size());
357 assert(node2
< _adj
.size());
358 _adj
[node1
].insert(node2
);
359 _adj
[node2
].insert(node1
);
362 /*--------------------------------------*/
364 void BSMATRIX
<T
>::iwant(unsigned* nm
)
366 _adj_ordered
.clear();
367 _adj_ordered
.resize(_adj
.size());
368 for( unsigned j
=0; j
<size(); ++j
){
369 for(std::set
<unsigned>::const_iterator ii
=_adj
[j
].begin();
370 ii
!= _adj
[j
].end(); ++ii
)
372 i_do_want(nm
[j
],nm
[*ii
]);
373 _adj_ordered
[nm
[j
]].insert(nm
[*ii
]);
374 _adj_ordered
[nm
[*ii
]].insert(nm
[j
]);
378 /*--------------------------------------*/
379 // i really want the nodes (former iwant)
381 void BSMATRIX
<T
>::i_do_want(unsigned node1
, unsigned node2
)
383 if (node1
<= 0 || node2
<= 0) {
384 // node 0 is ground, and doesn't count as a connection
385 // negative is invalid, not used but still may be in a node list
386 }else if (node1
< _lownode
[node2
]) {
387 _lownode
[node2
]=node1
;
388 }else if (node2
< _lownode
[node1
]) {
389 _lownode
[node1
]=node2
;
393 /*--------------------------------------------------------------------------*/
395 void BSMATRIX
<T
>::unallocate()
397 assert (_zero
== 0.);
403 _rowptr
= _colptr
= _diaptr
= NULL
;
406 /*--------------------------------------------------------------------------*/
407 /* allocate: really get the space to work
408 * hmm maybe pass nm here?
411 void BSMATRIX
<T
>::allocate(unsigned* nm
)
421 for (unsigned ii
= 0; ii
<= size(); ++ii
) {
422 assert (ii
>= _lownode
[ii
]);
423 _nzcount
+= 2 * unsigned(ii
- _lownode
[ii
]) + 1;
426 _colptr
= new T
*[size()+1];
427 _rowptr
= new T
*[size()+1];
428 _diaptr
= new T
*[size()+1];
429 trace1("BSMATRIX::allocate", _nzcount
);
430 _space
= new T
[_nzcount
];
440 for (unsigned ii
= 0; ii
<= size(); ++ii
) {
441 _colptr
[ii
] = point
- (int)_lownode
[ii
];
442 _rowptr
[ii
] = _colptr
[ii
] + 2*ii
;
443 _diaptr
[ii
] = _colptr
[ii
] + ii
;
444 point
+= 2 * ((int)ii
- (int)_lownode
[ii
]) + 1;
448 /*--------------------------------------------------------------------------*/
449 /* zero: wipe the whole array
452 void BSMATRIX
<T
>::zero()
457 std::fill_n(_space
, _nzcount
, 0.);
459 /*--------------------------------------------------------------------------*/
460 /* dezero: make sure(?) the diagonal is non-zero
463 void BSMATRIX
<T
>::dezero(T
& offset
)
465 for (unsigned ii
= 1; ii
<= size(); ++ii
) {
469 /*--------------------------------------------------------------------------*/
471 double BSMATRIX
<T
>::density()
476 for (unsigned ii
= 0; ii
<= size(); ++ii
) {
477 _nzcount
+= 2 * (ii
- _lownode
[ii
]) + 1;
479 return static_cast<double>(_nzcount
-1)/(static_cast<double>(size())*size());
484 /*--------------------------------------------------------------------------*/
485 /* d: fast matrix entry access
486 * It is known that the entry is valid and on the diagonal
489 T BSMATRIX
<T
>::d(unsigned r
, unsigned c
) const
497 return *(_diaptr
[r
]);
499 /*--------------------------------------------------------------------------*/
500 /* d: as above, but lvalue */
502 T
& BSMATRIX
<T
>::d(unsigned r
, unsigned c
)
506 assert(r
== c
); USE(c
);
510 return *(_diaptr
[r
]);
512 /*--------------------------------------------------------------------------*/
513 /* u: fast matrix entry access
514 * It is known that the entry is valid and in the upper triangle (or diagonal)
517 T BSMATRIX
<T
>::u(unsigned r
, unsigned c
) const
524 assert(1 <= _lownode
[c
]);
525 assert(_lownode
[c
] <= r
);
527 return _colptr
[c
][r
];
529 /*--------------------------------------------------------------------------*/
530 /* u: as above, but lvalue */
532 T
& BSMATRIX
<T
>::u(unsigned r
, unsigned c
)
538 //assert(c <= _size);
539 assert(1 <= _lownode
[c
]);
540 assert(_lownode
[c
] <= r
);
542 return _colptr
[c
][r
];
544 /*--------------------------------------------------------------------------*/
545 /* l: fast matrix entry access
546 * It is known that the entry is valid and in the lower triangle not diagonal
549 T BSMATRIX
<T
>::l(unsigned r
, unsigned c
) const
556 assert(1 <= _lownode
[r
]);
557 assert(_lownode
[r
] <= c
);
559 return *(_rowptr
[r
]-c
);
561 /*--------------------------------------------------------------------------*/
562 /* l: as above, but lvalue */
564 T
& BSMATRIX
<T
>::l(unsigned r
, unsigned c
)
571 assert(1 <= _lownode
[r
]);
572 assert(_lownode
[r
] <= c
);
574 return *(_rowptr
[r
]-c
);
576 /*--------------------------------------------------------------------------*/
577 /* m: semi-fast matrix entry access
578 * It is known that the entry refers to a valid location
579 * but it is not known whether lower, upper, or diagonal
582 T
& BSMATRIX
<T
>::m(unsigned r
, unsigned c
)
590 /*--------------------------------------------------------------------------*/
591 /* s: general matrix entry access (read-only)
592 * It is known that the location is strictly in bounds,
593 * but it is not known whether the location actually exists.
594 * If access is attempted to a non-allocated location,
595 * it returns a reference to a shared zero variable.
596 * Writing to this zero is not prohibited,
597 * but will corrupt the matrix in a known and testable way.
598 * If access is attempted to row 0 or column 0,
599 * it returns a reference to a shared trash variable.
600 * Writing to trash is allowed and encouraged,
601 * but reading it gives a number not useful for anything.
604 T BSMATRIX
<T
>::s(unsigned row
, unsigned col
)const
608 assert(col
<= size());
610 assert(row
<= size());
613 if (col
== row
) {itested();
615 }else if (col
> row
) {itested(); /* above the diagonal */
616 if (row
== 0) {untested();
618 }else if (row
< _lownode
[col
]) {
623 }else{itested(); /* below the diagonal */
627 }else if (col
< _lownode
[row
]) {
635 /*--------------------------------------------------------------------------*/
636 // the entry is allocated (non-zero)
638 needed_t BSMATRIX
<T
>::n(unsigned row
, unsigned col
)const
642 assert(col
<= size());
644 assert(row
<= size());
647 if (_adj_ordered
[row
].find(col
) != _adj_ordered
[row
].end()){
653 }else if (col
> row
) { /* above the diagonal */
656 }else if (row
< _lownode
[col
]) {
661 }else{ /* below the diagonal */
665 }else if (col
< _lownode
[row
]) {
673 /*--------------------------------------------------------------------------*/
676 T
& BSMATRIX
<T
>::s(unsigned row
, unsigned col
)
680 assert(col
<= size());
682 assert(row
<= size());
687 }else if (col
> row
) { /* above the diagonal */
690 }else if (row
< _lownode
[col
]) {
695 }else{ /* below the diagonal */
699 }else if (col
< _lownode
[row
]) {
707 /*--------------------------------------------------------------------------*/
709 void BSMATRIX
<T
>::load_point(unsigned i
, unsigned j
, T value
)
711 if (i
> 0 && j
> 0) {itested();
718 /*--------------------------------------------------------------------------*/
719 // load_point(i, i, value);
721 void BSMATRIX
<T
>::load_diagonal_point(uint_t i
, T value
)
729 /*--------------------------------------------------------------------------*/
730 // load_point(i, j, -value);
731 // load_point(j, i, -value);
733 void BSMATRIX
<T
>::load_couple(uint_t i
, uint_t j
, T value
)
746 /*--------------------------------------------------------------------------*/
747 // load_point(i, i, value); or load_diagonal_point(i, value);
748 // load_point(j, j, value); or load_diagonal_point(j, value);
749 // load_point(i, j, -value);
750 // load_point(j, i, -value);
752 void BSMATRIX
<T
>::load_symmetric(uint_t i
, uint_t j
, T value
)
770 /*--------------------------------------------------------------------------*/
771 // load_point(r1, c1, value);
772 // load_point(r2, c2, value);
773 // load_point(r1, c2, -value);
774 // load_point(r2, c1, -value);
776 void BSMATRIX
<T
>::load_asymmetric(uint_t r1
,uint_t r2
,uint_t c1
,uint_t c2
,T value
)
805 /*--------------------------------------------------------------------------*/
807 void BSMATRIX
<T
>::lu_decomp(const BSMATRIX
<T
>& aa
, bool do_partial
)
809 unsigned prop
= 0; /* change propagation indicator */
812 assert(aa
.size() == size());
813 for (unsigned mm
= 1; mm
<= size(); ++mm
) {
814 assert(aa
.lownode(mm
) == _lownode
[mm
]);
815 unsigned bn
= _lownode
[mm
];
816 if (!do_partial
|| aa
.is_changed(mm
) || bn
<= prop
) {
817 aa
.set_changed(mm
, false);
821 u(bn
,mm
) = aa
.u(bn
,mm
) / d(bn
,bn
);
822 for (unsigned ii
= bn
+1; ii
<mm
; ii
++) {
823 /* u(ii,mm) = (aa.u(ii,mm) - dot(ii,mm,ii)) / d(ii,ii); */
824 subtract_dot_product(ii
,mm
,ii
,aa
.u(ii
,mm
)) /= d(ii
,ii
);
826 l(mm
,bn
) = aa
.l(mm
,bn
);
827 for (unsigned jj
= bn
+1; jj
<mm
; jj
++) {
828 /* l(mm,jj) = aa.l(mm,jj) - dot(mm,jj,jj); */
829 subtract_dot_product(mm
,jj
,jj
,aa
.l(mm
,jj
));
832 /* d(mm,mm) = aa.d(mm,mm) - dot(mm,mm,mm); then test */
833 if (subtract_dot_product(mm
,mm
,mm
,aa
.d(mm
,mm
)) == 0.) {
834 error(bWARNING
, "open circuit: internal node %u\n", mm
);
835 d(mm
,mm
) = _min_pivot
;
839 }else{ /* bn == mm */
840 d(mm
,mm
) = aa
.d(mm
,mm
);
841 if (d(mm
,mm
)==0.) {untested();
842 d(mm
,mm
) = _min_pivot
;
850 /*--------------------------------------------------------------------------*/
852 void BSMATRIX
<T
>::lu_decomp()
855 for (unsigned mm
= 1; mm
<= size(); ++mm
) {
856 unsigned bn
= _lownode
[mm
];
858 u(bn
,mm
) /= d(bn
,bn
);
859 for (unsigned ii
=bn
+1; ii
<mm
; ii
++) {
860 /* (m(ii,mm) -= dot(ii,mm,ii)) /= d(ii,ii); */
861 subtract_dot_product(ii
,mm
,ii
) /= d(ii
,ii
);
863 for (unsigned jj
= bn
+1; jj
<mm
; jj
++) {
864 /* m(mm,jj) -= dot(mm,jj,jj); */
865 subtract_dot_product(mm
,jj
,jj
);
868 /* m(mm,mm) -= dot(mm,mm,mm); then test */
869 if (subtract_dot_product(mm
,mm
,mm
) == 0.) {
870 error(bWARNING
, "open circuit: internal node %u\n", mm
);
871 d(mm
,mm
) = _min_pivot
;
875 }else{ /* bn == mm */
877 d(mm
,mm
) = _min_pivot
;
883 /*--------------------------------------------------------------------------*/
884 /* fbsub: forward and back sub, shared storage
885 * v = right side vector, changed in place to solution vector
888 void BSMATRIX
<T
>::fbsub(T
* v
) const
893 for (unsigned ii
= 1; ii
<= size(); ++ii
) { /* forward substitution */
894 for (unsigned jj
= _lownode
[ii
]; jj
< ii
; ++jj
) {
895 v
[ii
] -= l(ii
,jj
) * v
[jj
];
900 for (unsigned jj
= size(); jj
> 1; --jj
) { /* back substitution */
901 for (unsigned ii
= _lownode
[jj
]; ii
< jj
; ++ii
) {
902 v
[ii
] -= u(ii
,jj
) * v
[jj
];
906 /*--------------------------------------------------------------------------*/
907 /* fbsub: forward and back sub, separate storage
908 * x = solution vector
909 * b = right side vector
910 * c = intermediate vector after fwd sub
913 void BSMATRIX
<T
>::fbsub(T
* x
, const T
* b
, T
* c
) const
922 for ( ; ii
<= size(); ++ii
) {
930 unsigned first_nz
= ii
;
931 for ( ; ii
<= size(); ++ii
) { /* forward substitution */
932 unsigned low_node
= std::max(_lownode
[ii
], first_nz
);
934 for (unsigned jj
= low_node
; jj
< ii
; ++jj
) {
935 c
[ii
] -= l(ii
,jj
) * c
[jj
];
941 notstd::copy_n(c
, size()+1, x
);
943 for (unsigned jj
= size(); jj
> 1; --jj
) { /* back substitution */
944 for (unsigned ii
= _lownode
[jj
]; ii
< jj
; ++ii
) {
945 x
[ii
] -= u(ii
,jj
) * x
[jj
];
949 // index starts at 1, but node 0 is ground
950 // x[0]==0 eliminates a lot of "if" statements
952 /*--------------------------------------------------------------------------*/
954 BSMATRIX
<T
>::BSMATRIX(const BSMATRIX
<T
>& m
) :
955 _changed(new bool[m
.size()+1]),
956 _lownode(new unsigned[m
.size()+1]),
957 _space(new T
[m
._nzcount
]),
958 _rowptr(new T
*[m
._size
+1]),
959 _colptr(new T
*[m
._size
+1]),
960 _diaptr(new T
*[m
._size
+1]),
961 _nzcount(m
._nzcount
),
965 _min_pivot(m
._min_pivot
)
967 memcpy(_changed
,m
._changed
, (_size
+1) * sizeof(bool) );
968 memcpy(_lownode
,m
._lownode
, (_size
+1) * sizeof(unsigned) );
969 memcpy(_space
,m
._space
, (_nzcount
) * sizeof(T
));
971 for(unsigned i
=0; i
<=_size
; i
++){
972 _rowptr
[i
]= _space
- intptr_t(m
._space
- m
._rowptr
[i
]);
973 _colptr
[i
]= _space
- intptr_t(m
._space
- m
._colptr
[i
]);
974 _diaptr
[i
]= _space
- intptr_t(m
._space
- m
._diaptr
[i
]);
979 /*--------------------------------------------------------------------------*/
980 // template <class X, class Y>
981 //Y& operator<< ( Y &o, const BSMATRIX<X>& m);
984 //OMSTREAM& operator<< ( OMSTREAM &o, const BSMATRIX<X>& m);
986 void BSMATRIX
<double>::sink_forward(unsigned* nm
);
988 void BSMATRIX
<double>::sink_reverse(unsigned* nm
);
989 /*--------------------------------------------------------------------------*/
990 /* fbsubt: forward and back substitution with implicitly transposed matrix Ut Lt x = v
991 * v = right side vector, changed in place to solution vector
993 * this method s used to solve system A_t X = B (_t - transposed)
994 * which corresponds to adjoint system
995 * (LU)_t then transforms to U_t L_t
996 * added: Gennadiy Serdyuk <gserdyuk@gserdyuk.com>
999 void BSMATRIX
<T
>::fbsubt(T
* v
) const
1004 // forward substitution
1005 for (unsigned ii
= 1; ii
<= size(); ++ii
) {untested();
1006 for (unsigned jj
= _lownode
[ii
]; jj
< ii
; ++jj
) {untested();
1007 v
[ii
] -= u(jj
,ii
) * v
[jj
];
1011 // back substitution
1012 for (unsigned jj
= size(); jj
> 1; --jj
) {untested();
1014 for (unsigned ii
= _lownode
[jj
]; ii
< jj
; ++ii
) {untested();
1015 v
[ii
] -= l(jj
,ii
) * v
[jj
];
1020 /*--------------------------------------------------------------------------*/
1021 // apply real matrix to complex vector.
1023 void BSMATRIX
<T
>::fbsub(std::complex<T
>* v
)const
1026 for(unsigned i
=0; i
<=size(); ++i
){
1027 part
[i
] = v
[i
].real();
1030 for(unsigned i
=0; i
<=size(); ++i
){
1032 part
[i
] = v
[i
].imag();
1035 for(unsigned i
=0; i
<=size(); ++i
){
1039 /*--------------------------------------------------------------------------*/
1042 // vim:ts=8:sw=2:noet: