C:/programs/SCPPNT/src/include/triang.h

00001 /*! \file tiang.h
00002  \brief Views and adaptors for triangular matrices.
00003  
00004  Modified version of triang.h from the Template Numerical Toolkit (TNT) 
00005  Currently, the only changes made are that exceptions are thrown rather
00006  than assert being called. The classes and functions in this file have
00007  not been tested with SCPPNT.
00008 
00009  */
00010 
00011 /*
00012  Simple C++ Numerical Toolkit (SCPPNT)
00013  http://www.smallwaters.com/software/cpp/scppnt.html
00014  This release updates original work contributed by 
00015  Brad Hanson (http://www.b-a-h.com/) in 2001.
00016  
00017  Modification: Changed "endl" to "std::endl". ww, 12-16-2007.
00018 
00019  */
00020 
00021 // Modified from tiang.h in:
00022 /*
00023  *
00024  * Template Numerical Toolkit (TNT): Linear Algebra Module
00025  *
00026  * Mathematical and Computational Sciences Division
00027  * National Institute of Technology,
00028  * Gaithersburg, MD USA
00029  *
00030  *
00031  * This software was developed at the National Institute of Standards and
00032  * Technology (NIST) by employees of the Federal Government in the course
00033  * of their official duties. Pursuant to title 17 Section 105 of the
00034  * United States Code, this software is not subject to copyright protection
00035  * and is in the public domain.  The Template Numerical Toolkit (TNT) is
00036  * an experimental system.  NIST assumes no responsibility whatsoever for
00037  * its use by other parties, and makes no guarantees, expressed or implied,
00038  * about its quality, reliability, or any other characteristic.
00039  *
00040  * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
00041  * see http://math.nist.gov/tnt for latest updates.
00042  *
00043  */
00044 
00045 // Triangular Matrices (Views and Adapators)
00046 // default to use lower-triangular portions of arrays
00047 // for symmetric matrices.
00048 
00049 #ifndef SCPPNT_TRIANG_H
00050 #define SCPPNT_TRIANG_H
00051 
00052 #ifdef SCPPNT_NO_DIR_PREFIX
00053 #include "scppnt.h"
00054 #include "scppnt_error.h"
00055 #else
00056 #include "scppnt/scppnt.h"
00057 #include "scppnt/scppnt_error.h"
00058 #endif
00059 
00060 #ifndef SCPPNT_NO_IO
00061 #include <iostream>
00062 #endif
00063 
00064 namespace SCPPNT
00065 {
00066 
00067   //! Lower triangular view of a matrix.
00068   template<class MaTRiX> class LowerTriangularView
00069   {
00070 protected:
00071 
00072     const MaTRiX &A_;
00073     const typename MaTRiX::element_type zero_;
00074 
00075 public:
00076 
00077     typedef typename MaTRiX::const_reference const_reference;
00078     typedef const typename MaTRiX::element_type element_type;
00079     typedef const typename MaTRiX::element_type value_type;
00080     typedef element_type T;
00081 
00082     Subscript dim(Subscript d) const
00083     {
00084       return A_.dim(d);
00085     }
00086     Subscript lbound() const
00087     {
00088       return A_.lbound();
00089     }
00090     Subscript num_rows() const
00091     {
00092       return A_.num_rows();
00093     }
00094     Subscript num_columns() const
00095     {
00096       return A_.num_columns();
00097     }
00098 
00099     // constructors
00100 
00101     LowerTriangularView(/*const*/MaTRiX &A) :
00102       A_(A), zero_(0)
00103     {
00104     }
00105 
00106     inline const_reference get(Subscript i, Subscript j) const
00107     {
00108 #ifdef SCPPNT_BOUNDS_CHECK
00109       if (lbound() > i || i>(A_.num_rows() + lbound() - 1) || lbound > j || j>(A_.num_columns()
00110           + lbound() - 1))
00111         throw BoundsError("LowerTriangularView::get");
00112 #endif
00113       if (i<j)
00114         return zero_;
00115       else
00116         return A_(i, j);
00117     }
00118 
00119     inline const_reference operator()(Subscript i, Subscript j) const
00120     {
00121 #ifdef SCPPNT_BOUNDS_CHECK
00122       if (lbound() > i || i>(A_.num_rows() + lbound() - 1) || lbound > j || j>(A_.num_columns()
00123           + lbound() - 1))
00124         throw BoundsError("LowerTriangularView::operator()");
00125 #endif
00126       if (i<j)
00127         return zero_;
00128       else
00129         return A_(i, j);
00130     }
00131 
00132 #ifdef SCPPNT_USE_REGIONS
00133 
00134     typedef const_Region2D< LowerTriangularView<MaTRiX> >
00135     const_Region;
00136 
00137     const_Region operator()(/*const*/Index1D &I,
00138         /*const*/Index1D &J) const
00139     {
00140       return const_Region(*this, I, J);
00141     }
00142 
00143     const_Region operator()(Subscript i1, Subscript i2,
00144         Subscript j1, Subscript j2) const
00145     {
00146       return const_Region(*this, i1, i2, j1, j2);
00147     }
00148 
00149 #endif
00150     // SCPPNT_USE_REGIONS
00151 
00152   };
00153 
00154   /* *********** Lower_triangular_view() algorithms ****************** */
00155 
00156   //! Multiply lower triangular view times a vector
00157   template<class MaTRiX, class VecToR> VecToR matmult(/*const*/LowerTriangularView<MaTRiX> &A,
00158       VecToR &x)
00159   {
00160     Subscript M = A.num_rows();
00161     Subscript N = A.num_columns();
00162 
00163     // assert(N == x.dim());
00164     if (N != x.dim())
00165       throw BoundsError("matmult(LowerTriangularView,Vector)");
00166 
00167     Subscript i, j;
00168     typename MaTRiX::element_type sum=0.0;
00169     VecToR result(M);
00170 
00171     Subscript start = A.lbound();
00172     Subscript Mend = M + A.lbound() -1;
00173 
00174     for (i=start; i<=Mend; i++)
00175     {
00176       sum = 0.0;
00177       for (j=start; j<=i; j++)
00178         sum = sum + A(i, j)*x(j);
00179       result(i) = sum;
00180     }
00181 
00182     return result;
00183   }
00184 
00185   //! Multiplication operator for product of lower triangular view and a vector
00186   template<class MaTRiX, class VecToR> inline VecToR operator*(
00187       /*const*/LowerTriangularView<MaTRiX> &A, VecToR &x)
00188   {
00189     return matmult(A, x);
00190   }
00191 
00192   //! Lower triangular view of a matrix with a unit diagonal
00193   template<class MaTRiX> class UnitLowerTriangularView
00194   {
00195 protected:
00196 
00197     const MaTRiX &A_;
00198     const typename MaTRiX::element_type zero;
00199     const typename MaTRiX::element_type one;
00200 
00201 public:
00202 
00203     typedef typename MaTRiX::const_reference const_reference;
00204     typedef typename MaTRiX::element_type element_type;
00205     typedef typename MaTRiX::element_type value_type;
00206     typedef element_type T;
00207 
00208     Subscript lbound() const
00209     {
00210       return 1;
00211     }
00212     Subscript dim(Subscript d) const
00213     {
00214       return A_.dim(d);
00215     }
00216     Subscript num_rows() const
00217     {
00218       return A_.num_rows();
00219     }
00220     Subscript num_columns() const
00221     {
00222       return A_.num_columns();
00223     }
00224 
00225     // constructors
00226 
00227     UnitLowerTriangularView(/*const*/MaTRiX &A) :
00228       A_(A), zero(0), one(1)
00229     {
00230     }
00231 
00232     inline const_reference get(Subscript i, Subscript j) const
00233     {
00234 #ifdef SCPPNT_BOUNDS_CHECK
00235       if (1>i || i>A_.dim(1) || 1>j || j>A_.dim(2) || !(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1)))
00236         throw BoundsError("UnitLowerTriangularView::get");
00237 #endif
00238       if (i>j)
00239         return A_(i, j);
00240       else if (i==j)
00241         return one;
00242       else
00243         return zero;
00244     }
00245 
00246     inline const_reference operator()(Subscript i, Subscript j) const
00247     {
00248 #ifdef SCPPNT_BOUNDS_CHECK
00249       if (1>i || i>A_.dim(1) || 1>j || j>A_.dim(2))
00250         throw BoundsError("UnitLowerTriangularView::operator()");
00251 #endif
00252       if (i>j)
00253         return A_(i, j);
00254       else if (i==j)
00255         return one;
00256       else
00257         return zero;
00258     }
00259 
00260 #ifdef SCPPNT_USE_REGIONS
00261     // These are the "index-aware" features
00262 
00263     typedef const_Region2D< UnitLowerTriangularView<MaTRiX> >
00264     const_Region;
00265 
00266     const_Region operator()(/*const*/Index1D &I,
00267         /*const*/Index1D &J) const
00268     {
00269       return const_Region(*this, I, J);
00270     }
00271 
00272     const_Region operator()(Subscript i1, Subscript i2,
00273         Subscript j1, Subscript j2) const
00274     {
00275       return const_Region(*this, i1, i2, j1, j2);
00276     }
00277 #endif
00278     // SCPPNT_USE_REGIONS
00279   };
00280 
00281   //! Adaptor to create a lower trangular view of a matrix
00282   template<class MaTRiX> LowerTriangularView<MaTRiX> Lower_triangular_view(
00283   /*const*/MaTRiX &A)
00284   {
00285     return LowerTriangularView<MaTRiX>(A);
00286   }
00287 
00288   //! Adaptor to create a unit lower trangular view of a matrix
00289   template<class MaTRiX> UnitLowerTriangularView<MaTRiX> Unit_lower_triangular_view(
00290   /*const*/MaTRiX &A)
00291   {
00292     return UnitLowerTriangularView<MaTRiX>(A);
00293   }
00294 
00295   //! Multiply a lower triangular view times a vector
00296   template<class MaTRiX, class VecToR> VecToR matmult(/*const*/UnitLowerTriangularView<MaTRiX> &A,
00297       VecToR &x)
00298   {
00299     Subscript M = A.num_rows();
00300     Subscript N = A.num_columns();
00301 
00302     //assert(N == x.dim());
00303     if (N != x.dim())
00304       throw BoundsError("matmult(UnitLowerTriangularView,Vector)");
00305 
00306     Subscript i, j;
00307     typename MaTRiX::element_type sum=0.0;
00308     VecToR result(M);
00309 
00310     Subscript start = A.lbound();
00311     Subscript Mend = M + A.lbound() -1;
00312 
00313     for (i=start; i<=Mend; i++)
00314     {
00315       sum = 0.0;
00316       for (j=start; j<i; j++)
00317         sum = sum + A(i, j)*x(j);
00318       result(i) = sum + x(i);
00319     }
00320 
00321     return result;
00322   }
00323 
00324   //! Multiplication operator giving the product of a lower triangular view and a vector,
00325   template<class MaTRiX, class VecToR> inline VecToR operator*(
00326       /*const*/UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
00327   {
00328     return matmult(A, x);
00329   }
00330 
00331   //********************** Algorithms *************************************
00332 
00333 
00334 #ifndef SCPPNT_NO_IO
00335   //! Assign values of a lower triangular view from a stream
00336   template<class MaTRiX> std::ostream& operator<<(std::ostream &s,
00337       const LowerTriangularView<MaTRiX>&A)
00338   {
00339     Subscript M=A.num_rows();
00340     Subscript N=A.num_columns();
00341 
00342     s << M << " " << N << std::endl;
00343 
00344     for (Subscript i=1; i<=M; i++)
00345     {
00346       for (Subscript j=1; j<=N; j++)
00347       {
00348         s << A(i, j) << " ";
00349       }
00350       s << std::endl;
00351     }
00352 
00353     return s;
00354   }
00355 
00356   //! Write values of a lower triangular view to a stream
00357   template<class MaTRiX> std::ostream& operator<<(std::ostream &s,
00358       const UnitLowerTriangularView<MaTRiX>&A)
00359   {
00360     Subscript M=A.num_rows();
00361     Subscript N=A.num_columns();
00362 
00363     s << M << " " << N << std::endl;
00364 
00365     for (Subscript i=1; i<=M; i++)
00366     {
00367       for (Subscript j=1; j<=N; j++)
00368       {
00369         s << A(i, j) << " ";
00370       }
00371       s << std::endl;
00372     }
00373 
00374     return s;
00375   }
00376 
00377 #endif
00378 
00379   // ******************* Upper Triangular Section **************************
00380 
00381   //! Upper triangular view of a matrix
00382   template<class MaTRiX> class UpperTriangularView
00383   {
00384 protected:
00385 
00386     /*const*/MaTRiX &A_;
00387     /*const*/
00388     typename MaTRiX::element_type zero_;
00389 
00390 public:
00391 
00392     typedef typename MaTRiX::const_reference const_reference;
00393     typedef /*const*/typename MaTRiX::element_type element_type;
00394     typedef /*const*/typename MaTRiX::element_type value_type;
00395     typedef element_type T;
00396 
00397     Subscript dim(Subscript d) const
00398     {
00399       return A_.dim(d);
00400     }
00401     Subscript lbound() const
00402     {
00403       return A_.lbound();
00404     }
00405     Subscript num_rows() const
00406     {
00407       return A_.num_rows();
00408     }
00409     Subscript num_columns() const
00410     {
00411       return A_.num_columns();
00412     }
00413 
00414     // constructors
00415 
00416     UpperTriangularView(/*const*/MaTRiX &A) :
00417       A_(A), zero_(0)
00418     {
00419     }
00420 
00421     inline const_reference get(Subscript i, Subscript j) const
00422     {
00423 #ifdef SCPPNT_BOUNDS_CHECK
00424       if (lbound>i || i>(A_.num_rows() + lbound() - 1) || lbound()>j || j>(A_.num_columns()
00425           + lbound() - 1))
00426         throw BoundsError("UpperTriangularView::get");
00427 #endif
00428       if (i>j)
00429         return zero_;
00430       else
00431         return A_(i, j);
00432     }
00433 
00434     inline const_reference operator()(Subscript i, Subscript j) const
00435     {
00436 #ifdef SCPPNT_BOUNDS_CHECK
00437       if (lbound()>i || i>(A_.num_rows() + lbound() - 1) || lbound()>j || j>(A_.num_columns()
00438           + lbound() - 1))
00439         throw BoundsError("UpperTriangularView::operator()");
00440 #endif
00441       if (i>j)
00442         return zero_;
00443       else
00444         return A_(i, j);
00445     }
00446 
00447 #ifdef SCPPNT_USE_REGIONS
00448 
00449     typedef const_Region2D< UpperTriangularView<MaTRiX> >
00450     const_Region;
00451 
00452     const_Region operator()(const Index1D &I,
00453         const Index1D &J) const
00454     {
00455       return const_Region(*this, I, J);
00456     }
00457 
00458     const_Region operator()(Subscript i1, Subscript i2,
00459         Subscript j1, Subscript j2) const
00460     {
00461       return const_Region(*this, i1, i2, j1, j2);
00462     }
00463 
00464 #endif
00465     // SCPPNT_USE_REGIONS
00466 
00467   };
00468 
00469   /* *********** Upper_triangular_view() algorithms ****************** */
00470 
00471   //! Multiply an upper triangular view times a vector.
00472   template<class MaTRiX, class VecToR> VecToR matmult(/*const*/UpperTriangularView<MaTRiX> &A,
00473       VecToR &x)
00474   {
00475     Subscript M = A.num_rows();
00476     Subscript N = A.num_columns();
00477 
00478     //assert(N == x.dim());
00479     if (N != x.dim())
00480       throw BoundsError("matmult(UpperTriangularView,Vector)");
00481 
00482     Subscript i, j;
00483     typename VecToR::element_type sum=0.0;
00484     VecToR result(M);
00485 
00486     Subscript start = A.lbound();
00487     Subscript Mend = M + A.lbound() -1;
00488 
00489     for (i=start; i<=Mend; i++)
00490     {
00491       sum = 0.0;
00492       for (j=i; j<=N; j++)
00493         sum = sum + A(i, j)*x(j);
00494       result(i) = sum;
00495     }
00496 
00497     return result;
00498   }
00499 
00500   //! Multiplication operator giving project of an upper triangular view and a vector.
00501   template<class MaTRiX, class VecToR> inline VecToR operator*(
00502       /*const*/UpperTriangularView<MaTRiX> &A, VecToR &x)
00503   {
00504     return matmult(A, x);
00505   }
00506 
00507   //! Upper triangular view of a matrix with a unit diagonal
00508   template<class MaTRiX> class UnitUpperTriangularView
00509   {
00510 protected:
00511 
00512     const MaTRiX &A_;
00513     const typename MaTRiX::element_type zero;
00514     const typename MaTRiX::element_type one;
00515 
00516 public:
00517 
00518     typedef typename MaTRiX::const_reference const_reference;
00519     typedef typename MaTRiX::element_type element_type;
00520     typedef typename MaTRiX::element_type value_type;
00521     typedef element_type T;
00522 
00523     Subscript lbound() const
00524     {
00525       return 1;
00526     }
00527     Subscript dim(Subscript d) const
00528     {
00529       return A_.dim(d);
00530     }
00531     Subscript num_rows() const
00532     {
00533       return A_.num_rows();
00534     }
00535     Subscript num_columns() const
00536     {
00537       return A_.num_columns();
00538     }
00539 
00540     // constructors
00541 
00542     UnitUpperTriangularView(/*const*/MaTRiX &A) :
00543       A_(A), zero(0), one(1)
00544     {
00545     }
00546 
00547     inline const_reference get(Subscript i, Subscript j) const
00548     {
00549 #ifdef SCPPNT_BOUNDS_CHECK
00550       if (1>i || i>A_.dim(1) || 1>j || j>A_.dim(2) || !(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1)))
00551         throw BoundsError("UnitUpperTriangularView::get");
00552 #endif
00553       if (i<j)
00554         return A_(i, j);
00555       else if (i==j)
00556         return one;
00557       else
00558         return zero;
00559     }
00560 
00561     inline const_reference operator()(Subscript i, Subscript j) const
00562     {
00563 #ifdef SCPPNT_BOUNDS_CHECK
00564       if (1>i || i>A_.dim(1) || 1>j || j>A_.dim(2))
00565         throw BoundsError("UnitUpperTriangularView::operator()");
00566 #endif
00567       if (i<j)
00568         return A_(i, j);
00569       else if (i==j)
00570         return one;
00571       else
00572         return zero;
00573     }
00574 
00575 #ifdef SCPPNT_USE_REGIONS
00576     // These are the "index-aware" features
00577 
00578     typedef const_Region2D< UnitUpperTriangularView<MaTRiX> >
00579     const_Region;
00580 
00581     const_Region operator()(const Index1D &I,
00582         const Index1D &J) const
00583     {
00584       return const_Region(*this, I, J);
00585     }
00586 
00587     const_Region operator()(Subscript i1, Subscript i2,
00588         Subscript j1, Subscript j2) const
00589     {
00590       return const_Region(*this, i1, i2, j1, j2);
00591     }
00592 #endif
00593     // SCPPNT_USE_REGIONS
00594   };
00595 
00596   //! Adapter to create upper triangular view of matrix
00597   template<class MaTRiX> UpperTriangularView<MaTRiX> Upper_triangular_view(
00598   /*const*/MaTRiX &A)
00599   {
00600     return UpperTriangularView<MaTRiX>(A);
00601   }
00602 
00603   // Adaptor to create unit upper triangular view of matrix.
00604   template<class MaTRiX> UnitUpperTriangularView<MaTRiX> Unit_upper_triangular_view(
00605   /*const*/MaTRiX &A)
00606   {
00607     return UnitUpperTriangularView<MaTRiX>(A);
00608   }
00609 
00610   //! Multiply a unit upper triangular view times a vector
00611   template<class MaTRiX, class VecToR> VecToR matmult(/*const*/UnitUpperTriangularView<MaTRiX> &A,
00612       VecToR &x)
00613   {
00614     Subscript M = A.num_rows();
00615     Subscript N = A.num_columns();
00616 
00617     // assert(N == x.dim());
00618     if (N != x.dim())
00619       throw BoundsError("matmult(UnitUpperTriangularView,Vector)");
00620 
00621     Subscript i, j;
00622     typename VecToR::element_type sum=0.0;
00623     VecToR result(M);
00624 
00625     Subscript start = A.lbound();
00626     Subscript Mend = M + A.lbound() -1;
00627 
00628     for (i=start; i<=Mend; i++)
00629     {
00630       sum = x(i);
00631       for (j=i+1; j<=N; j++)
00632         sum = sum + A(i, j)*x(j);
00633       result(i) = sum + x(i);
00634     }
00635 
00636     return result;
00637   }
00638 
00639   //! Multiplication operator giving the project of a unit upper triangular view and a vector.
00640   template<class MaTRiX, class VecToR> inline VecToR operator*(
00641       /*const*/UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
00642   {
00643     return matmult(A, x);
00644   }
00645 
00646   //********************** Algorithms *************************************
00647 
00648 
00649 #ifndef SCPPNT_NO_IO
00650 
00651   //! Write the contents of an upper triangular view to a stream.
00652   template<class MaTRiX> std::ostream& operator<<(std::ostream &s,
00653   /*const*/UpperTriangularView<MaTRiX>&A)
00654   {
00655     Subscript M=A.num_rows();
00656     Subscript N=A.num_columns();
00657 
00658     s << M << " " << N << std::endl;
00659 
00660     for (Subscript i=1; i<=M; i++)
00661     {
00662       for (Subscript j=1; j<=N; j++)
00663       {
00664         s << A(i, j) << " ";
00665       }
00666       s << std::endl;
00667     }
00668 
00669     return s;
00670   }
00671 
00672   //! Write the contents of a unit upper triangular view to a stream.
00673   template<class MaTRiX> std::ostream& operator<<(std::ostream &s,
00674   /*const*/UnitUpperTriangularView<MaTRiX>&A)
00675   {
00676     Subscript M=A.num_rows();
00677     Subscript N=A.num_columns();
00678 
00679     s << M << " " << N << std::endl;
00680 
00681     for (Subscript i=1; i<=M; i++)
00682     {
00683       for (Subscript j=1; j<=N; j++)
00684       {
00685         s << A(i, j) << " ";
00686       }
00687       s << std::endl;
00688     }
00689 
00690     return s;
00691   }
00692 
00693 #endif
00694 
00695 } // namespace SCPPNT
00696 
00697 
00698 #endif 
00699 // SCPPNT_TRIANG_H
00700 

Generated on Tue Dec 18 23:34:06 2007 for SCPPNT by  doxygen 1.5.4