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 }