MiscMath.hpp

Go to the documentation of this file.
00001 #pragma ident "$Id: MiscMath.hpp 3327 2012-10-31 13:11:36Z btolman $"
00002 
00003 
00004 
00010 #ifndef GPSTK_MISCMATH_HPP
00011 #define GPSTK_MISCMATH_HPP
00012 
00013 //============================================================================
00014 //
00015 //  This file is part of GPSTk, the GPS Toolkit.
00016 //
00017 //  The GPSTk is free software; you can redistribute it and/or modify
00018 //  it under the terms of the GNU Lesser General Public License as published
00019 //  by the Free Software Foundation; either version 2.1 of the License, or
00020 //  any later version.
00021 //
00022 //  The GPSTk is distributed in the hope that it will be useful,
00023 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 //  GNU Lesser General Public License for more details.
00026 //
00027 //  You should have received a copy of the GNU Lesser General Public
00028 //  License along with GPSTk; if not, write to the Free Software Foundation,
00029 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00030 //  
00031 //  Copyright 2004, The University of Texas at Austin
00032 //
00033 //============================================================================
00034 
00035 //============================================================================
00036 //
00037 //This software developed by Applied Research Laboratories at the University of
00038 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00039 //Department of Defense. The U.S. Government retains all rights to use,
00040 //duplicate, distribute, disclose, or release this software. 
00041 //
00042 //Pursuant to DoD Directive 523024 
00043 //
00044 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00045 //                           release, distribution is unlimited.
00046 //
00047 //=============================================================================
00048 
00049 #include <cstring>   // for size_t
00050 #include <vector>
00051 #include "MathBase.hpp"
00052 #include "DebugUtils.hpp"
00053 
00054 namespace gpstk
00055 {
00058 
00069     template <class T>
00070     T LagrangeInterpolation(const std::vector<T>& X, const std::vector<T>& Y, T x)
00071     {
00072         GPSTK_ASSERT(X.size()==Y.size());
00073 
00074         T Yx(0.0);
00075         for(std::size_t i=0;i<X.size();i++)
00076         {
00077             if(x==X[i]) return Y[i];
00078 
00079             T Li(1.0);
00080             for(std::size_t j=0;j<X.size();j++)
00081             {
00082                 if(i!=j)  Li *= (x-X[j])/(X[i]-X[j]);
00083             }
00084             Yx += Li*Y[i];
00085         }
00086 
00087         return Yx;
00088 
00089     }  // end T LagrangeInterpolation(vector, vector, const T)
00090 
00091 
00096    template <class T>
00097    T LagrangeInterpolation(const std::vector<T>& X, const std::vector<T>& Y, const T& x, T& err)
00098    {
00099       std::size_t i,j,k;
00100       T y,del;
00101       std::vector<T> D,Q;
00102 
00103       err = T(0);
00104       k = X.size()/2;
00105       if(x == X[k]) return Y[k];
00106       if(x == X[k-1]) return Y[k-1];
00107       if(ABS(x-X[k-1]) < ABS(x-X[k])) k=k-1;
00108       for(i=0; i<X.size(); i++) {
00109          Q.push_back(Y[i]);
00110          D.push_back(Y[i]);
00111       }
00112       y = Y[k--];
00113       for(j=1; j<X.size(); j++) {
00114          for(i=0; i<X.size()-j; i++) {
00115             del = (Q[i+1]-D[i])/(X[i]-X[i+j]);
00116             D[i] = (X[i+j]-x)*del;
00117             Q[i] = (X[i]-x)*del;
00118          }
00119          err = (2*k < X.size()-j ? Q[k+1] : D[k--]);
00120          y += err;
00121       }
00122       return y;
00123    }  // end T LagrangeInterpolation(vector, vector, const T, T&)
00124 
00125    // The following is a
00126    // Straightforward implementation of Lagrange polynomial and its derivative
00127    // { all sums are over index=0,N-1; Xi is short for X[i]; Lp is dL/dx;
00128    //   y(x) is the function being approximated. }
00129    // y(x) = SUM[Li(x)*Yi]
00130    // Li(x) = PROD(j!=i)[x-Xj] / PROD(j!=i)[Xi-Xj]
00131    // dy(x)/dx = SUM[Lpi(x)*Yi]
00132    // Lpi(x) = SUM(k!=i){PROD(j!=i,j!=k)[x-Xj]} / PROD(j!=i)[Xi-Xj]
00133    // Define Pi = PROD(j!=i)[x-Xj], Di = PROD(j!=i)[Xi-Xj],
00134    // Qij = PROD(k!=i,k!=j)[x-Xk] and Si = SUM(j!=i)Qij.
00135    // then Li(x) = Pi/Di, and Lpi(x) = Si/Di.
00136    // Qij is symmetric, there are only N(N+1)/2 - N of them, so store them
00137    // in a vector of length N(N+1)/2, where Qij==Q[i+j*(j+1)/2] (ignore i=j).
00138 
00145    template <class T>
00146    void LagrangeInterpolation(const std::vector<T>& X, const std::vector<T>& Y, const T& x, T& y, T& dydx)
00147    {
00148       std::size_t i,j,k,N=X.size(),M;
00149       M = (N*(N+1))/2;
00150       std::vector<T> P(N,T(1)),Q(M,T(1)),D(N,T(1));
00151       for(i=0; i<N; i++) {
00152          for(j=0; j<N; j++) {
00153             if(i != j) {
00154                P[i] *= x-X[j];
00155                D[i] *= X[i]-X[j];
00156                if(i < j) {
00157 //std::cout << "Compute Q[" << i << "," << j << "=" << (i+(j*(j+1))/2) << "] = 1 ";
00158                   for(k=0; k<N; k++) {
00159                      if(k == i || k == j) continue;
00160 //std::cout << " * (x-X[" << k << "])";
00161                      Q[i+(j*(j+1))/2] *= (x-X[k]);
00162                   }
00163 //std::cout << " = " << Q[i+(j*(j+1))/2] << std::endl;
00164                }
00165             }
00166          }
00167       }
00168       y = dydx = T(0);
00169       for(i=0; i<N; i++) {
00170          y += Y[i]*(P[i]/D[i]);
00171          T S(0);
00172          for(k=0; k<N; k++) if(i != k) {
00173             if(k<i) S += Q[k+(i*(i+1))/2]/D[i];
00174             else    S += Q[i+(k*(k+1))/2]/D[i];
00175          }
00176          dydx += Y[i]*S;
00177       }
00178    }  // end void LagrangeInterpolation(vector, vector, const T, T&, T&)
00179 
00180 
00182    template <class T>
00183    T LagrangeInterpolating2ndDerivative( const std::vector<T>& pos,
00184                                          const std::vector<T>& val,
00185                                          T desiredPos )
00186    {
00187 
00188       int degree( pos.size() );
00189 
00190          // First, compute interpolation factors
00191       typedef std::vector< T > vectorType;
00192       std::vector< vectorType > delta( degree, vectorType(degree, 0.0) );
00193 
00194 
00195       for (int i = 0; i < degree; ++i)
00196       {
00197          for (int j = 0; j < degree; ++j)
00198          {
00199             if (j != i)
00200             {
00201                delta[i][j] = ( (desiredPos - pos[j]) / (pos[i] - pos[j]) );
00202             }
00203          }
00204       }
00205 
00206       double retVal(0.0);
00207 
00208       for( int i = 0; i < degree; ++i )
00209       {
00210          double sum( 0.0 );
00211 
00212          for( int m = 0; m < degree; ++m )
00213          {
00214 
00215             if( m != i )
00216             {
00217 
00218                double weight1( 1.0/(pos[i]-pos[m]) );
00219                double sum2( 0.0 );
00220 
00221                for( int j = 0; j < degree; ++j )
00222                {
00223 
00224                   if( (j != i) && (j != m) )
00225                   {
00226 
00227                      double weight2( 1.0/(pos[i]-pos[j]) );
00228 
00229                      for( int n = 0; n < degree; ++n )
00230                      {
00231 
00232                         if( (n != j) && (n != m) && (n != i) )
00233                         {
00234                            weight2 *= delta[i][n];
00235                         }
00236                      }
00237                      sum2 += weight2;
00238                   }
00239                }
00240 
00241                sum += sum2*weight1;
00242             }
00243 
00244          }
00245 
00246          retVal += val[i] * sum;
00247       }
00248 
00249       return retVal;
00250 
00251    }  // End of 'lagrangeInterpolating2ndDerivative()'
00252 
00253 
00255    template <class T>
00256    T RSS (T aa, T bb, T cc)
00257    {
00258       T a(ABS(aa)), b(ABS(bb)), c(ABS(cc));
00259       if ( (a > b) && (a > c) )
00260          return a * SQRT(1 + (b/a)*(b/a) + (c/a)*(c/a));
00261       if ( (b > a) && (b > c) )
00262          return b * SQRT(1 + (a/b)*(a/b) + (c/b)*(c/b));
00263       if ( (c > b) && (c > a) )
00264          return c * SQRT(1 + (b/c)*(b/c) + (a/c)*(a/c));
00265 
00266       if (a == b)
00267       {
00268          if (b == c)
00269             return a * SQRT(T(3));
00270          a *= SQRT(T(2));
00271          if (a > c)
00272             return a * SQRT(1 + (c/a)*(c/a));
00273          else
00274             return c * SQRT(1 + (a/c)*(a/c));
00275       }
00276       if (a == c)
00277       {
00278          a *= SQRT(T(2));
00279          if (a > b)
00280             return a * SQRT(1 + (b/a)*(b/a));
00281          else
00282             return b * SQRT(1 + (a/b)*(a/b));
00283       }
00284       if (b == c)
00285       {
00286          b *= SQRT(T(2));
00287          if (b > a)
00288             return b * SQRT(1 + (a/b)*(a/b));
00289          else
00290             return a * SQRT(1 + (b/a)*(b/a));
00291       }
00292 
00293       return T(0);
00294    }
00295 
00297    template <class T>
00298    T RSS (T aa, T bb)
00299    {
00300       return RSS(aa,bb,T(0));
00301    }
00302 
00303  
00305    template <class T>
00306    T RSS (T aa, T bb, T cc, T dd)
00307    {
00308 #define swapValues(x,y) \
00309    { T temporalStorage; \
00310    temporalStorage = x; x = y; y = temporalStorage; }
00311 
00312       T a(ABS(aa)), b(ABS(bb)), c(ABS(cc)), d(ABS(dd));
00313 
00314       // For numerical reason, let's just put the biggest in "a" (we are not sorting)
00315       if (a < b) std::swap(a,b);
00316       if (a < c) swapValues(a,c);
00317       if (a < d) swapValues(a,d);
00318 
00319       return a * SQRT(1 + (b/a)*(b/a) + (c/a)*(c/a) + (d/a)*(d/a));
00320    }
00321 
00322 
00323    inline double Round(double x)
00324    {
00325       return double(std::floor(x+0.5));
00326    }
00328 
00329 }  // namespace gpstk
00330 
00331 #endif

Generated on Sat May 18 03:31:06 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1