00001 #include <map> 00002 #include <vector> 00003 #include <float.h> 00004 #include <math.h> 00005 00006 template <class t> inline void addEq(t &a, const t &b, bool bNeg) 00007 { if(bNeg) a -= b; else a += b; } 00008 00009 template <class t> inline void CalcEpsilon(t& maxCoef, t &epsilon, const t &d); 00010 template <class t> inline t abs(const t& x) { return(x < 0 ? -x : x); } 00011 template <class t> inline t max(const t& a, const t& b) { return(a > b ? a : b); } 00012 template <class t> inline t min(const t& a, const t& b) { return(a < b ? a : b); } 00013 00014 typedef pair<size_t, size_t> rng; 00015 00016 template <class t> class smIdent; 00017 00018 template<class ta, class tb> ta& svAssign(ta& a, const tb &b) 00019 { 00020 a.range = b.range; 00021 ta::iterator ia = a.lower_bound(0); 00022 ta::iterator iaEnd = a.lower_bound((size_t)-1); 00023 tb::const_iterator ib = b.lower_bound(b.range.first); 00024 tb::const_iterator ibEnd = b.lower_bound(b.range.second + 1); 00025 while(ia != iaEnd || ib != ibEnd) 00026 { 00027 if(ia == iaEnd) 00028 { 00029 ta::iterator iaNew = a.insert(ia, b.Index(ib), b.Coef(ib)); 00030 if(iaNew != ia) 00031 iaEnd = ia = ++iaNew; 00032 ib++; 00033 } 00034 else if(ib == ibEnd) 00035 ia = a.erase(ia); 00036 else if(a.Index(ia) < b.Index(ib)) 00037 ia = a.erase(ia); 00038 else if(a.Index(ia) > b.Index(ib)) 00039 { 00040 ta::iterator iaNew = a.insert(ia, b.Index(ib), b.Coef(ib)); 00041 if(iaNew != ia) 00042 ia = ++iaNew; 00043 ib++; 00044 } 00045 else 00046 a.Coef(ia++) = b.Coef(ib++); 00047 } 00048 return(a); 00049 } 00050 00051 template<class ta, class tb> ta& svAddEq(ta& a, const tb& b, bool bNegate) 00052 { 00053 ta::iterator ia = a.lower_bound(min(b.range.first, a.range.second + 1)); 00054 ta::iterator iaEnd = a.lower_bound(a.range.second + 1); 00055 tb::const_iterator ib = b.lower_bound(b.range.first); 00056 tb::const_iterator ibEnd = b.lower_bound(b.range.second + 1); 00057 00058 while(ib != ibEnd) 00059 { 00060 if(ia == iaEnd) 00061 { 00062 ta::iterator iaNew = a.insert(ia, b.Index(ib), bNegate ? -b.Coef(ib) : b.Coef(ib)); 00063 if(iaNew != ia) 00064 iaEnd = ia = ++iaNew; 00065 ib++; 00066 } 00067 else if(a.Index(ia) > b.Index(ib)) 00068 { 00069 ta::iterator iaNew = a.insert(ia, b.Index(ib), bNegate ? -b.Coef(ib) : b.Coef(ib)); 00070 if(iaNew != ia) 00071 ia = ++iaNew; 00072 ib++; 00073 } 00074 else if(a.Index(ia) < b.Index(ib)) 00075 ia++; 00076 else 00077 { 00078 addEq(a.Coef(ia), b.Coef(ib++), bNegate); 00079 a.CalcEpsilon(a.Coef(ia)); 00080 ia++; 00081 } 00082 } 00083 00084 a.range.first = min(a.range.first, b.range.first); 00085 a.range.second = max(a.range.second, b.range.second); 00086 00087 return(a); 00088 } 00089 00090 template <class t> class smatrix 00091 { 00092 public: 00093 class vector_map : public vector< map<size_t, size_t> *> 00094 { 00095 public: 00096 vector_map& operator=(const vector_map &a) 00097 { 00098 resize(a.size()); 00099 const_iterator ap = a.begin(); 00100 for(iterator p = begin(); p != end(); p++, ap++) 00101 **p = **ap; 00102 return(*this); 00103 } 00104 ~vector_map() { for(iterator p = begin(); p != end(); p++) delete(*p); } 00105 void resize(size_t NewSize) 00106 { 00107 size_t OldSize = size(); 00108 if(NewSize < OldSize) 00109 { 00110 for(iterator p = begin(); p != &(*this)[OldSize]; p++) 00111 delete(*p); 00112 vector< map<size_t, size_t> *>::resize(NewSize); 00113 } 00114 else if(NewSize > OldSize) 00115 { 00116 vector< map<size_t, size_t> *>::resize(NewSize, NULL); 00117 for(iterator p = &(*this)[OldSize]; p != end(); p++) 00118 *p = new map<size_t, size_t>; 00119 } 00120 } 00121 }; 00122 00123 vector<t> e; 00124 t epsilon, maxCoef; 00125 vector_map *iMap, *jMap; 00126 size_t iDim, jDim, NZ, FirstBlank, FreeSlots; 00127 bool bOddNumPivots; 00128 static size_t PrintWidth, PrintPrecision; 00129 00130 typedef map<size_t, size_t>::iterator iterator; 00131 typedef map<size_t, size_t>::const_iterator const_iterator; 00132 typedef pair<size_t, size_t> mapping; 00133 00134 virtual ~smatrix() 00135 { 00136 delete(iMap); 00137 delete(jMap); 00138 } 00139 smatrix() : iMap(NULL), jMap(NULL), maxCoef(0), 00140 epsilon(0) { initialize(0, 0, 0); } 00141 smatrix(const smatrix<t>& a) : iMap(NULL), jMap(NULL) 00142 { 00143 *this = a; 00144 } 00145 smatrix(const t* d, size_t iDim, size_t jDim) : iMap(NULL), jMap(NULL) 00146 { 00147 initialize(iDim, jDim, iDim * jDim); 00148 for(size_t r = 1; r <= iDim; r++) 00149 { 00150 for(size_t c = 1; c <= jDim; c++, d++) 00151 { 00152 if(*d != 0) 00153 insert(r, c, *d); 00154 } 00155 } 00156 } 00157 smatrix(size_t iDim, size_t jDim, size_t MaxNZ) : iMap(NULL), jMap(NULL) 00158 { 00159 initialize(iDim, jDim, MaxNZ); 00160 } 00161 smatrix<t>& operator=(const smatrix<t>& a) 00162 { 00163 e = a.e; 00164 epsilon = a.epsilon; 00165 maxCoef = a.maxCoef; 00166 00167 delete(iMap); 00168 iMap = new vector_map; 00169 *iMap = *a.iMap; 00170 00171 delete(jMap); 00172 jMap = new vector_map; 00173 *jMap = *a.jMap; 00174 00175 NZ = a.NZ; 00176 iDim = a.iDim; 00177 jDim = a.jDim; 00178 FirstBlank = a.FirstBlank; 00179 bOddNumPivots = a.bOddNumPivots; 00180 00181 return(*this); 00182 } 00183 void initialize(size_t MaxNZ) 00184 { 00185 delete(iMap); 00186 iMap = new vector_map; 00187 delete(jMap); 00188 jMap = new vector_map; 00189 e.reserve(MaxNZ); 00190 iMap->resize(iDim + 1); 00191 jMap->resize(jDim + 1); 00192 FirstBlank = (size_t)-1; 00193 NZ = 0; 00194 FreeSlots = 0; 00195 bOddNumPivots = false; 00196 epsilon = 0; 00197 maxCoef = 0; 00198 } 00199 void initialize(size_t iDim, size_t jDim, size_t MaxNZ) 00200 { 00201 this->iDim = iDim; 00202 this->jDim = jDim; 00203 initialize(MaxNZ); 00204 } 00205 void erase(size_t pos) 00206 { 00207 e[pos] = FirstBlank; 00208 FirstBlank = pos; 00209 NZ--; 00210 FreeSlots++; 00211 } 00212 size_t SlackSpace() const 00213 { 00214 return(FreeSlots + (e.size() - NZ)); 00215 } 00216 double Sparsity() const 00217 { 00218 return((double)NZ / (iDim * jDim)); 00219 } 00220 void reserve(size_t space) 00221 { 00222 size_t slack = SlackSpace(); 00223 if(slack < space) 00224 e.reserve(space - FreeSlots); 00225 } 00226 bool insert(size_t i, size_t j, const t& d, iterator &iIter, iterator &jIter, bool bZeroInsert = false) 00227 { 00228 if(bZeroInsert == false && abs(d) <= epsilon) 00229 return(false); 00230 00231 size_t pos; 00232 if(FirstBlank != (size_t)-1) 00233 { 00234 pos = FirstBlank; 00235 FirstBlank = (size_t)e[pos]; 00236 FreeSlots--; 00237 } 00238 else 00239 { 00240 if(e.capacity() == e.size()) 00241 e.reserve(e.size() + (e.size() / 10)); 00242 pos = e.size(); 00243 e.insert(e.end()); 00244 } 00245 NZ++; 00246 00247 e[pos] = d; 00248 CalcEpsilon(maxCoef, epsilon, d); 00249 00250 if(i > iDim) 00251 { 00252 iDim = i; 00253 iMap->resize(iDim + 1); 00254 } 00255 jIter = (*iMap)[i]->insert(mapping(j, pos)).first; 00256 00257 if(j > jDim) 00258 { 00259 jDim = j; 00260 jMap->resize(jDim + 1); 00261 } 00262 iIter = (*jMap)[j]->insert(mapping(i, pos)).first; 00263 00264 return(true); 00265 } 00266 iterator insert(size_t i, size_t j, const t& d) 00267 { 00268 iterator iIter, jIter; 00269 if(insert(i, j, d, iIter, jIter)) 00270 return(iIter); 00271 return(IterForRow(0, 0)); 00272 } 00273 iterator ZeroInsert(size_t i, size_t j) 00274 { 00275 iterator iIter, jIter; 00276 t d(0); 00277 insert(i, j, d, iIter, jIter, true); 00278 return(iIter); 00279 } 00280 smatrix<t>& Transpose() 00281 { 00282 swap(iMap, jMap); 00283 swap(iDim, jDim); 00284 return(*this); 00285 } 00286 template<class ta, class tb> static t svMultiply(const ta& a, const tb& b) 00287 { 00288 size_t first = max(a.range.first, b.range.first); 00289 size_t last = min(a.range.second, b.range.second); 00290 00291 ta::const_iterator ia = a.lower_bound(first); 00292 ta::const_iterator iaEnd = a.lower_bound(last + 1); 00293 00294 tb::const_iterator ib = b.lower_bound(first); 00295 tb::const_iterator ibEnd = b.lower_bound(last + 1); 00296 00297 t d(0); 00298 while(ia != iaEnd && ib != ibEnd) 00299 { 00300 if(a.Index(ia) < b.Index(ib)) 00301 ia++; 00302 else if(a.Index(ia) > b.Index(ib)) 00303 ib++; 00304 else 00305 { 00306 addEq(d, a.Coef(ia) * b.Coef(ib), false); 00307 ia++; 00308 ib++; 00309 } 00310 } 00311 return(d); 00312 } 00313 class svector : public map<size_t, t> 00314 { 00315 public: 00316 rng range; 00317 t epsilon, maxCoef; 00318 00319 svector(const t &ep) : epsilon(ep), maxCoef(0) { } 00320 t GetEpsilon() const { return(epsilon); } 00321 template<class tb> t operator*(const tb &b) 00322 { 00323 epsilon *= b; 00324 maxCoef *= b; 00325 return(svMultiply(*this, b)); 00326 } 00327 svector& operator=(const class const_svector_ref& a); 00328 t Coef(const_iterator p) const 00329 { 00330 return(p->second); 00331 } 00332 static size_t Index(iterator p) { return(p->first); } 00333 static size_t Index(const_iterator p) { return(p->first); } 00334 static t& Coef(iterator p) { return(p->second); } 00335 void CalcEpsilon(const t &d) 00336 { 00337 sm::CalcEpsilon(maxCoef, epsilon, d); 00338 } 00339 iterator insert(iterator p, size_t x, const t& d) 00340 { 00341 CalcEpsilon(d); 00342 return(map<size_t, t>::insert(p, pair<size_t, t>(x, d))); 00343 } 00344 t& operator()(size_t n) 00345 { 00346 return(operator[](n)->second); 00347 } 00348 t operator()(size_t n) const 00349 { 00350 const_iterator p = find(n); 00351 return(p == end() ? 0 : p->second); 00352 } 00353 }; 00354 class const_svector_ref 00355 { 00356 public: 00357 const smatrix<t> *cm; 00358 rng range; 00359 size_t n; 00360 bool bColVect; 00361 00362 typedef map<size_t, size_t>::const_iterator const_iterator; 00363 00364 const_svector_ref(const smatrix<t> *pm, const rng& i, size_t j) : 00365 cm(pm), range(i), n(j), bColVect(true) { } 00366 const_svector_ref(const smatrix<t> *pm, size_t i, const rng& j) : 00367 cm(pm), range(j), n(i), bColVect(false) { } 00368 const map<size_t, size_t> *GetMap() const 00369 { 00370 if(bColVect && n < cm->jMap->size()) 00371 return((*cm->jMap)[n]); 00372 if(!bColVect && n < cm->iMap->size()) 00373 return((*cm->iMap)[n]); 00374 return((*cm->iMap)[0]); 00375 } 00376 const_iterator lower_bound(size_t i) const 00377 { 00378 return(GetMap()->lower_bound(i)); 00379 } 00380 svector operator*(const t& b) 00381 { 00382 svector c(GetEpsilon() * b); 00383 c.range = range; 00384 const_iterator i = lower_bound(range.first); 00385 const_iterator iEnd = lower_bound(range.second + 1); 00386 for(; i != iEnd; i++) 00387 c.insert(c.end(), i->first, Coef(i) * b); 00388 return(c); 00389 } 00390 t GetEpsilon() const { return(cm->epsilon); } 00391 static size_t Index(const_iterator p) { return(p->first); } 00392 t Coef(const_iterator p) const { return(cm->e[p->second]); } 00393 t operator()(size_t n) const 00394 { 00395 const map<size_t, size_t> *Map = GetMap(); 00396 const_iterator p = Map->find(n); 00397 return(p == Map->end() ? 0 : cm->e[p->second]); 00398 } 00399 bool operator!=(const const_svector_ref& b) 00400 { 00401 if(range.first != b.range.first || range.second != b.range.second) return(true); 00402 const_iterator ia = lower_bound(range.first); 00403 const_iterator iaEnd = lower_bound(range.second + 1); 00404 const_iterator ib = b.lower_bound(b.range.first); 00405 const_iterator ibEnd = b.lower_bound(b.range.second + 1); 00406 for(; ia != iaEnd && ib != ibEnd; ia++, ib++) 00407 { 00408 if(Index(ia) != b.Index(ib)) return(true); 00409 if(Coef(ia) != b.Coef(ib)) return(true); 00410 } 00411 return(ia != iaEnd || ib != ibEnd); 00412 } 00413 template<class tb> t operator*(const tb &b) 00414 { 00415 return(smatrix<t>::svMultiply(*this, b)); 00416 } 00417 template<class tb> svector operator+(const tb &b) const 00418 { 00419 svector c(max(GetEpsilon(), b.GetEpsilon())); 00420 svAssign(c, *this); 00421 return(svAddEq(c, b, false)); 00422 } 00423 template<class tb> svector operator-(const tb &b) const 00424 { 00425 svector c(max(GetEpsilon(), b.GetEpsilon())); 00426 svAssign(c, *this); 00427 return(svAddEq(c, b, true)); 00428 } 00429 }; 00430 class svector_ref : public const_svector_ref 00431 { 00432 public: 00433 smatrix<t> *m; 00434 typedef map<size_t, size_t>::iterator iterator; 00435 00436 svector_ref(smatrix<t> *pm, const rng& i, size_t j) : 00437 m(pm), const_svector_ref(pm, i, j) { } 00438 svector_ref(smatrix<t> *pm, size_t i, const rng& j) : 00439 m(pm), const_svector_ref(pm, i, j) { } 00440 map<size_t, size_t> *GetMap() 00441 { 00442 if(bColVect && n < m->jMap->size()) 00443 return((*m->jMap)[n]); 00444 if(!bColVect && n < m->iMap->size()) 00445 return((*m->iMap)[n]); 00446 return((*m->iMap)[0]); 00447 } 00448 iterator lower_bound(size_t i) 00449 { 00450 return(GetMap()->lower_bound(i)); 00451 } 00452 static size_t Index(iterator p) { return(p->first); } 00453 t& Coef(iterator p) 00454 { 00455 return(m->e[p->second]); 00456 } 00457 svector_ref operator=(const const_svector_ref &b) 00458 { 00459 return(svAssign(*this, b)); 00460 } 00461 svector_ref& operator=(const svector &b) 00462 { 00463 return(svAssign(*this, b)); 00464 } 00465 iterator insert(iterator p, size_t x, const t& d) 00466 { 00467 iterator iIter, jIter; 00468 if(bColVect) 00469 { 00470 iIter = p; 00471 m->insert(x, n, d, iIter, iIter); 00472 return(iIter); 00473 } 00474 jIter = p; 00475 m->insert(n, x, d, iIter, jIter); 00476 return(jIter); 00477 } 00478 iterator erase(iterator p) 00479 { 00480 m->erase(p->second); 00481 if(bColVect) 00482 { 00483 (*m->iMap)[p->first]->erase(n); 00484 return((*m->jMap)[n]->erase(p)); 00485 } 00486 (*m->jMap)[p->first]->erase(n); 00487 return((*m->iMap)[n]->erase(p)); 00488 } 00489 t& operator()(size_t n) 00490 { 00491 const map<size_t, size_t> *Map = GetMap(); 00492 const_iterator p = Map->find(n); 00493 return(p == Map->end() ? insert(n, t(0)) : cm->e[p->second]); 00494 } 00495 void CalcEpsilon(const t &d) 00496 { 00497 sm::CalcEpsilon(m->maxCoef, m->epsilon, d); 00498 } 00499 svector_ref& operator+=(const const_svector_ref &b) 00500 { 00501 return(svAddEq(*this, b, false)); 00502 } 00503 svector_ref& operator-=(const const_svector_ref &b) 00504 { 00505 return(svAddEq(*this, b, true)); 00506 } 00507 svector_ref& operator+=(const svector &b) 00508 { 00509 return(svAddEq(*this, b, false)); 00510 } 00511 svector_ref& operator-=(const svector &b) 00512 { 00513 return(svAddEq(*this, b, true)); 00514 } 00515 svector_ref& operator*=(const t& d) 00516 { 00517 iterator i = lower_bound(range.first); 00518 iterator iEnd = lower_bound(range.second + 1); 00519 for(; i != iEnd; i++) 00520 Coef(i) *= d; 00521 return(*this); 00522 } 00523 }; 00524 t operator()(size_t i, size_t j) const 00525 { 00526 if(i > iDim || j > jDim) return(0); 00527 const map<size_t, size_t> *r = (*iMap)[i]; 00528 map<size_t, size_t>::const_iterator p = r->find(j); 00529 if(p == r->end()) 00530 return(0); 00531 return(e[p->second]); 00532 } 00533 class coefRef 00534 { 00535 public: 00536 smatrix<t> *m; 00537 size_t i, j; 00538 00539 coefRef(smatrix<t> *m, size_t i, size_t j) 00540 { 00541 this->m = m; 00542 this->i = i; 00543 this->j = j; 00544 } 00545 coefRef& operator=(const t &d) 00546 { 00547 if(abs(d) > m->epsilon) 00548 { 00549 if(i > m->iDim || j > m->jDim) 00550 m->insert(i, j, d); 00551 else 00552 { 00553 const map<size_t, size_t> *r = (*m->iMap)[i]; 00554 map<size_t, size_t>::const_iterator p = r->find(j); 00555 if(p == r->end()) 00556 m->insert(i, j, d); 00557 else 00558 { 00559 m->e[p->second] = d; 00560 CalcEpsilon(m->maxCoef, m->epsilon, d); 00561 } 00562 } 00563 } 00564 else if(i <= m->iDim && j <= m->jDim) 00565 m->erase(i, j); 00566 return(*this); 00567 } 00568 operator t() const 00569 { 00570 if(i > m->iDim || j > m->jDim) return(0); 00571 const map<size_t, size_t> *r = (*m->iMap)[i]; 00572 map<size_t, size_t>::const_iterator p = r->find(j); 00573 if(p == r->end()) 00574 return(0); 00575 return(m->e[p->second]); 00576 } 00577 }; 00578 coefRef operator()(size_t i, size_t j) 00579 { 00580 return(coefRef(this, i, j)); 00581 } 00582 void erase(size_t i, size_t j) 00583 { 00584 map<size_t, size_t> *r = (*iMap)[i]; 00585 map<size_t, size_t>::iterator p = r->find(j); 00586 if(p != r->end()) 00587 { 00588 erase(p->second); 00589 r->erase(p); 00590 (*jMap)[j]->erase(i); 00591 } 00592 } 00593 t Coef(size_t i, size_t j) const { return((*this)(i, j)); } 00594 coefRef Coef(size_t i, size_t j) { return((*this)(i, j)); } 00595 t Coef(const_iterator p) const { return(e[p->second]); } 00596 t& Coef(const_iterator p) { return(e[p->second]); } 00597 static size_t Index(const_iterator p) { return(p->first); } 00598 static size_t Index(iterator p) { return(p->first); } 00599 static size_t CoefPtr(const_iterator p) { return(p->second); } 00600 static size_t CoefPtr(iterator p) { return(p->second); } 00601 00602 svector_ref operator()(size_t i, const rng& range) 00603 { return(svector_ref(this, i, range)); } 00604 svector_ref operator()(const rng& range, size_t j) 00605 { return(svector_ref(this, range, j)); } 00606 const_svector_ref operator()(size_t i, const rng& range) const 00607 { return(const_svector_ref(this, i, range)); } 00608 const_svector_ref operator()(const rng& range, size_t j) const 00609 { return(const_svector_ref(this, range, j)); } 00610 00611 svector_ref row(size_t i) 00612 { return(svector_ref(this, i, rng(1, jDim))); } 00613 svector_ref row(size_t i, const rng& range) 00614 { return(svector_ref(this, i, range)); } 00615 svector_ref col(size_t j) 00616 { return(svector_ref(this, rng(1, iDim), j)); } 00617 svector_ref col(const rng& range, size_t j) 00618 { return(svector_ref(this, range, j)); } 00619 const_svector_ref row(size_t i) const 00620 { return(const_svector_ref(this, i, rng(1, jDim))); } 00621 const_svector_ref row(size_t i, const rng& range) const 00622 { return(const_svector_ref(this, i, range)); } 00623 const_svector_ref col(size_t j) const 00624 { return(const_svector_ref(this, rng(1, iDim), j)); } 00625 const_svector_ref col(const rng& range, size_t j) const 00626 { return(const_svector_ref(this, range, j)); } 00627 00628 iterator IterFor(size_t n, size_t Start, const vector_map *p) 00629 { 00630 map<size_t, size_t> *Map = (n > p->size() ? (*p)[0] : (*p)[n]); 00631 return(Start <= 1 ? Map->begin() : Map->lower_bound(Start)); 00632 } 00633 const_iterator IterFor(size_t n, size_t Start, const vector_map *p) const 00634 { 00635 const map<size_t, size_t> *Map = (n > p->size() ? (*p)[0] : (*p)[n]); 00636 return(Start <= 1 ? Map->begin() : Map->lower_bound(Start)); 00637 } 00638 iterator EndOf(size_t n, vector_map *p) 00639 { 00640 map<size_t, size_t> *Map = (n > p->size() ? (*p)[0] : (*p)[n]); 00641 return(Map->end()); 00642 } 00643 const_iterator EndOf(size_t n, const vector_map *p) const 00644 { 00645 const map<size_t, size_t> *Map = (n > p->size() ? (*p)[0] : (*p)[n]); 00646 return(Map->end()); 00647 } 00648 iterator IterForRow(size_t i, size_t jStart = 1) 00649 { return(IterFor(i, jStart, iMap)); } 00650 const_iterator IterForRow(size_t i, size_t jStart = 1) const 00651 { return(IterFor(i, jStart, iMap)); } 00652 const_iterator EndOfRow(size_t i) const 00653 { return(EndOf(i, iMap)); } 00654 iterator EndOfRow(size_t i) 00655 { return(EndOf(i, iMap)); } 00656 iterator IterForCol(size_t j, size_t iStart = 1) 00657 { return(IterFor(j, iStart, jMap)); } 00658 const_iterator IterForCol(size_t j, size_t iStart = 1) const 00659 { return(IterFor(j, iStart, jMap)); } 00660 const_iterator EndOfCol(size_t j) const 00661 { return(EndOf(j, jMap)); } 00662 iterator EndOfCol(size_t j) 00663 { return(EndOf(j, jMap)); } 00664 00665 smatrix<t> operator+(const smatrix<t> &b) const 00666 { 00667 smatrix<t> c; 00668 c.initialize(max(iDim, b.iDim), max(jDim, b.jDim), NZ + b.NZ); 00669 for(size_t i = 1; i <= iDim; i++) 00670 c.row(i) = row(i) + b.row(i); 00671 return(c); 00672 } 00673 smatrix<t> operator-(const smatrix<t> &b) const 00674 { 00675 smatrix<t> c; 00676 c.initialize(max(iDim, b.iDim), max(jDim, b.jDim), NZ + b.NZ); 00677 for(size_t i = 1; i <= iDim; i++) 00678 c.row(i) = row(i) - b.row(i); 00679 return(c); 00680 } 00681 smatrix<t> operator*(const smatrix<t>& b) const 00682 { 00683 smatrix<t> c; 00684 00685 c.iDim = iDim; 00686 c.jDim = b.jDim; 00687 size_t MaxNZ = max(NZ, b.NZ); 00688 if(c.iDim == 1 && c.jDim == 1) MaxNZ = 1; 00689 else if(c.iDim == 1 || c.jDim == 1) MaxNZ = max(c.iDim, c.jDim); 00690 c.initialize(MaxNZ); 00691 00692 for(size_t i = 1; i <= iDim; i++) 00693 { 00694 const_svector_ref r = row(i); 00695 for(size_t j = 1; j <= b.jDim; j++) 00696 { 00697 t d = svMultiply(r, b.col(j)); 00698 c.insert(i, j, d); 00699 } 00700 } 00701 return(c); 00702 } 00703 bool operator==(const smatrix<t> &b) const 00704 { 00705 if(iDim != b.iDim || jDim != b.jDim || NZ != b.NZ) return(false); 00706 for(size_t i = 1; i <= iDim; i++) 00707 { 00708 if(row(i) != b.row(i)) 00709 return(false); 00710 } 00711 return(true); 00712 } 00713 bool operator!=(const const smatrix<t>& b) 00714 { 00715 return(operator==(b) == false); 00716 } 00717 bool operator!() { return(NZ == 0); } 00718 void PivotMap(size_t a, size_t b, vector_map *Source, vector_map &Dest) 00719 { 00720 bOddNumPivots = (bOddNumPivots == false); 00721 if(a != b) 00722 { 00723 const_iterator ia = IterFor(a, 1, Source); 00724 const_iterator ib = IterFor(b, 1, Source); 00725 while(ia != EndOf(a, Source) || ib != EndOf(b, Source)) 00726 { 00727 if(ia == EndOf(a, Source)) 00728 { 00729 Dest[Index(ib)]->erase(b); 00730 Dest[Index(ib)]->insert(mapping(a, CoefPtr(ib))); 00731 ib++; 00732 } 00733 else if(ib == EndOf(b, Source)) 00734 { 00735 Dest[Index(ia)]->erase(a); 00736 Dest[Index(ia)]->insert(mapping(b, CoefPtr(ia))); 00737 ia++; 00738 } 00739 else if(Index(ia) > Index(ib)) 00740 { 00741 Dest[Index(ib)]->erase(b); 00742 Dest[Index(ib)]->insert(mapping(a, CoefPtr(ib))); 00743 ib++; 00744 } 00745 else if(Index(ia) < Index(ib)) 00746 { 00747 Dest[Index(ia)]->erase(a); 00748 Dest[Index(ia)]->insert(mapping(b, CoefPtr(ia))); 00749 ia++; 00750 } 00751 else 00752 { 00753 map<size_t, size_t> &p = *Dest[Index(ia)]; 00754 swap(p[a], p[b]); 00755 ia++; 00756 ib++; 00757 } 00758 } 00759 } 00760 swap((*Source)[a], (*Source)[b]); 00761 } 00762 bool Pivot(size_t k, size_t &MaxIdx, t &MaxCoef, vector_map *Source, vector_map &Dest) 00763 { 00764 iterator p = Dest[k]->lower_bound(k); 00765 if(p == Dest[k]->end()) 00766 return(false); 00767 MaxIdx = Index(p); 00768 MaxCoef = Coef(p); 00769 for(p++; p != Dest[k]->end(); p++) 00770 { 00771 if(abs(MaxCoef) < abs(Coef(p))) 00772 { 00773 MaxCoef = Coef(p); 00774 MaxIdx = Index(p); 00775 } 00776 } 00777 if(k != MaxIdx) 00778 PivotMap(k, MaxIdx, Source, Dest); 00779 00780 return(true); 00781 } 00782 void PivotRow(size_t k, size_t MaxIdx, smatrix<t> *pMatix = NULL) 00783 { 00784 PivotMap(k, MaxIdx, iMap, *jMap); 00785 if(pMatix != NULL && k != MaxIdx) 00786 pMatix->PivotMap(k, MaxIdx, pMatix->iMap, *pMatix->jMap); 00787 } 00788 bool PivotRow(size_t k, t& MaxCoef, smatrix<t> *pMatix = NULL) 00789 { 00790 size_t MaxIdx; 00791 if(Pivot(k, MaxIdx, MaxCoef, iMap, *jMap)) 00792 { 00793 if(pMatix != NULL && k != MaxIdx) 00794 pMatix->PivotMap(k, MaxIdx, pMatix->iMap, *pMatix->jMap); 00795 return(true); 00796 } 00797 return(false); 00798 } 00799 void PivotCol(size_t k, size_t MaxIdx, smatrix<t> *pMatix = NULL) 00800 { 00801 PivotMap(k, MaxIdx, jMap, *iMap); 00802 if(pMatix != NULL && k != MaxIdx) 00803 pMatix->PivotMap(k, MaxIdx, pMatix->jMap, *pMatix->iMap); 00804 } 00805 bool PivotCol(size_t k, t& MaxCoef, smatrix<t> *pMatix = NULL) 00806 { 00807 size_t MaxIdx; 00808 if(Pivot(k, MaxCoef, jMap, *iMap, L)) 00809 { 00810 if(pMatix != NULL && k != MaxIdx) 00811 pMatix->PivotMap(k, MaxIdx, pMatix->jMap, *pMatix->iMap); 00812 return(true); 00813 } 00814 return(false); 00815 } 00816 bool GetDiag(size_t k, t& Diag, bool bWithPartialPivot = false, smatrix<t> *pMatix = NULL) 00817 { 00818 if(bWithPartialPivot) 00819 { 00820 if(PivotRow(k, Diag, pMatix) == false) 00821 return(false); 00822 } 00823 else 00824 Diag = Coef(k, k); 00825 if(abs(Diag) < epsilon) 00826 return(false); 00827 return(true); 00828 } 00829 bool FwdElim(bool bWithPartialPivot, bool bErase = true) 00830 { 00831 for(size_t k = 1; k < iDim; k++) 00832 { 00833 t Diag; 00834 if(!GetDiag(k, Diag, bWithPartialPivot)) return(false); 00835 Diag = t(-1.0) / Diag; 00836 iterator i = IterForCol(k, k + 1); 00837 while(i != EndOfCol(k)) 00838 { 00839 t Scaler = Coef(i) * Diag; 00840 size_t r = Index(i++); 00841 row(r) += row(k, rng(k + 1, jDim)) * Scaler; 00842 if(bErase) erase(r, k); 00843 } 00844 } 00845 t Diag = Coef(k, k); 00846 if(abs(Diag) < epsilon) 00847 return(false); 00848 return(true); 00849 } 00850 bool BackElim(bool bErase = true, bool bScaleDiag = true) 00851 { 00852 for(size_t k = iDim; k >= 1; k--) 00853 { 00854 t Diag; 00855 if(!GetDiag(k, Diag)) return(false); 00856 Diag = t(-1.0) / Diag; 00857 iterator i = IterForCol(k); 00858 while(Index(i) < k) 00859 { 00860 t Scaler = Coef(i) * Diag; 00861 size_t r = Index(i++); 00862 row(r) += row(k) * Scaler; 00863 if(bErase) erase(r, k); 00864 } 00865 if(bScaleDiag) row(k) *= -Diag; 00866 } 00867 return(true); 00868 } 00869 bool SolveWithGaussElim(const smatrix<t> &m, bool bWithPartialPivot = true) 00870 { 00871 *this = m; 00872 if(FwdElim(bWithPartialPivot) == false) return(false); 00873 return(BackElim()); 00874 } 00875 smatrix<t> SolveWithGaussElim(bool bWithPartialPivot = true) const 00876 { 00877 smatrix<t> m; 00878 if(m.SolveWithGaussElim(*this, bWithPartialPivot) == false) 00879 return(smatrix<t>()); 00880 return(m); 00881 } 00882 t det(bool bWithPartialPivot) 00883 { 00884 if(iDim != jDim) return(t(0)); 00885 FwdElim(bWithPartialPivot, true); 00886 t d(bOddNumPivots ? -1.0 : 1.0); 00887 for(size_t k = 1; k <= iDim; k++) 00888 d *= Coef(k, k); 00889 return(d); 00890 } 00891 int lnScaledDet(t& lnScale, bool bWithPartialPivot) 00892 { 00893 lnScale = t(0); 00894 00895 if(iDim != jDim) return(t(0)); 00896 FwdElim(bWithPartialPivot, true); 00897 int sign = (bOddNumPivots ? -1 : 1); 00898 00899 for(size_t k = 1; k <= iDim; k++) 00900 { 00901 t d; 00902 if(!GetDiag(k, d, false)) return(false); 00903 if(d > 0) 00904 lnScale += log(d); 00905 else 00906 { 00907 sign *= -1; 00908 lnScale += log(-d); 00909 } 00910 } 00911 return(sign); 00912 } 00913 int lnScaledDet(const smatrix<t>& m, t &lnScale, bool bWithPartialPivot) 00914 { 00915 *this = m; 00916 return(lnScaledDet(lnScale, bWithPartialPivot)); 00917 } 00918 int lnScaledDet(t &lnScale, bool bWithPartialPivot = true) const 00919 { 00920 smatrix<t> m; 00921 return(m.lnScaledDet(*this, lnScale, bWithPartialPivot)); 00922 } 00923 bool FwdElim(smatrix<t> &m, bool bWithPartialPivot) 00924 { 00925 for(size_t k = 1; k < iDim; k++) 00926 { 00927 t Diag; 00928 if(!GetDiag(k, Diag, bWithPartialPivot, &m)) return(false); 00929 Diag = t(-1.0) / Diag; 00930 iterator i = IterForCol(k, k + 1); 00931 while(i != EndOfCol(k)) 00932 { 00933 t Scaler = Coef(i) * Diag; 00934 size_t r = Index(i++); 00935 row(r) += row(k, rng(k + 1, jDim)) * Scaler; 00936 m.row(r) += m.row(k) * Scaler; 00937 } 00938 } 00939 t Diag = Coef(k, k); 00940 if(abs(Diag) < epsilon) 00941 return(false); 00942 return(true); 00943 } 00944 void RecalcMaxCoef() 00945 { 00946 maxCoef = t(0); 00947 epsilon = 0; 00948 for(size_t i = 1; i < iDim; i++) 00949 { 00950 iterator j = IterForRow(i); 00951 for(; j != EndOfRow(i); j++) 00952 CalcEpsilon(maxCoef, epsilon, e[j->second]); 00953 } 00954 } 00955 bool BackElim(smatrix<t> &m) 00956 { 00957 for(size_t k = iDim; k >= 1; k--) 00958 { 00959 t Diag; 00960 if(!GetDiag(k, Diag)) return(false); 00961 Diag = t(-1.0) / Diag; 00962 iterator i = IterForCol(k); 00963 while(Index(i) < k) 00964 { 00965 t Scaler = Coef(i) * Diag; 00966 size_t r = Index(i++); 00967 row(r) += row(k, rng(k, k)) * Scaler; 00968 m.row(r) += m.row(k) * Scaler; 00969 } 00970 m.row(k) *= -Diag; 00971 } 00972 m.RecalcMaxCoef(); 00973 return(true); 00974 } 00975 smatrix<t> Solve(const smatrix<t> &L, const smatrix<t> &U) const 00976 { 00977 smatrix<t> m, c(*this); 00978 m = L; 00979 if(m.FwdElim(c, false)) 00980 { 00981 m = U; 00982 if(m.BackElim(c)) 00983 return(c); 00984 } 00985 return(smatrix<t>()); 00986 } 00987 smatrix<t> Inverse(bool bWithPartialPivot) const 00988 { 00989 smIdentity<t> c(iDim); 00990 c.epsilon = epsilon; 00991 smatrix<t> m(*this); 00992 00993 if(m.FwdElim(c, bWithPartialPivot)) 00994 { 00995 if(m.BackElim(c)) 00996 return(c); 00997 } 00998 return(smatrix<t>()); 00999 } 01000 t FrobeniousNormal() const 01001 { 01002 if(NZ == 0) return(0); 01003 t d(0); 01004 for(vector<t>::const_iterator i = e.begin(); i != e.end(); i++) 01005 d += *i * *i; 01006 return(sqrt(d)); 01007 } 01008 smatrix<t>& operator*=(const t& d) 01009 { 01010 for(vector<t>::iterator i = e.begin(); i != e.end(); i++) 01011 *i *= d; 01012 return(*this); 01013 } 01014 smatrix<t> operator*(const t& d) const 01015 { 01016 smatrix<t> c(*this); 01017 return(c *= d); 01018 } 01019 void PrintListing(ostream &os) const 01020 { 01021 os << "Matrix" << endl; 01022 os << *this << endl; 01023 os << "vector<t> e" << endl; 01024 for(size_t n = 0; n < e.size(); n++) 01025 os << e[n] << " "; 01026 os << endl << endl; 01027 01028 for(size_t r = 1; r <= iDim; r++) 01029 { 01030 os << "iMap[" << r << "] "; 01031 for(const_iterator i = IterForRow(r); i != EndOfRow(r); i++) 01032 os << "(" << i->first << ", " << i->second << ") "; 01033 os << endl; 01034 } 01035 os << endl; 01036 for(size_t c = 1; c <= jDim; c++) 01037 { 01038 os << "jMap[" << c << "] "; 01039 for(const_iterator j = IterForCol(c); j != EndOfCol(c); j++) 01040 os << "(" << j->first << ", " << j->second << ") "; 01041 os << endl; 01042 } 01043 } 01044 }; 01045 01046 template <class t> smatrix<t> operator*(const t &d, const smatrix<t> &m) 01047 { 01048 return(m * d); 01049 } 01050 01051 template <class t> class smIdentity : public smatrix<t> 01052 { 01053 public: 01054 smIdentity(size_t dim) : smatrix<t>(dim, dim, dim) 01055 { 01056 for(size_t i = 1; i <= dim; i++) 01057 insert(i, i, t(1)); 01058 } 01059 }; 01060 01061 template <class t> inline t det(const smatrix<t>& m, bool bWithPartialPivot = true) 01062 { 01063 smatrix<t> c(m); 01064 return(c.det(bWithPartialPivot)); 01065 } 01066 01067 template <class t> inline ostream& operator<<(ostream& os, const smatrix<t>::svector& v) 01068 { 01069 for(size_t n = v.range.first; n <= v.range.second; n++) 01070 { 01071 os.width(smatrix<t>::PrintWidth); 01072 os.precision(smatrix<t>::PrintPrecision); 01073 os << v(n); 01074 } 01075 return(os); 01076 } 01077 01078 template <class t> inline ostream& operator<<(ostream& os, const smatrix<t>::const_svector_ref& v) 01079 { 01080 for(size_t n = v.range.first; n <= v.range.second; n++) 01081 { 01082 os.width(smatrix<t>::PrintWidth); 01083 os.precision(smatrix<t>::PrintPrecision); 01084 os << v(n); 01085 } 01086 return(os); 01087 } 01088 01089 template <class t> inline ostream& operator<<(ostream& os, const smatrix<t>& m) 01090 { 01091 if(m.NZ > 0) 01092 { 01093 if(m.iDim < 20) 01094 { 01095 for(size_t i = 1; i <= m.iDim; i++) 01096 os << m(i, rng(1, m.jDim)) << endl; 01097 } 01098 else 01099 { 01100 os << m.iDim << " x " << m.jDim << ", NZ = " << m.NZ << endl; 01101 os << "Max coef = " << m.maxCoef << ", epsilon = " << m.epsilon << endl; 01102 } 01103 } 01104 else 01105 os << "<null>"; 01106 return(os); 01107 } 01108 01109 template <class t> inline t Residual(const smatrix<t> &a, const smatrix<t> &b) 01110 { 01111 return((a - b).maxCoef); 01112 } 01113 01114 inline void CalcEpsilon(double &maxCoef, double &epsilon, const double &d) 01115 { 01116 double ep = abs(d); 01117 if(maxCoef < ep) { 01118 maxCoef = ep; 01119 epsilon = max(ep * DBL_EPSILON, epsilon); } 01120 }