Changeset 1007 in Sophya


Ignore:
Timestamp:
May 16, 2000, 7:54:20 PM (25 years ago)
Author:
ansari
Message:

gestion det dans GausPiv et new norm cmv 16/5/00

Location:
trunk/SophyaLib/TArray
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/SophyaLib/TArray/sopemtx.cc

    r999 r1007  
    438438#define M_LN2 0.69314718055994530942
    439439#endif
     440//// CMV BUG BUG : sur OSF 5.0 DMINEXP est deconnant (~1.e+19 !!!)
    440441#ifndef LN_MINDOUBLE
    441442#define LN_MINDOUBLE  (M_LN2 * (DMINEXP - 1))
     
    445446#endif
    446447
     448template <class T>
     449int SimpleMatrixOperation<T>::GausPivScaling = PIV_GLOB_SCALE;
     450
    447451//! Gaussian pivoting
    448452/*!
    449453  Do Gauss pivoting of \b a, doing the same operations on matrix \b b
    450   \return determinant of \b a.
     454  \param computedet = true : return determimant of \b a (beware of over/underfloat)
     455  \param computedet = false : return 1 if OK, 0 if not.
    451456  \verbatim
    452457  Solve linear system A(n,n) * X(n,m) = B(n,m)
     
    457462 */ 
    458463template <class T>
    459 T SimpleMatrixOperation<T>::GausPiv(TMatrix<T>& a, TMatrix<T>& b)
     464T SimpleMatrixOperation<T>::GausPiv(TMatrix<T>& a, TMatrix<T>& b,bool computedet)
    460465// Pivot de Gauss
    461466// * Attention: egcs impose que cette fonction soit mise dans le .cc
     
    466471if(n!=b.NRows())
    467472  throw(SzMismatchError("TMatrix::GausPiv size mismatch\n"));
    468 // On fait une normalisation un peu brutale...
    469 double vmin=MAXDOUBLE;
    470 double vmax=0;
    471 for(uint_4 iii=0; iii<a.NRows(); iii++)
    472   for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
    473     double v = TMatrixRC<T>::Abs_Value(a(iii,jjj));
    474     if(v>vmax) vmax = v;
    475     if(v<vmin && v>0) vmin = v;
    476 }
    477 double nrm = sqrt(vmin*vmax);
    478 if(nrm > 1.e5 || nrm < 1.e-5) {
    479   a /= (T) nrm;
    480   b /= (T) nrm;
    481   //cout << "normalisation matrice " << nrm << endl;
    482 } else nrm=1;
    483473
    484474T det = 1;
    485 if(nrm != 1) {
    486   double ld = a.NRows() * log(nrm);
    487   if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
    488    // cerr << "TMatrix warning, overflow for det" << endl;
    489   } else {
    490     det = (T) exp(ld);
    491   }
    492 }
     475
     476//////////////////
     477// Data scaling //
     478//////////////////
     479
     480// Pas de normalisation des donnees
     481if(GausPivScaling==PIV_NO_SCALE) {
     482  if(computedet) det = (T) 1;
     483// normalisation des donnees ligne par ligne
     484} else if(GausPivScaling==PIV_ROW_SCALE) {
     485  double nrm = 0.;
     486  for(uint_4 iii=0; iii<a.NRows(); iii++) {
     487    uint_4 jjj; double vmax = -1.;
     488    for(jjj=0; jjj<a.NCols(); jjj++) {
     489      double v = TMatrixRC<T>::Abs_Value(a(iii,jjj));
     490      if(v>vmax) vmax = v;
     491    }
     492    if(vmax>0.) {
     493      for(jjj=0; jjj<a.NCols(); jjj++) a(iii,jjj) /= (T) vmax;
     494      for(jjj=0; jjj<b.NCols(); jjj++) b(iii,jjj) /= (T) vmax;
     495      nrm += log(vmax);
     496    } else return (T) 0;
     497  }
     498  if(computedet) {
     499    if(nrm <= LN_MINDOUBLE || nrm >= LN_MAXDOUBLE) {
     500      cerr<<"GausPiv_Row: normalisation failure, "
     501          <<"determinant has to be multiplied by exp("<<nrm<<")"<<endl;
     502    } else det = (T) exp(nrm);
     503  }
     504// On fait une normalisation un peu brutale globale
     505} else {
     506  double vmin=MAXDOUBLE, vmax=0;
     507  for(uint_4 iii=0; iii<a.NRows(); iii++)
     508    for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
     509      double v = TMatrixRC<T>::Abs_Value(a(iii,jjj));
     510      if(v>vmax) vmax = v;
     511      if(v<vmin && v>0.) vmin = v;
     512  }
     513  double nrm = sqrt(vmin*vmax);
     514  if(nrm>0.) { a /= (T) nrm; b /= (T) nrm;} else return (T) 0;
     515  if(computedet) {
     516    nrm = a.NRows() * log(nrm);
     517    if (nrm <= LN_MINDOUBLE || nrm >= LN_MAXDOUBLE) {
     518      cerr<<"GausPiv_Glob: normalisation failure, "
     519          <<"determinant has to be multiplied by exp("<<nrm<<")"<<endl;
     520    } else det = (T) exp(nrm);
     521  }
     522}
     523
     524////////////////////////////////////////
     525// Gaussian elimination with pivoting //
     526////////////////////////////////////////
    493527
    494528TMatrixRC<T> pivRowa(a,TMatrixRC<T>::TmatrixRow);
     
    507541  T pivot = a(k,k);
    508542  if( TMatrixRC<T>::Abs_Value(pivot) < 1.e-50 ) return (T) 0;
    509   //det *= pivot;
     543  if(computedet) det *= pivot;
    510544  pivRowa.SetRow(k); // to avoid constructors
    511545  pivRowb.SetRow(k);
     
    516550  }
    517551}
    518 det *= a(n-1, n-1);
     552if(computedet) det *= a(n-1, n-1);
    519553
    520554// on remonte
     
    545579TMatrix<T> a(A,false);
    546580TMatrix<T> b(a.NCols(),a.NRows());  b = IdentityMatrix(1.);
    547 if( TMatrixRC<T>::Abs_Value(GausPiv(a,b)) < 1.e-50)
     581if(GausPiv(a,b)==(T) 0)
    548582  throw(MathExc("TMatrix Inverse() Singular Matrix"));
    549583b.SetTemp(true);
     
    620654     a(j,k) = a(k,j) = TMatrixRC<T>::Row(const_cast<TMatrix<T> &>(fx), j)
    621655                     * TMatrixRC<T>::Row(const_cast<TMatrix<T> &>(fx), k);
    622                                 /* $CHECK$ Reza 10/3/2000 */
    623656
    624657c = fx * y;
    625658
    626659if(SimpleMatrixOperation<T>::GausPiv(a,c)==(T) 0) THROW(singMatxErr);
    627                    /* $CHECK$ Reza 10/3/2000 */
    628660
    629661r_8 xi2 = 0., ax;
     
    718750
    719751if(SimpleMatrixOperation<T>::GausPiv(a,d)==(T) 0) THROW(singMatxErr);
    720                                             /* $CHECK$ Reza 10/3/2000 */
    721752
    722753for(uint_4 l=0; l<nf; l++) {
     
    806837#endif
    807838
    808 
    809 
    810 
    811 
    812 
    813 
    814 
    815 
    816 
    817 
    818 
    819 
  • trunk/SophyaLib/TArray/sopemtx.h

    r999 r1007  
    2727class SimpleMatrixOperation {
    2828public:
     29  //! To define the type of data scaling for Gauss pivoting method (type T)
     30  enum GausPivScal {
     31    PIV_NO_SCALE = 0,   //!< do not scale datas for gauss pivoting
     32    PIV_GLOB_SCALE = 1, //!< do a global scaling of datas for gauss pivoting (default)
     33    PIV_ROW_SCALE = 2   //!< do a scaling by row of datas for gauss pivoting
     34  };
     35  static inline int SetGausPivScal(int gps = PIV_GLOB_SCALE)
     36              { GausPivScaling = gps; return GausPivScaling; }
     37
    2938  static TMatrix<T> Inverse(TMatrix<T> const & A);
    30   static T GausPiv(TMatrix<T>& A, TMatrix<T>& B);
     39  static T GausPiv(TMatrix<T>& A, TMatrix<T>& B, bool computedet=false);
     40
     41protected:
     42  static int GausPivScaling;
    3143};
    3244
     
    4759//------------------------------------------------------------
    4860/*! \ingroup TArray \fn LinSolveInPlace(TMatrix<T>&,TVector<T>&)
    49     \brief  Solve A*C = B for C in place and return determinant
     61    \brief  Solve A*C = B for C in place and return 1 if OK, 0 if not.
    5062*/
    5163template <class T>
     
    6274/*! \ingroup TArray
    6375    \fn LinSolve(const TMatrix<T>&, const TVector<T>&, TVector<T>&)
    64     \brief Solve A*C = B and return C and determinant
     76    \brief Solve A*C = B and return C. Return 1 if OK, 0 if not.
    6577*/
    6678template <class T>
     
    8698/*! \ingroup TArray
    8799    \fn Inverse(TMatrix<T> const &)
    88     \brief To inverse a TMatrix
     100    \brief To inverse a TMatrix.
    89101*/
    90102template <class T>
     
    94106/*! \ingroup TArray
    95107    \fn Determinant(TMatrix<T> const &)
    96     \brief Give the TMatrix determinant
     108    \brief Return the TMatrix determinant
    97109*/
    98110template <class T>
     
    100112  TMatrix<T> a(A,false);
    101113  TMatrix<T> b(a.NCols(),a.NRows());  b = IdentityMatrix(1.);
    102   return SimpleMatrixOperation<T>::GausPiv(a,b);
     114  return SimpleMatrixOperation<T>::GausPiv(a,b,true);
    103115}
    104116
    105117/*! \ingroup TArray
    106     \fn GausPiv(TMatrix<T> const &,TMatrix<T> &)
     118    \fn GausPiv(TMatrix<T> const &,TMatrix<T> &, bool)
    107119    \brief Gauss pivoting on matrix \b A, doing the same operations
    108            on matrix \b B and return determinant of \b A.
    109     \sa SOPHYA::SimpleMatrixOperation::GausPiv(TMatrix<T>&,TMatrix<T>&)
     120           on matrix \b B.
     121    \param computedet = true : return the determinant of \b A
     122           (beware of over/underfloat), default is false.
     123    \return determinant if requested, or 1 if OK.
     124    \sa SOPHYA::SimpleMatrixOperation::GausPiv(TMatrix<T>&,TMatrix<T>&,bool)
    110125*/
    111126template <class T>
    112 inline T GausPiv(TMatrix<T> const & A,TMatrix<T> & B) {
     127inline T GausPiv(TMatrix<T> const & A,TMatrix<T> & B, bool computedet=false) {
    113128  TMatrix<T> a(A,false);
    114   return SimpleMatrixOperation<T>::GausPiv(a,B);
     129  return SimpleMatrixOperation<T>::GausPiv(a,B,computedet);
    115130}
    116131
Note: See TracChangeset for help on using the changeset viewer.