00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "Teuchos_TestForException.hpp"
00033 #include "Sacado_ConfigDefs.h"
00034 #include "Sacado_DynamicArrayTraits.hpp"
00035 #include <ostream>
00036
00037 namespace Sacado {
00038 namespace PCE {
00039
00040
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
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
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
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
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
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
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
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
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
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
00903 b(0,0) = a;
00904 for (unsigned int i=1; i<=dc; i++)
00905 b(i,0) = T(0.0);
00906
00907
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01471 for (unsigned int i=1; i<=dc; i++)
01472 B(i-1,0) = ca[i];
01473
01474
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
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
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
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
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
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
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
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
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
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 }
01884 }