Sacado_PCE_HermiteImp.hpp

Go to the documentation of this file.
00001 // $Id: Sacado_PCE_HermiteImp.hpp,v 1.2 2008/01/22 17:56:14 etphipp Exp $ 
00002 // $Source: /space/CVS/Trilinos/packages/sacado/src/pce/Sacado_PCE_HermiteImp.hpp,v $ 
00003 // @HEADER
00004 // ***********************************************************************
00005 // 
00006 //                           Sacado Package
00007 //                 Copyright (2006) Sandia Corporation
00008 // 
00009 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00010 // license for use of this work by or on behalf of the U.S. Government.
00011 // 
00012 // This library is free software; you can redistribute it and/or modify
00013 // it under the terms of the GNU Lesser General Public License as
00014 // published by the Free Software Foundation; either version 2.1 of the
00015 // License, or (at your option) any later version.
00016 //  
00017 // This library is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //  
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
00027 // (etphipp@sandia.gov).
00028 // 
00029 // ***********************************************************************
00030 // @HEADER
00031 
00032 #include "Teuchos_TestForException.hpp"
00033 #include "Sacado_ConfigDefs.h"
00034 #include "Sacado_DynamicArrayTraits.hpp"
00035 #include <ostream>  // for std::ostream
00036 
00037 namespace Sacado {
00038 namespace PCE {
00039 
00040 // Initialize static data
00041 template <typename T> typename Hermite<T>::ws_type Hermite<T>::workspace(1);
00042 
00043 template <typename T> 
00044 Hermite<T>::HermiteData::
00045 HermiteData() :
00046   coeff_(NULL), deg_(-1), len_(0) 
00047 {
00048 }
00049 
00050 template <typename T> 
00051 Hermite<T>::HermiteData::
00052 HermiteData(const T& x) :
00053   coeff_(), deg_(0), len_(1) 
00054 {
00055   coeff_ = Sacado::ds_array<T>::get_and_fill(len_);
00056   coeff_[0] = x;
00057 }
00058 
00059 template <typename T> 
00060 Hermite<T>::HermiteData::
00061 HermiteData(unsigned int d, const T& x) :
00062   coeff_(), deg_(d), len_(d+1) 
00063 {
00064   coeff_ = Sacado::ds_array<T>::get_and_fill(len_);
00065   coeff_[0] = x;
00066 }
00067 
00068 template <typename T> 
00069 Hermite<T>::HermiteData::
00070 HermiteData(unsigned int d) :
00071   coeff_(), deg_(d), len_(d+1) 
00072 {
00073   coeff_ = Sacado::ds_array<T>::get_and_fill(len_);
00074 }
00075 
00076 template <typename T> 
00077 Hermite<T>::HermiteData::
00078 HermiteData(unsigned int d, unsigned int l) :
00079   coeff_(), deg_(d), len_(l) 
00080 {
00081   coeff_ = Sacado::ds_array<T>::get_and_fill(len_);
00082 }
00083 
00084 template <typename T> 
00085 Hermite<T>::HermiteData::
00086 HermiteData(const typename Hermite<T>::HermiteData& x) :
00087   coeff_(), deg_(x.deg_), len_(x.deg_+1) 
00088 {
00089   coeff_ = Sacado::ds_array<T>::get_and_fill(x.coeff_, len_);
00090 }
00091 
00092 template <typename T> 
00093 Hermite<T>::HermiteData::
00094 ~HermiteData()
00095 {
00096   if (len_ > 0)
00097     Sacado::ds_array<T>::destroy_and_release(coeff_, len_);
00098 }
00099 
00100 template <typename T> 
00101 typename Hermite<T>::HermiteData&
00102 Hermite<T>::HermiteData::
00103 operator=(const typename Hermite<T>::HermiteData& x) 
00104 {
00105   if (len_ < x.deg_+1) {
00106     Sacado::ds_array<T>::destroy_and_release(coeff_, len_);
00107     len_ = x.deg_+1;
00108     deg_ = x.deg_;
00109     coeff_ = Sacado::ds_array<T>::get_and_fill(x.coeff_, len_);
00110   }
00111   else {
00112     deg_ = x.deg_;
00113     Sacado::ds_array<T>::copy(x.coeff_, coeff_, deg_+1);
00114   }
00115   
00116   return *this;
00117 }
00118 
00119 template <typename T> 
00120 Hermite<T>::
00121 Hermite() :
00122   th(new HermiteData)
00123 {
00124 }
00125 
00126 template <typename T> 
00127 Hermite<T>::
00128 Hermite(const T& x) :
00129   th(new HermiteData(x))
00130 {
00131 }
00132 
00133 template <typename T> 
00134 Hermite<T>::
00135 Hermite(unsigned int d, const T& x) :
00136   th(new HermiteData(d, x))
00137 {
00138 }
00139 
00140 template <typename T> 
00141 Hermite<T>::
00142 Hermite(unsigned int d) :
00143   th(new HermiteData(d))
00144 {
00145 }
00146 
00147 template <typename T> 
00148 Hermite<T>::
00149 Hermite(const Hermite<T>& x) :
00150   th(x.th)
00151 {
00152 }
00153 
00154 template <typename T> 
00155 Hermite<T>::
00156 ~Hermite()
00157 {
00158 }
00159 
00160 template <typename T> 
00161 void
00162 Hermite<T>::
00163 resize(unsigned int d, bool keep_coeffs)
00164 {
00165   if (d+1 > length()) {
00166     Sacado::Handle<HermiteData> h(new HermiteData(d));
00167     if (keep_coeffs)
00168       Sacado::ds_array<T>::copy(th->coeff_, h->coeff_, th->deg_+1);
00169     th = h;
00170   }
00171   else {
00172     th.makeOwnCopy();
00173     if (!keep_coeffs)
00174       Sacado::ds_array<T>::zero(coeff(), degree()+1);
00175     th->deg_ = d;
00176   }
00177 }
00178 
00179 template <typename T> 
00180 void
00181 Hermite<T>::
00182 reserve(unsigned int d)
00183 {
00184   if (d+1 > length()) {
00185     Sacado::Handle<HermiteData> h(new HermiteData(th->deg_,d+1));
00186     Sacado::ds_array<T>::copy(th->coeff_, h->coeff_, th->deg_+1);
00187     th = h;
00188   }
00189 }
00190 
00191 template <typename T> 
00192 void
00193 Hermite<T>::
00194 initWorkspace(unsigned int d)
00195 {
00196   workspace.resize(d+1);
00197 }
00198 
00199 template <typename T> 
00200 StandardPoly<T>
00201 Hermite<T>::
00202 toStandardBasis() const
00203 {
00204   const typename Hermite<T>::ws_type::tp_type& Cijk = 
00205     Hermite<T>::workspace.getTripleProduct();
00206   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
00207     Cijk.getBasis();
00208   return basis.toStandardBasis(th->coeff_, th->deg_+1);
00209 }
00210 
00211 template <typename T> 
00212 Hermite<T>& 
00213 Hermite<T>::
00214 operator=(const T& val) 
00215 {
00216   th.makeOwnCopy();
00217 
00218   if (th->len_ == 0) {
00219     th->len_ = 1;
00220     th->deg_ = 0;
00221     th->coeff_ = Sacado::ds_array<T>::get_and_fill(th->len_);
00222   }
00223 
00224   th->coeff_[0] = val;
00225   Sacado::ds_array<T>::zero(th->coeff_+1, th->deg_);
00226 
00227   return *this;
00228 }
00229 
00230 template <typename T> 
00231 Hermite<T>& 
00232 Hermite<T>::
00233 operator=(const Hermite<T>& x) 
00234 {
00235   th = x.th;
00236   return *this;
00237 }
00238 
00239 template <typename T> 
00240 Hermite<T>
00241 Hermite<T>::
00242 operator+() const
00243 {
00244   return *this;
00245 }
00246 
00247 template <typename T> 
00248 Hermite<T> 
00249 Hermite<T>::
00250 operator-() const
00251 {
00252   Hermite<T> x;
00253   x.th->deg_ = th->deg_;
00254   x.th->len_ = th->deg_+1;
00255   x.th->coeff_ = Sacado::ds_array<T>::get_and_fill(x.th->len_);
00256   for (unsigned int i=0; i<=th->deg_; i++)
00257     x.th->coeff_[i] = -th->coeff_[i];
00258 
00259   return x;
00260 }
00261 
00262 template <typename T> 
00263  Hermite<T>& 
00264 Hermite<T>::
00265 operator+=(const T& val)
00266 {
00267   th.makeOwnCopy();
00268 
00269   th->coeff_[0] += val;
00270 
00271   return *this;
00272 }
00273 
00274 template <typename T> 
00275 Hermite<T>& 
00276 Hermite<T>::
00277 operator-=(const T& val)
00278 {
00279   th.makeOwnCopy();
00280 
00281   th->coeff_[0] -= val;
00282 
00283   return *this;
00284 }
00285 
00286 template <typename T> 
00287 Hermite<T>& 
00288 Hermite<T>::
00289 operator*=(const T& val)
00290 {
00291   th.makeOwnCopy();
00292 
00293   for (unsigned int i=0; i<=th->deg_; i++)
00294     th->coeff_[i] *= val;
00295 
00296   return *this;
00297 }
00298 
00299 template <typename T> 
00300 Hermite<T>& 
00301 Hermite<T>::
00302 operator/=(const T& val)
00303 {
00304   th.makeOwnCopy();
00305 
00306   for (unsigned int i=0; i<=th->deg_; i++)
00307     th->coeff_[i] /= val;
00308 
00309   return *this;
00310 }
00311 
00312 template <typename T> 
00313 Hermite<T>& 
00314 Hermite<T>::
00315 operator+=(const Hermite<T>& x)
00316 {
00317   th.makeOwnCopy();
00318 
00319   unsigned int d = degree();
00320   unsigned int xd = x.degree();
00321   unsigned int dmin = xd < d ? xd : d;
00322 
00323   unsigned int l = xd + 1;
00324   bool need_resize = l > length();
00325   T* c;
00326   if (need_resize) {
00327     c = Sacado::ds_array<T>::get_and_fill(l);
00328     for (unsigned int i=0; i<=d; i++)
00329       c[i] = fastAccessCoeff(i);
00330   }
00331   else
00332     c = th->coeff_;
00333   T* xc = x.th->coeff_;
00334 
00335   for (unsigned int i=0; i<=dmin; i++)
00336     c[i] += xc[i];
00337   if (th->deg_ < xd) {
00338     for (unsigned int i=d+1; i<=xd; i++)
00339       c[i] = xc[i];
00340     th->deg_ = xd;
00341   }
00342 
00343   if (need_resize) {
00344     Sacado::ds_array<T>::destroy_and_release(th->coeff_, th->len_);
00345     th->len_ = l;
00346     th->coeff_ = c;
00347   }
00348 
00349   return *this;
00350 }
00351 
00352 template <typename T> 
00353 Hermite<T>& 
00354 Hermite<T>::
00355 operator-=(const Hermite<T>& x)
00356 {
00357   th.makeOwnCopy();
00358 
00359   unsigned int d = degree();
00360   unsigned int xd = x.degree();
00361   unsigned int dmin = xd < d ? xd : d;
00362 
00363   unsigned int l = xd + 1;
00364   bool need_resize = l > length();
00365   T* c;
00366   if (need_resize) {
00367     c = Sacado::ds_array<T>::get_and_fill(l);
00368     for (unsigned int i=0; i<=d; i++)
00369       c[i] = fastAccessCoeff(i);
00370   }
00371   else
00372     c = th->coeff_;
00373   T* xc = x.th->coeff_;
00374 
00375   for (unsigned int i=0; i<=dmin; i++)
00376     c[i] -= xc[i];
00377   if (d < xd) {
00378     for (unsigned int i=d+1; i<=xd; i++)
00379       c[i] = -xc[i];
00380     th->deg_ = xd;
00381   }
00382 
00383   if (need_resize) {
00384     Sacado::ds_array<T>::destroy_and_release(th->coeff_, th->len_);
00385     th->len_ = l;
00386     th->coeff_ = c;
00387   }
00388 
00389   return *this;
00390 }
00391 
00392 template <typename T> 
00393 Hermite<T>& 
00394 Hermite<T>::
00395 operator*=(const Hermite<T>& x)
00396 {
00397 #ifdef SACADO_DEBUG
00398   const char* func = "Sacado::PCE::Hermite::operator*=()";
00399   TEST_FOR_EXCEPTION((x.degree() != degree()) && (x.degree() != 0) && 
00400          (degree() != 0), std::logic_error,
00401          func << ":  Attempt to assign with incompatible degrees");
00402 #endif
00403   unsigned int d = degree();
00404   unsigned int xd = x.degree();
00405   
00406   T* c = th->coeff_; 
00407   T* xc = x.th->coeff_;
00408   
00409   if (d > 0 && xd > 0) {
00410 #ifdef SACADO_DEBUG
00411     TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < d+1, std::logic_error,
00412            func << ":  Workspace size (" 
00413            << Hermite<T>::workspace.size() 
00414            << ") is too small for computation (" << d+1 
00415            << " needed).");
00416 #endif
00417     Sacado::Handle<HermiteData> h(new HermiteData(d));
00418     T* cc = h->coeff_;
00419     T tmp;
00420     const typename Hermite<T>::ws_type::tp_type& Cijk = 
00421       workspace.getTripleProduct();
00422 
00423     for (unsigned int k=0; k<=d; k++) {
00424       tmp = T(0.0);
00425       for (unsigned int i=0; i<=d; i++) {
00426   for (unsigned int j=0; j<=xd; j++)
00427     tmp += Cijk.value(i,j,k)*c[i]*xc[j];
00428       }
00429       cc[k] = tmp / Cijk.norm_squared(k);
00430     }
00431     th = h;
00432   }
00433   else if (d > 0) {
00434     th.makeOwnCopy();
00435     for (unsigned int i=0; i<=d; i++)
00436       c[i] = c[i]*xc[0];
00437   }
00438   else  {
00439     if (length() < xd+1) {
00440       Sacado::Handle<HermiteData> h(new HermiteData(xd));
00441       T* cc = h->coeff_;
00442       for (unsigned int i=0; i<=xd; i++)
00443   cc[i] = c[0]*xc[i];
00444       th = h;
00445     }
00446     else {
00447       th.makeOwnCopy();
00448       for (unsigned int i=d; i>=0; i--)
00449   c[i] = c[0]*xc[i];
00450     }
00451   }
00452 
00453   return *this;
00454 }
00455 
00456 template <typename T> 
00457 Hermite<T>& 
00458 Hermite<T>::
00459 operator/=(const Hermite<T>& x)
00460 {
00461 #ifdef SACADO_DEBUG
00462   const char* func = "Sacado::PCE::Hermite::operator/=()";
00463   TEST_FOR_EXCEPTION((x.degree() != degree()) && (x.degree() != 0) && 
00464          (degree() != 0), std::logic_error,
00465          func << ":  Attempt to assign with incompatible degrees");
00466 #endif
00467 
00468   unsigned int d = degree();
00469   unsigned int xd = x.degree();
00470   
00471   T* c = th->coeff_; 
00472   T* xc = x.th->coeff_;
00473   
00474   if (xd > 0) {
00475     unsigned int dd = (xd > d) ? xd : d;
00476 
00477 #ifdef SACADO_DEBUG
00478     TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dd+1, std::logic_error,
00479            func << ":  Workspace size (" << 
00480            Hermite<T>::workspace.size() 
00481            << ") is too small for computation (" << dd+1 
00482            << " needed).");
00483 #endif
00484 
00485     Sacado::Handle<HermiteData> h(new HermiteData(dd));
00486     T* cc = h->coeff_;
00487 
00488     const typename Hermite<T>::ws_type::matrix_type& A = workspace.getMatrix();
00489     const typename Hermite<T>::ws_type::matrix_type& b = workspace.getRHS();
00490     const typename Hermite<T>::ws_type::tp_type& Cijk = 
00491       workspace.getTripleProduct();
00492     
00493     // Fill A
00494     for (unsigned int i=0; i<=dd; i++) {
00495       for (unsigned int j=0; j<=dd; j++) {
00496   A(i,j) = 0.0;
00497   for (unsigned int k=0; k<=xd; k++) {
00498     A(i,j) += Cijk.value(i,j,k)*xc[k];
00499   }
00500   A(i,j) /= Cijk.norm_squared(i);
00501       }
00502     }
00503     
00504     // Fill b
00505     for (unsigned int i=0; i<=d; i++)
00506       b(i,0) = c[i];
00507     for (unsigned int i=d+1; i<=dd; i++)
00508       b(i,0) = T(0.0);
00509 
00510     // Solve system
00511     int info = Hermite<T>::workspace.solve(dd+1, 1);
00512 
00513 #ifdef SACADO_DEBUG
00514     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
00515            func << ":  Argument " << info 
00516                 << " for solve had illegal value");
00517     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
00518            func << ":  Diagonal entry " << info 
00519                 << " in LU factorization is exactly zero");
00520 #endif
00521 
00522     // Get coefficients
00523     for (unsigned int i=0; i<=dd; i++)
00524       cc[i] = b(i,0);
00525 
00526     th = h;
00527   }
00528   else {
00529     th.makeOwnCopy();
00530     for (unsigned int i=0; i<=d; i++)
00531       c[i] = c[i]/xc[0];
00532   }
00533 
00534   return *this;
00535 }
00536 
00537 template <typename T>
00538 void
00539 Hermite<T>::
00540 resizeCoeffs(unsigned int len)
00541 {
00542   if (th->coeff_)
00543     Sacado::ds_array<T>::destroy_and_release(th->coeff_, th->len_);
00544   th->len_ = len;
00545   th->coeff_ = Sacado::ds_array<T>::get_and_fill(th->len_);
00546 }
00547 
00548 template <typename T>
00549 Hermite<T>
00550 operator+(const Hermite<T>& a, 
00551     const Hermite<T>& b)
00552 {
00553 #ifdef SACADO_DEBUG
00554   const char* func = "Sacado::PCE::Hermite::operator+()";
00555   TEST_FOR_EXCEPTION((a.degree() != b.degree()) && (a.degree() != 0) && 
00556          (b.degree() != 0), 
00557          std::logic_error,
00558          func << ":  Arguments have incompatible degrees!");
00559 #endif
00560 
00561   unsigned int da = a.degree();
00562   unsigned int db = b.degree();
00563   unsigned int dc = da > db ? da : db;
00564 
00565   Hermite<T> c(dc);
00566   const T* ca = a.coeff();
00567   const T* cb = b.coeff();
00568   T* cc = c.coeff();
00569 
00570   if (da > 0 && db > 0) {
00571     for (unsigned int i=0; i<=dc; i++)
00572       cc[i] = ca[i] + cb[i];
00573   }
00574   else if (da > 0) {
00575     cc[0] = ca[0] + cb[0];
00576     for (unsigned int i=1; i<=dc; i++)
00577       cc[i] = ca[i];
00578   }
00579   else if (db >= 0) {
00580     cc[0] = ca[0] + cb[0];
00581     for (unsigned int i=1; i<=dc; i++)
00582       cc[i] = cb[i];
00583   }
00584 
00585   return c;
00586 }
00587 
00588 template <typename T>
00589 Hermite<T>
00590 operator+(const T& a, const Hermite<T>& b)
00591 {
00592   unsigned int dc = b.degree();
00593 
00594   Hermite<T> c(dc);
00595   const T* cb = b.coeff();
00596   T* cc = c.coeff();
00597 
00598   cc[0] = a + cb[0];
00599   for (unsigned int i=1; i<=dc; i++)
00600     cc[i] = cb[i];
00601 
00602   return c;
00603 }
00604 
00605 template <typename T>
00606 Hermite<T>
00607 operator+(const Hermite<T>& a, const T& b)
00608 {
00609   unsigned int dc = a.degree();
00610 
00611   Hermite<T> c(dc);
00612   const T* ca = a.coeff();
00613   T* cc = c.coeff();
00614 
00615   cc[0] = ca[0] + b;
00616   for (unsigned int i=1; i<=dc; i++)
00617     cc[i] = ca[i];
00618 
00619   return c;
00620 }
00621 
00622 template <typename T>
00623 Hermite<T>
00624 operator-(const Hermite<T>& a, 
00625     const Hermite<T>& b)
00626 {
00627 #ifdef SACADO_DEBUG
00628   const char* func = "Sacado::PCE::Hermite::operator-()";
00629   TEST_FOR_EXCEPTION((a.degree() != b.degree()) && (a.degree() != 0) && 
00630          (b.degree() != 0), 
00631          std::logic_error,
00632          func << ":  Arguments have incompatible degrees!");
00633 #endif
00634 
00635   unsigned int da = a.degree();
00636   unsigned int db = b.degree();
00637   unsigned int dc = da > db ? da : db;
00638 
00639   Hermite<T> c(dc);
00640   const T* ca = a.coeff();
00641   const T* cb = b.coeff();
00642   T* cc = c.coeff();
00643 
00644   if (da > 0 && db > 0) {
00645     for (unsigned int i=0; i<=dc; i++)
00646       cc[i] = ca[i] - cb[i];
00647   }
00648   else if (da > 0) {
00649     cc[0] = ca[0] - cb[0];
00650     for (unsigned int i=1; i<=dc; i++)
00651       cc[i] = ca[i];
00652   }
00653   else if (db >= 0) {
00654     cc[0] = ca[0] - cb[0];
00655     for (unsigned int i=1; i<=dc; i++)
00656       cc[i] = -cb[i];
00657   }
00658 
00659   return c;
00660 }
00661 
00662 template <typename T>
00663 Hermite<T>
00664 operator-(const T& a, const Hermite<T>& b)
00665 {
00666   unsigned int dc = b.degree();
00667 
00668   Hermite<T> c(dc);
00669   const T* cb = b.coeff();
00670   T* cc = c.coeff();
00671 
00672   cc[0] = a - cb[0];
00673   for (unsigned int i=1; i<=dc; i++)
00674     cc[i] = -cb[i];
00675 
00676   return c;
00677 }
00678 
00679 template <typename T>
00680 Hermite<T>
00681 operator-(const Hermite<T>& a, const T& b)
00682 {
00683   unsigned int dc = a.degree();
00684 
00685   Hermite<T> c(dc);
00686   const T* ca = a.coeff();
00687   T* cc = c.coeff();
00688 
00689   cc[0] = ca[0] - b;
00690   for (unsigned int i=1; i<=dc; i++)
00691     cc[i] = ca[i];
00692 
00693   return c;
00694 }
00695 
00696 template <typename T>
00697 Hermite<T>
00698 operator*(const Hermite<T>& a, 
00699     const Hermite<T>& b)
00700 {
00701 #ifdef SACADO_DEBUG
00702   const char* func = "Sacado::PCE::Hermite::operator*()";
00703   TEST_FOR_EXCEPTION((a.degree() != b.degree()) && (a.degree() != 0) && 
00704          (b.degree() != 0), 
00705          std::logic_error,
00706          func << ":  Arguments have incompatible degrees!");
00707 #endif
00708 
00709   unsigned int da = a.degree();
00710   unsigned int db = b.degree();
00711   unsigned int dc = da > db ? da : db;
00712 
00713   Hermite<T> c(dc);
00714   const T* ca = a.coeff();
00715   const T* cb = b.coeff();
00716   T* cc = c.coeff();
00717 
00718   if (da > 0 && db > 0) {
00719 #ifdef SACADO_DEBUG
00720     TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
00721            func << ":  Workspace size (" 
00722            << Hermite<T>::workspace.size() 
00723            << ") is too small for computation (" << dc+1 
00724            << " needed).");
00725 #endif
00726 
00727     T tmp;
00728     const typename Hermite<T>::ws_type::tp_type& Cijk = 
00729       Hermite<T>::workspace.getTripleProduct();
00730 
00731     for (unsigned int k=0; k<=dc; k++) {
00732       tmp = T(0.0);
00733       for (unsigned int i=0; i<=da; i++) {
00734   for (unsigned int j=0; j<=db; j++)
00735     tmp += Cijk.value(i,j,k)*ca[i]*cb[j];
00736       }
00737       cc[k] = tmp / Cijk.norm_squared(k);
00738     }
00739   }
00740   else if (da > 0) {
00741     for (unsigned int i=0; i<=dc; i++)
00742       cc[i] = ca[i]*cb[0];
00743   }
00744   else if (db >= 0) {
00745     for (unsigned int i=0; i<=dc; i++)
00746       cc[i] = ca[0]*cb[i];
00747   }
00748 
00749   return c;
00750 }
00751 
00752 template <typename T>
00753 Hermite<T>
00754 operator*(const T& a, const Hermite<T>& b)
00755 {
00756   unsigned int dc = b.degree();
00757 
00758   Hermite<T> c(dc);
00759   const T* cb = b.coeff();
00760   T* cc = c.coeff();
00761 
00762   for (unsigned int i=0; i<=dc; i++)
00763     cc[i] = a*cb[i];
00764 
00765   return c;
00766 }
00767 
00768 template <typename T>
00769 Hermite<T>
00770 operator*(const Hermite<T>& a, const T& b)
00771 {
00772   unsigned int dc = a.degree();
00773 
00774   Hermite<T> c(dc);
00775   const T* ca = a.coeff();
00776   T* cc = c.coeff();
00777 
00778   for (unsigned int i=0; i<=dc; i++)
00779     cc[i] = ca[i]*b;
00780 
00781   return c;
00782 }
00783 
00784 template <typename T>
00785 Hermite<T>
00786 operator/(const Hermite<T>& a, 
00787     const Hermite<T>& b)
00788 {
00789 #ifdef SACADO_DEBUG
00790   const char* func = "Sacado::PCE::Hermite::operator/()";
00791   TEST_FOR_EXCEPTION((a.degree() != b.degree()) && (a.degree() != 0) && 
00792          (b.degree() != 0), 
00793          std::logic_error,
00794          func << ":  Arguments have incompatible degrees!");
00795 #endif
00796 
00797   unsigned int da = a.degree();
00798   unsigned int db = b.degree();
00799   unsigned int dc = da > db ? da : db;
00800 
00801   Hermite<T> c(dc);
00802   const T* ca = a.coeff();
00803   const T* cb = b.coeff();
00804   T* cc = c.coeff();
00805 
00806   if (db > 0) {
00807 
00808 #ifdef SACADO_DEBUG
00809     TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
00810            func << ":  Workspace size (" 
00811            << Hermite<T>::workspace.size() 
00812            << ") is too small for computation (" << dc+1 
00813            << " needed).");
00814 #endif
00815 
00816     typename Hermite<T>::ws_type::matrix_type& A = 
00817       Hermite<T>::workspace.getMatrix();
00818     typename Hermite<T>::ws_type::matrix_type& b = 
00819       Hermite<T>::workspace.getRHS();
00820     const typename Hermite<T>::ws_type::tp_type& Cijk = 
00821       Hermite<T>::workspace.getTripleProduct();
00822     
00823     // Fill A
00824     for (unsigned int i=0; i<=dc; i++) {
00825       for (unsigned int j=0; j<=dc; j++) {
00826   A(i,j) = 0.0;
00827   for (unsigned int k=0; k<=db; k++) {
00828     A(i,j) += Cijk.value(i,j,k)*cb[k];
00829   }
00830   A(i,j) /= Cijk.norm_squared(i);
00831       }
00832     }
00833     
00834     // Fill b
00835     for (unsigned int i=0; i<=da; i++)
00836       b(i,0) = ca[i];
00837     for (unsigned int i=da+1; i<=dc; i++)
00838       b(i,0) = T(0.0);
00839 
00840     // Solve system
00841     int info = Hermite<T>::workspace.solve(dc+1, 1);
00842 
00843 #ifdef SACADO_DEBUG
00844     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
00845            func << ":  Argument " << info 
00846                 << " for solve had illegal value");
00847     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
00848            func << ":  Diagonal entry " << info 
00849                 << " in LU factorization is exactly zero");
00850 #endif
00851 
00852     // Get coefficients
00853     for (unsigned int i=0; i<=dc; i++)
00854       cc[i] = b(i,0);
00855   }
00856   else {
00857     for (unsigned int i=0; i<=da; i++)
00858       cc[i] = ca[i]/cb[0];
00859   }
00860 
00861   return c;
00862 }
00863 
00864 template <typename T>
00865 Hermite<T>
00866 operator/(const T& a, const Hermite<T>& b)
00867 {
00868   unsigned int dc = b.degree();
00869 
00870   Hermite<T> c(dc);
00871   const T* cb = b.coeff();
00872   T* cc = c.coeff();
00873 
00874   if (dc > 0) {
00875 #ifdef SACADO_DEBUG
00876     const char* func = "Sacado::PCE::Hermite::operator/()";
00877     TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
00878            func << ":  Workspace size (" 
00879            << Hermite<T>::workspace.size() 
00880            << ") is too small for computation (" << dc+1 
00881            << " needed).");
00882 #endif
00883 
00884     typename Hermite<T>::ws_type::matrix_type& A = 
00885       Hermite<T>::workspace.getMatrix();
00886     typename Hermite<T>::ws_type::matrix_type& b = 
00887       Hermite<T>::workspace.getRHS();
00888     const typename Hermite<T>::ws_type::tp_type& Cijk = 
00889       Hermite<T>::workspace.getTripleProduct();
00890     
00891     // Fill A
00892     for (unsigned int i=0; i<=dc; i++) {
00893       for (unsigned int j=0; j<=dc; j++) {
00894   A(i,j) = 0.0;
00895   for (unsigned int k=0; k<=dc; k++) {
00896     A(i,j) += Cijk.value(i,j,k)*cb[k];
00897   }
00898   A(i,j) /= Cijk.norm_squared(i);
00899       }
00900     }
00901 
00902     // Fill b
00903     b(0,0) = a;
00904     for (unsigned int i=1; i<=dc; i++)
00905       b(i,0) = T(0.0);
00906 
00907     // Solve system
00908     int info = Hermite<T>::workspace.solve(dc+1, 1);
00909 
00910 #ifdef SACADO_DEBUG
00911     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
00912            func << ":  Argument " << info 
00913                 << " for solve had illegal value");
00914     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
00915            func << ":  Diagonal entry " << info 
00916                 << " in LU factorization is exactly zero");
00917 #endif
00918 
00919     // Get coefficients
00920     for (unsigned int i=0; i<=dc; i++)
00921       cc[i] = b(i,0);
00922   }
00923   else 
00924     cc[0] = a / cb[0];
00925 
00926   return c;
00927 }
00928 
00929 template <typename T>
00930 Hermite<T>
00931 operator/(const Hermite<T>& a, const T& b)
00932 {
00933   unsigned int dc = a.degree();
00934 
00935   Hermite<T> c(dc);
00936   const T* ca = a.coeff();
00937   T* cc = c.coeff();
00938 
00939   for (unsigned int i=0; i<=dc; i++)
00940     cc[i] = ca[i]/b;
00941 
00942   return c;
00943 }
00944 
00945 template <typename T>
00946 Hermite<T>
00947 exp(const Hermite<T>& a)
00948 {
00949   unsigned int dc = a.degree();
00950 
00951 #ifdef SACADO_DEBUG
00952   const char* func = "Sacado::PCE::Hermite::exp()";
00953   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
00954          func << ":  Workspace size (" 
00955          << Hermite<T>::workspace.size() 
00956          << ") is too small for computation (" << dc+1 
00957          << " needed).");
00958 #endif
00959 
00960   Hermite<T> c(dc);
00961   const T* ca = a.coeff();
00962   T* cc = c.coeff();
00963 
00964   typename Hermite<T>::ws_type::matrix_type& A = 
00965     Hermite<T>::workspace.getMatrix();
00966   typename Hermite<T>::ws_type::matrix_type& b = 
00967     Hermite<T>::workspace.getRHS();
00968   const typename Hermite<T>::ws_type::tp_type& Cijk = 
00969     Hermite<T>::workspace.getTripleProduct();
00970   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
00971     Cijk.getBasis();
00972 
00973   // Fill A and b
00974   for (unsigned int i=1; i<=dc; i++) {
00975     for (unsigned int j=1; j<=dc; j++) {
00976       A(i-1,j-1) = 0.0;
00977       for (unsigned int k=1; k<=dc; k++) {
00978   if (i+j >= k) {
00979     A(i-1,j-1) += Cijk.value(i-1,j,k-1)*basis.derivCoeff(k)*ca[k];
00980   }
00981       }
00982       A(i-1,j-1) /= Cijk.norm_squared(i-1)*basis.derivCoeff(i);
00983     }
00984     A(i-1,i-1) -= T(1.0);
00985     b(i-1,0) = -ca[i];
00986   }
00987 
00988   // Solve system
00989   int info = Hermite<T>::workspace.solve(dc, 1);
00990 
00991 #ifdef SACADO_DEBUG
00992     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
00993            func << ":  Argument " << info 
00994                 << " for solve had illegal value");
00995     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
00996            func << ":  Diagonal entry " << info 
00997                 << " in LU factorization is exactly zero");
00998 #endif
00999 
01000   // Compute degree-0 coefficient
01001   T s = basis.getBasisPoly(0).coeff(0) * ca[0];
01002   T t = T(1.0);
01003   for (unsigned int i=1; i<=dc; i++) {
01004     s += basis.getBasisPoly(i).coeff(0) * ca[i];
01005     t += basis.getBasisPoly(i).coeff(0) * b(i-1,0);
01006   }
01007   s = std::exp(s);
01008   cc[0] = (s/t);
01009 
01010   // Compute remaining coefficients
01011   for (unsigned int i=1; i<=dc; i++)
01012     cc[i] = b(i-1,0) * cc[0];
01013 
01014   cc[0] /= basis.getBasisPoly(0).coeff(0);
01015 
01016   return c;
01017 }
01018 
01019 template <typename T>
01020 Hermite<T>
01021 log(const Hermite<T>& a)
01022 {
01023   unsigned int dc = a.degree();
01024 
01025 #ifdef SACADO_DEBUG
01026   const char* func = "Sacado::PCE::Hermite::exp()";
01027   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
01028          func << ":  Workspace size (" 
01029          << Hermite<T>::workspace.size() 
01030          << ") is too small for computation (" << dc+1 
01031          << " needed).");
01032 #endif
01033 
01034   Hermite<T> c(dc);
01035   const T* ca = a.coeff();
01036   T* cc = c.coeff();
01037 
01038   typename Hermite<T>::ws_type::matrix_type& A = 
01039     Hermite<T>::workspace.getMatrix();
01040   typename Hermite<T>::ws_type::matrix_type& b = 
01041     Hermite<T>::workspace.getRHS();
01042   const typename Hermite<T>::ws_type::tp_type& Cijk = 
01043     Hermite<T>::workspace.getTripleProduct();
01044   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
01045     Cijk.getBasis();
01046 
01047   // Fill A and b
01048   for (unsigned int i=1; i<=dc; i++) {
01049     for (unsigned int j=1; j<=dc; j++) {
01050       A(i-1,j-1) = 0.0;
01051       for (unsigned int k=0; k<=dc; k++) {
01052   if (i+j-2 >= k) {
01053     A(i-1,j-1) += Cijk.value(i-1,j-1,k)*basis.derivCoeff(j)*ca[k];
01054   }
01055       }
01056       A(i-1,j-1) /= Cijk.norm_squared(i-1)*basis.derivCoeff(i);
01057     }
01058     b(i-1,0) = ca[i];
01059   }
01060 
01061   // Solve system
01062   int info = Hermite<T>::workspace.solve(dc, 1);
01063 
01064 #ifdef SACADO_DEBUG
01065     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01066            func << ":  Argument " << info 
01067                 << " for solve had illegal value");
01068     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01069            func << ":  Diagonal entry " << info 
01070                 << " in LU factorization is exactly zero");
01071 #endif
01072 
01073   // Compute degree-0 coefficient
01074   T s = basis.getBasisPoly(0).coeff(0) * ca[0];
01075   T t = T(0.0);
01076   for (unsigned int i=1; i<=dc; i++) {
01077     s += basis.getBasisPoly(i).coeff(0) * ca[i];
01078     t += basis.getBasisPoly(i).coeff(0) * b(i-1,0);
01079   }
01080   cc[0] = (std::log(s) - t) / basis.getBasisPoly(0).coeff(0);
01081 
01082   // Compute remaining coefficients
01083   for (unsigned int i=1; i<=dc; i++)
01084     cc[i] = b(i-1,0);
01085 
01086   return c;
01087 }
01088 
01089 template <typename T>
01090 Hermite<T>
01091 log10(const Hermite<T>& a)
01092 {
01093   return log(a) / std::log(10.0);
01094 }
01095 
01096 template <typename T>
01097 Hermite<T>
01098 sqrt(const Hermite<T>& a)
01099 {
01100   return exp(T(0.5)*log(a));
01101 }
01102 
01103 template <typename T>
01104 Hermite<T>
01105 pow(const Hermite<T>& a,
01106     const Hermite<T>& b)
01107 {
01108   return exp(b*log(a));
01109 }
01110 
01111 template <typename T>
01112 Hermite<T>
01113 pow(const T& a,
01114     const Hermite<T>& b)
01115 {
01116   return exp(b*std::log(a));
01117 }
01118 
01119 template <typename T>
01120 Hermite<T>
01121 pow(const Hermite<T>& a,
01122     const T& b)
01123 {
01124   return exp(b*log(a));
01125 }
01126 
01127 template <typename T>
01128 void
01129 sincos(const Hermite<T>& a,
01130        Hermite<T>& s,
01131        Hermite<T>& c)
01132 {
01133   unsigned int dc = a.degree();
01134 
01135 #ifdef SACADO_DEBUG
01136   const char* func = "Sacado::PCE::Hermite::sincos()";
01137   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
01138          func << ":  Workspace size (" 
01139          << Hermite<T>::workspace.size() 
01140          << ") is too small for computation (" << dc+1 
01141          << " needed).");
01142 #endif
01143 
01144   if (s.degree() != dc)
01145     s.resize(dc, false);
01146   if (c.degree() != dc)
01147     c.resize(dc, false);
01148 
01149   const T* ca = a.coeff();
01150   T* cs = s.coeff();
01151   T* cc = c.coeff();
01152 
01153   typename Hermite<T>::ws_type::matrix_type& A = 
01154     Hermite<T>::workspace.getMatrix();
01155   typename Hermite<T>::ws_type::matrix_type& b = 
01156     Hermite<T>::workspace.getRHS();
01157   const typename Hermite<T>::ws_type::tp_type& Cijk = 
01158     Hermite<T>::workspace.getTripleProduct();
01159   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
01160     Cijk.getBasis();
01161 
01162   // Fill A and b
01163   A.putScalar(T(0.0));
01164   b.putScalar(T(0.0));
01165   for (unsigned int i=1; i<=dc; i++) {
01166     for (unsigned int j=1; j<=dc; j++) {
01167       T tmp = T(0.0);
01168       for (unsigned int k=1; k<=dc; k++) {
01169   if (i+j >= k) {
01170     tmp += Cijk.value(i-1,j,k-1)*basis.derivCoeff(k)*ca[k];
01171   }
01172       }
01173       tmp /= Cijk.norm_squared(i-1)*basis.derivCoeff(i);
01174       A(i-1,j-1+dc) = -tmp;
01175       A(i-1+dc,j-1) = tmp;
01176     }
01177     A(i-1,i-1) = T(1.0);
01178     A(i-1+dc,i-1+dc) = T(1.0);
01179     b(i-1,0) = ca[i];
01180     b(i-1+dc,1) = ca[i];
01181   }
01182 
01183   // Solve system
01184   int info = Hermite<T>::workspace.solve(2*dc, 2);
01185 
01186 #ifdef SACADO_DEBUG
01187     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01188            func << ":  Argument " << info 
01189                 << " for solve had illegal value");
01190     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01191            func << ":  Diagonal entry " << info 
01192                 << " in LU factorization is exactly zero");
01193 #endif
01194 
01195   // Compute degree-0 coefficients
01196   T t = basis.getBasisPoly(0).coeff(0) * ca[0];
01197   T a00 = T(0.0);
01198   T a01 = T(0.0);
01199   T a10 = T(0.0);
01200   T a11 = T(0.0);
01201   T b0 = b(0,0);
01202   T b1 = b(1,0);
01203   for (unsigned int i=1; i<=dc; i++) {
01204     t += basis.getBasisPoly(i).coeff(0) * ca[i];
01205     a00 += basis.getBasisPoly(i).coeff(0) * b(i-1,1);
01206     a01 += basis.getBasisPoly(i).coeff(0) * b(i-1,0);
01207     a10 += basis.getBasisPoly(i).coeff(0) * b(i-1+dc,1);
01208     a11 += basis.getBasisPoly(i).coeff(0) * b(i-1+dc,0);
01209   }
01210   A(0,0) = T(1.0) - a00;
01211   A(0,1) = a01;
01212   A(1,0) = -a10;
01213   A(1,1) = T(1.0) + a11;
01214   b(0,0) = std::sin(t);
01215   b(1,0) = std::cos(t);
01216   info = Hermite<T>::workspace.solve(2, 1);
01217 #ifdef SACADO_DEBUG
01218   TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01219          func << ":  Argument " << info 
01220          << " for (2x2) solve had illegal value");
01221   TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01222          func << ":  Diagonal entry " << info 
01223          << " in (2x2) LU factorization is exactly zero");
01224 #endif
01225   cs[0] = b(0,0);
01226   cc[0] = b(1,0);
01227 
01228   // Compute remaining coefficients
01229   b(0,0) = b0;
01230   b(1,0) = b1;
01231   for (unsigned int i=1; i<=dc; i++) {
01232     cs[i] = cc[0]*b(i-1,0) - cs[0]*b(i-1,1);
01233     cc[i] = cc[0]*b(i-1+dc,0) - cs[0]*b(i-1+dc,1);
01234   }
01235 
01236   cs[0] /= basis.getBasisPoly(0).coeff(0);
01237   cc[0] /= basis.getBasisPoly(0).coeff(0);
01238 }
01239 
01240 template <typename T>
01241 Hermite<T>
01242 sin(const Hermite<T>& a)
01243 {
01244   unsigned int dc = a.degree();
01245   Hermite<T> s(dc);
01246   Hermite<T> c(dc);
01247   sincos(a, s, c);
01248 
01249   return s;
01250 }
01251 
01252 template <typename T>
01253 Hermite<T>
01254 cos(const Hermite<T>& a)
01255 {
01256   unsigned int dc = a.degree();
01257   Hermite<T> s(dc);
01258   Hermite<T> c(dc);
01259   sincos(a, s, c);
01260 
01261   return c;
01262 }
01263 
01264 template <typename T>
01265 Hermite<T>
01266 tan(const Hermite<T>& a)
01267 {
01268   unsigned int dc = a.degree();
01269   Hermite<T> s(dc);
01270   Hermite<T> c(dc);
01271   
01272   sincos(a, s, c);
01273 
01274   return s / c;
01275 }
01276 
01277 template <typename T>
01278 void
01279 sinhcosh(const Hermite<T>& a,
01280    Hermite<T>& s,
01281    Hermite<T>& c)
01282 {
01283     unsigned int dc = a.degree();
01284 
01285 #ifdef SACADO_DEBUG
01286   const char* func = "Sacado::PCE::Hermite::sinhcosh()";
01287   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
01288          func << ":  Workspace size (" 
01289          << Hermite<T>::workspace.size() 
01290          << ") is too small for computation (" << dc+1 
01291          << " needed).");
01292 #endif
01293 
01294   if (s.degree() != dc)
01295     s.resize(dc, false);
01296   if (c.degree() != dc)
01297     c.resize(dc, false);
01298 
01299   const T* ca = a.coeff();
01300   T* cs = s.coeff();
01301   T* cc = c.coeff();
01302 
01303   typename Hermite<T>::ws_type::matrix_type& A = 
01304     Hermite<T>::workspace.getMatrix();
01305   typename Hermite<T>::ws_type::matrix_type& b = 
01306     Hermite<T>::workspace.getRHS();
01307   const typename Hermite<T>::ws_type::tp_type& Cijk = 
01308     Hermite<T>::workspace.getTripleProduct();
01309   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
01310     Cijk.getBasis();
01311 
01312   // Fill A and b
01313   A.putScalar(T(0.0));
01314   b.putScalar(T(0.0));
01315   for (unsigned int i=1; i<=dc; i++) {
01316     for (unsigned int j=1; j<=dc; j++) {
01317       T tmp = T(0.0);
01318       for (unsigned int k=1; k<=dc; k++) {
01319   if (i+j >= k) {
01320     tmp += Cijk.value(i-1,j,k-1)*basis.derivCoeff(k)*ca[k];
01321   }
01322       }
01323       tmp /= Cijk.norm_squared(i-1)*basis.derivCoeff(i);
01324       A(i-1,j-1+dc) = -tmp;
01325       A(i-1+dc,j-1) = -tmp;
01326     }
01327     A(i-1,i-1) = T(1.0);
01328     A(i-1+dc,i-1+dc) = T(1.0);
01329     b(i-1,0) = ca[i];
01330     b(i-1+dc,1) = ca[i];
01331   }
01332 
01333   // Solve system
01334   int info = Hermite<T>::workspace.solve(2*dc, 2);
01335 
01336 #ifdef SACADO_DEBUG
01337     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01338            func << ":  Argument " << info 
01339                 << " for solve had illegal value");
01340     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01341            func << ":  Diagonal entry " << info 
01342                 << " in LU factorization is exactly zero");
01343 #endif
01344 
01345   // Compute degree-0 coefficients
01346   T t = basis.getBasisPoly(0).coeff(0) * ca[0];
01347   T a00 = T(1.0);
01348   T a01 = T(0.0);
01349   T a10 = T(0.0);
01350   T a11 = T(1.0);
01351   T b0 = b(0,0);
01352   T b1 = b(1,0);
01353   for (unsigned int i=1; i<=dc; i++) {
01354     t += basis.getBasisPoly(i).coeff(0) * ca[i];
01355     a00 += basis.getBasisPoly(i).coeff(0) * b(i-1,1);
01356     a01 += basis.getBasisPoly(i).coeff(0) * b(i-1,0);
01357     a10 += basis.getBasisPoly(i).coeff(0) * b(i-1+dc,1);
01358     a11 += basis.getBasisPoly(i).coeff(0) * b(i-1+dc,0);
01359   }
01360   A(0,0) = a00;
01361   A(0,1) = a01;
01362   A(1,0) = a10;
01363   A(1,1) = a11;
01364   b(0,0) = std::sinh(t);
01365   b(1,0) = std::cosh(t);
01366   info = Hermite<T>::workspace.solve(2, 1);
01367 #ifdef SACADO_DEBUG
01368   TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01369          func << ":  Argument " << info 
01370          << " for (2x2) solve had illegal value");
01371   TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01372          func << ":  Diagonal entry " << info 
01373          << " in (2x2) LU factorization is exactly zero");
01374 #endif
01375   cs[0] = b(0,0);
01376   cc[0] = b(1,0);
01377 
01378   // Compute remaining coefficients
01379   b(0,0) = b0;
01380   b(1,0) = b1;
01381   for (unsigned int i=1; i<=dc; i++) {
01382     cs[i] = cc[0]*b(i-1,0) + cs[0]*b(i-1,1);
01383     cc[i] = cc[0]*b(i-1+dc,0) + cs[0]*b(i-1+dc,1);
01384   }
01385 
01386   cs[0] /= basis.getBasisPoly(0).coeff(0);
01387   cc[0] /= basis.getBasisPoly(0).coeff(0);
01388 }
01389 
01390 template <typename T>
01391 Hermite<T>
01392 sinh(const Hermite<T>& a)
01393 {
01394   unsigned int dc = a.degree();
01395   Hermite<T> s(dc);
01396   Hermite<T> c(dc);
01397   sinhcosh(a, s, c);
01398 
01399   return s;
01400 }
01401 
01402 template <typename T>
01403 Hermite<T>
01404 cosh(const Hermite<T>& a)
01405 {
01406   unsigned int dc = a.degree();
01407   Hermite<T> s(dc);
01408   Hermite<T> c(dc);
01409   sinhcosh(a, s, c);
01410 
01411   return c;
01412 }
01413 
01414 template <typename T>
01415 Hermite<T>
01416 tanh(const Hermite<T>& a)
01417 {
01418   unsigned int dc = a.degree();
01419   Hermite<T> s(dc);
01420   Hermite<T> c(dc);
01421   
01422   sinhcosh(a, s, c);
01423 
01424   return s / c;
01425 }
01426 
01427 template <typename T, typename OpT>
01428 Hermite<T>
01429 quad(const OpT& quad_func,
01430      const Hermite<T>& a,
01431      const Hermite<T>& b)
01432 {
01433   unsigned int dc = a.degree();
01434 
01435   Hermite<T> c(dc);
01436   const T* ca = a.coeff();
01437   const T* cb = b.coeff();
01438   T* cc = c.coeff();
01439 
01440 #ifdef SACADO_DEBUG
01441   const char* func = "Sacado::PCE::Hermite::quad()";
01442   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc, std::logic_error,
01443          func << ":  Workspace size (" 
01444          << Hermite<T>::workspace.size() 
01445          << ") is too small for computation (" << dc+1 
01446          << " needed).");
01447 #endif
01448 
01449   typename Hermite<T>::ws_type::matrix_type& A = 
01450     Hermite<T>::workspace.getMatrix();
01451   typename Hermite<T>::ws_type::matrix_type& B = 
01452     Hermite<T>::workspace.getRHS();
01453   const typename Hermite<T>::ws_type::tp_type& Cijk = 
01454     Hermite<T>::workspace.getTripleProduct();
01455   const typename Hermite<T>::ws_type::tp_type::basis_type& basis = 
01456     Cijk.getBasis();
01457     
01458     // Fill A
01459     for (unsigned int i=1; i<=dc; i++) {
01460       for (unsigned int j=1; j<=dc; j++) {
01461   A(i-1,j-1) = 0.0;
01462   for (unsigned int k=0; k<=dc; k++) {
01463     A(i-1,j-1) += Cijk.value(i-1,j-1,k)*cb[k];
01464   }
01465   A(i-1,j-1) = A(i-1,j-1)*basis.derivCoeff(j) / 
01466     (Cijk.norm_squared(i-1)*basis.derivCoeff(i));
01467       }
01468     }
01469     
01470     // Fill b
01471     for (unsigned int i=1; i<=dc; i++)
01472       B(i-1,0) = ca[i];
01473 
01474     // Solve system
01475     int info = Hermite<T>::workspace.solve(dc, 1);
01476 
01477 #ifdef SACADO_DEBUG
01478     TEST_FOR_EXCEPTION(info < 0, std::logic_error,
01479            func << ":  Argument " << info 
01480                 << " for solve had illegal value");
01481     TEST_FOR_EXCEPTION(info > 0, std::logic_error,
01482            func << ":  Diagonal entry " << info 
01483                 << " in LU factorization is exactly zero");
01484 #endif
01485 
01486   // Compute degree-0 coefficient
01487   T s = basis.getBasisPoly(0).coeff(0) * ca[0];
01488   T t = T(0.0);
01489   for (unsigned int i=1; i<=dc; i++) {
01490     s += basis.getBasisPoly(i).coeff(0) * ca[i];
01491     t += basis.getBasisPoly(i).coeff(0) * B(i-1,0);
01492   }
01493   cc[0] = (quad_func(s) - t) / basis.getBasisPoly(0).coeff(0);
01494 
01495   // Get coefficients
01496   for (unsigned int i=1; i<=dc; i++)
01497     cc[i] = B(i-1,0);
01498 
01499   return c;
01500 }
01501 
01502 template <typename T>
01503 struct acos_quad_func { 
01504   T operator() (const T& a) const { return std::acos(a); } 
01505 };
01506 
01507 template <typename T>
01508 struct asin_quad_func { 
01509   T operator() (const T& a) const { return std::asin(a); } 
01510 };
01511 
01512 template <typename T>
01513 struct atan_quad_func { 
01514   T operator() (const T& a) const { return std::atan(a); } 
01515 };
01516 
01517 template <typename T>
01518 struct acosh_quad_func { 
01519   T operator() (const T& a) const { return std::log(a+std::sqrt(a*a-T(1.0))); }
01520 };
01521 
01522 template <typename T>
01523 struct asinh_quad_func { 
01524   T operator() (const T& a) const { return std::log(a+std::sqrt(a*a+T(1.0))); }
01525 };
01526 
01527 template <typename T>
01528 struct atanh_quad_func { 
01529   T operator() (const T& a) const { return 0.5*std::log((T(1.0)+a)/(T(1.0)-a)); } 
01530 };
01531 
01532 template <typename T>
01533 Hermite<T>
01534 acos(const Hermite<T>& a)
01535 {
01536   Hermite<T> b = -sqrt(T(1.0) - a*a);
01537   return quad(acos_quad_func<T>(), a, b);
01538 }
01539 
01540 template <typename T>
01541 Hermite<T>
01542 asin(const Hermite<T>& a)
01543 {
01544   Hermite<T> b = sqrt(T(1.0) - a*a);
01545   return quad(asin_quad_func<T>(), a, b);
01546 }
01547 
01548 template <typename T>
01549 Hermite<T>
01550 atan(const Hermite<T>& a)
01551 {
01552   Hermite<T> b = T(1.0) + a*a;
01553   return quad(atan_quad_func<T>(), a, b);
01554 }
01555 
01556 // template <typename T>
01557 // Hermite<T>
01558 // atan2(const Hermite<T>& a,
01559 //       const Hermite<T>& b)
01560 // {
01561 //   Hermite<T> c = atan(a/b);
01562 //   c.fastAccessCoeff(0) = atan2(a.coeff(0),b.coeff(0));
01563 // }
01564 
01565 // template <typename T>
01566 // Hermite<T>
01567 // atan2(const T& a,
01568 //       const Hermite<T>& b)
01569 // {
01570 //   Hermite<T> c = atan(a/b);
01571 //   c.fastAccessCoeff(0) = atan2(a,b.coeff(0));
01572 // }
01573 
01574 // template <typename T>
01575 // Hermite<T>
01576 // atan2(const Hermite<T>& a,
01577 //       const T& b)
01578 // {
01579 //   Hermite<T> c = atan(a/b);
01580 //   c.fastAccessCoeff(0) = atan2(a.coeff(0),b);
01581 // }
01582 
01583 template <typename T>
01584 Hermite<T>
01585 acosh(const Hermite<T>& a)
01586 {
01587   Hermite<T> b = sqrt(a*a - T(1.0));
01588   return quad(acosh_quad_func<T>(), a, b);
01589 //   return std::log(a + std::sqrt(a*a - T(1.0)));
01590 }
01591 
01592 template <typename T>
01593 Hermite<T>
01594 asinh(const Hermite<T>& a)
01595 {
01596   Hermite<T> b = sqrt(a*a + T(1.0));
01597   return quad(asinh_quad_func<T>(), a, b);
01598 //   return std::log(a + std::sqrt(a*a + T(1.0)));
01599 }
01600 
01601 template <typename T>
01602 Hermite<T>
01603 atanh(const Hermite<T>& a)
01604 {
01605   Hermite<T> b = 1.0 - a*a;
01606   return quad(atanh_quad_func<T>(), a, b);
01607 //   return T(0.5) * std::log((T(1.0) + a)/(T(1.0) - a));
01608 }
01609 
01610 template <typename T>
01611 Hermite<T>
01612 fabs(const Hermite<T>& a)
01613 {
01614   if (a.coeff(0) >= 0)
01615     return a;
01616   else
01617     return -a;
01618 }
01619 
01620 template <typename T>
01621 Hermite<T>
01622 abs(const Hermite<T>& a)
01623 {
01624   if (a.coeff(0) >= 0)
01625     return a;
01626   else
01627     return -a;
01628 }
01629 
01630 // template <typename T>
01631 // Hermite<T>
01632 // deriv(const Hermite<T>& a)
01633 // {
01634 //   unsigned int dc = a.degree();
01635 
01636 // #ifdef SACADO_DEBUG
01637 //   const char* func = "Sacado::PCE::Hermite::deriv()";
01638 //   TEST_FOR_EXCEPTION(Hermite<T>::workspace.size() < dc+1, std::logic_error,
01639 //         func << ":  Workspace size (" 
01640 //         << Hermite<T>::workspace.size() 
01641 //         << ") is too small for computation (" << dc+1 
01642 //         << " needed).");
01643 // #endif
01644 
01645 //   Hermite<T> c(dc);
01646 //   const T* ca = a.coeff();
01647 //   T* cc = c.coeff();
01648 
01649 //   const typename Hermite<T>::ws_type::tp_type& Cijk = 
01650 //     Hermite<T>::workspace.getTripleProduct();
01651 
01652 //   for (unsigned int i=0; i<dc; i++)
01653 //     cc[i] = T(2.0)*(i+1)*ca[i+1] / Cijk.norm_squared(i);
01654 //   cc[dc] = T(0.0);
01655 
01656 //   return c;
01657 // }
01658 
01659 template <typename T>
01660 Hermite<T>
01661 max(const Hermite<T>& a,
01662     const Hermite<T>& b)
01663 {
01664   if (a.coeff(0) >= b.coeff(0))
01665     return a;
01666   else
01667     return b;
01668 }
01669 
01670 template <typename T>
01671 Hermite<T>
01672 max(const T& a,
01673     const Hermite<T>& b)
01674 {
01675   if (a >= b.coeff(0))
01676     return Hermite<T>(b.degree(), a);
01677   else
01678     return b;
01679 }
01680 
01681 template <typename T>
01682 Hermite<T>
01683 max(const Hermite<T>& a,
01684     const T& b)
01685 {
01686   if (a.coeff(0) >= b)
01687     return a;
01688   else
01689     return Hermite<T>(a.degree(), b);
01690 }
01691 
01692 template <typename T>
01693 Hermite<T>
01694 min(const Hermite<T>& a,
01695     const Hermite<T>& b)
01696 {
01697   if (a.coeff(0) <= b.coeff(0))
01698     return a;
01699   else
01700     return b;
01701 }
01702 
01703 template <typename T>
01704 Hermite<T>
01705 min(const T& a,
01706     const Hermite<T>& b)
01707 {
01708   if (a <= b.coeff(0))
01709     return Hermite<T>(b.degree(), a);
01710   else
01711     return b;
01712 }
01713 
01714 template <typename T>
01715 Hermite<T>
01716 min(const Hermite<T>& a,
01717     const T& b)
01718 {
01719   if (a.coeff(0) <= b)
01720     return a;
01721   else
01722     return Hermite<T>(a.degree(), b);
01723 }
01724 
01725 template <typename T>
01726 bool
01727 operator==(const Hermite<T>& a, 
01728      const Hermite<T>& b)
01729 {
01730   return a.coeff(0) == b.coeff(0);
01731 }
01732 
01733 template <typename T>
01734 bool
01735 operator==(const T& a, 
01736      const Hermite<T>& b)
01737 {
01738   return a == b.coeff(0);
01739 }
01740 
01741 template <typename T>
01742 bool
01743 operator==(const Hermite<T>& a, 
01744      const T& b)
01745 {
01746   return a.coeff(0) == b;
01747 }
01748 
01749 template <typename T>
01750 bool
01751 operator!=(const Hermite<T>& a, 
01752      const Hermite<T>& b)
01753 {
01754   return a.coeff(0) != b.coeff(0);
01755 }
01756 
01757 template <typename T>
01758 bool
01759 operator!=(const T& a, 
01760      const Hermite<T>& b)
01761 {
01762   return a != b.coeff(0);
01763 }
01764 
01765 template <typename T>
01766 bool
01767 operator!=(const Hermite<T>& a, 
01768      const T& b)
01769 {
01770   return a.coeff(0) != b;
01771 }
01772 
01773 template <typename T>
01774 bool
01775 operator<=(const Hermite<T>& a, 
01776      const Hermite<T>& b)
01777 {
01778   return a.coeff(0) <= b.coeff(0);
01779 }
01780 
01781 template <typename T>
01782 bool
01783 operator<=(const T& a, 
01784      const Hermite<T>& b)
01785 {
01786   return a <= b.coeff(0);
01787 }
01788 
01789 template <typename T>
01790 bool
01791 operator<=(const Hermite<T>& a, 
01792      const T& b)
01793 {
01794   return a.coeff(0) <= b;
01795 }
01796 
01797 template <typename T>
01798 bool
01799 operator>=(const Hermite<T>& a, 
01800      const Hermite<T>& b)
01801 {
01802   return a.coeff(0) >= b.coeff(0);
01803 }
01804 
01805 template <typename T>
01806 bool
01807 operator>=(const T& a, 
01808      const Hermite<T>& b)
01809 {
01810   return a >= b.coeff(0);
01811 }
01812 
01813 template <typename T>
01814 bool
01815 operator>=(const Hermite<T>& a, 
01816      const T& b)
01817 {
01818   return a.coeff(0) >= b;
01819 }
01820 
01821 template <typename T>
01822 bool
01823 operator<(const Hermite<T>& a, 
01824     const Hermite<T>& b)
01825 {
01826   return a.coeff(0) < b.coeff(0);
01827 }
01828 
01829 template <typename T>
01830 bool
01831 operator<(const T& a, 
01832     const Hermite<T>& b)
01833 {
01834   return a < b.coeff(0);
01835 }
01836 
01837 template <typename T>
01838 bool
01839 operator<(const Hermite<T>& a, 
01840     const T& b)
01841 {
01842   return a.coeff(0) < b;
01843 }
01844 
01845 template <typename T>
01846 bool
01847 operator>(const Hermite<T>& a, 
01848     const Hermite<T>& b)
01849 {
01850   return a.coeff(0) > b.coeff(0);
01851 }
01852 
01853 template <typename T>
01854 bool
01855 operator>(const T& a, 
01856     const Hermite<T>& b)
01857 {
01858   return a > b.coeff(0);
01859 }
01860 
01861 template <typename T>
01862 bool
01863 operator>(const Hermite<T>& a, 
01864     const T& b)
01865 {
01866   return a.coeff(0) > b;
01867 }
01868 
01869 template <typename T>
01870 std::ostream& 
01871 operator << (std::ostream& os, const Hermite<T>& a)
01872 {
01873   os << "[ ";
01874       
01875   for (unsigned int i=0; i<=a.degree(); i++) {
01876     os << a.coeff(i) << " ";
01877   }
01878 
01879   os << "]\n";
01880   return os;
01881 }
01882 
01883 } // namespace PCE
01884 } // namespace Sacado

Generated on Wed May 12 21:59:04 2010 for Sacado Package Browser (Single Doxygen Collection) by  doxygen 1.4.7