CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/TrackPropagation/NavGeometry/src/LinearEquation3.h

Go to the documentation of this file.
00001 #ifndef LinearEquation3_H
00002 #define LinearEquation3_H
00003 
00004 #include "DataFormats/GeometryVector/interface/Basic3DVector.h"
00005 
00006 #include <algorithm>
00007 
00008 #ifdef DEBUG_SOLUTION
00009 #include <iostream>
00010 #endif
00011 
00012 template <class T>
00013 class LinearEquation3 {
00014 public:
00015 
00016   template <class U> 
00017   class Array3 {
00018   public:
00019     Array3() {}
00020     Array3( U a0, U a1, U a2) { a_[0] = a0; a_[1] = a1; a_[2] = a2;}
00021     Array3( const Basic3DVector<U>& v) {
00022       a_[0] = v.x(); a_[1] = v.y(); a_[2] = v.z();
00023     }
00024 
00025     Array3& operator=( const Array3& other) {
00026       a_[0] = other[0]; a_[1] = other[1]; a_[2] = other[2];
00027       return *this;
00028     }
00029       
00030     Array3& operator=(const Basic3DVector<U>& v) {
00031       a_[0] = v.x(); a_[1] = v.y(); a_[2] = v.z();
00032       return *this;
00033     }
00034 
00035     U& operator[]( int i) { return a_[i];}
00036     const U& operator[]( int i) const { return a_[i];}
00037     void operator-=( const Array3& other) {
00038       a_[0] -= other[0];
00039       a_[1] -= other[1];
00040       a_[2] -= other[2];
00041     }
00042 
00043     Array3 operator*( U t) const {
00044       return Array3( a_[0]*t, a_[1]*t, a_[2]*t);
00045     }
00046 
00047     void subtractScaled( const Array3& a, U c) {
00048       a_[0] -= a[0]*c;  a_[1] -= a[1]*c;  a_[2] -= a[2]*c; 
00049     }
00050 
00051   private:
00052     U a_[3];
00053   };
00054 
00055   Basic3DVector<T> solution( const Basic3DVector<T>& row0,
00056                              const Basic3DVector<T>& row1,
00057                              const Basic3DVector<T>& row2,
00058                              const Basic3DVector<T>& rhsvec) const {
00059 
00060     // copy the input to internal "matrix"
00061     Array3<T> row[3];
00062     row[0] = row0;
00063     row[1] = row1;
00064     row[2] = row2;
00065     Array3<T> rhs(rhsvec);
00066 
00067     // no implicit pivoting - rows expected to be normalized already
00068 
00069     // find pivot 0, i.e. row with largest first element
00070     int i0 = std::abs(row[0][0]) > std::abs(row[1][0]) ? 0 : 1;
00071     if (std::abs(row[i0][0]) < std::abs(row[2][0])) i0 = 2;
00072 
00073     int i1 = (i0+1)%3;
00074     int i2 = (i0+2)%3;
00075 
00076     // zero the first column of rows i1 and i2
00077     T c1 = row[i1][0] / row[i0][0];
00078     // row[i1] -= c1*row[i0];
00079     row[i1].subtractScaled( row[i0], c1);
00080     rhs[i1] -= c1*rhs[i0];
00081     T c2 = row[i2][0] / row[i0][0];
00082     // row[i2] -= c2*row[i0];
00083     row[i2].subtractScaled( row[i0], c2);
00084     rhs[i2] -= c2*rhs[i0];
00085 
00086     // find pivot 1, i.e. which row (i1 or i2) has the largest second element
00087     if (std::abs(row[i1][1]) < std::abs(row[i2][1])) std::swap( i1, i2);
00088 
00089     // zero the second column of row i2
00090     T c3 = row[i2][1] / row[i1][1];
00091     row[i2][1] -= c3 * row[i1][1];
00092     row[i2][2] -= c3 * row[i1][2];
00093     rhs[i2] -= c3*rhs[i1];
00094 
00095     // compute the solution
00096     T x2 = rhs[i2] / row[i2][2];
00097     T x1 = (rhs[i1] - x2*row[i1][2]) / row[i1][1];
00098     T x0 = (rhs[i0] - x1*row[i0][1] - x2*row[i0][2]) / row[i0][0];
00099 
00100     return Basic3DVector<T>(x0, x1, x2);
00101   }
00102 
00103 #ifdef DEBUG_SOLUTION
00104 private:
00105   typedef Array3<T> AT;
00106   void dump(const AT row[]) const {
00107     std::cout << " (" << row[0][0] << ',' << row[0][1] << ',' << row[0][2] << ") " << std::endl;
00108     std::cout << " (" << row[1][0] << ',' << row[1][1] << ',' << row[1][2] << ") " << std::endl;
00109     std::cout << " (" << row[2][0] << ',' << row[2][1] << ',' << row[2][2] << ") " << std::endl;
00110     std::cout << std::endl;
00111   }
00112 #endif
00113 
00114 };
00115 
00116 #endif