Main Page   Packages   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Search  

C:/temp/src/j2k/Beta/Math/Vector/NotDone/Gauss/Smatrix.hpp

Go to the documentation of this file.
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 }

Generated on Sun Oct 14 18:46:15 2001 for Standard J2K Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001