OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
Tps.hpp
Go to the documentation of this file.
1 #ifndef CLASSIC_Tps_CC
2 #define CLASSIC_Tps_CC 1
3 
4 // ------------------------------------------------------------------------
5 // $RCSfile: Tps.cpp,v $
6 // ------------------------------------------------------------------------
7 // $Revision: 1.3 $
8 // ------------------------------------------------------------------------
9 // Copyright: see Copyright.readme
10 // ------------------------------------------------------------------------
11 //
12 // Template Class: Tps<class T>
13 // Truncated power series in n variables of type T.
14 // This file contains the template implementation only.
15 //
16 // ------------------------------------------------------------------------
17 // Class category: Algebra
18 // ------------------------------------------------------------------------
19 //
20 // $Date: 2001/11/27 23:33:32 $
21 // $Author: jsberg $
22 //
23 // ------------------------------------------------------------------------
24 
25 #include "Algebra/Tps.h"
26 #include "Algebra/Array1D.h"
27 #include "Algebra/Matrix.h"
28 #include "Algebra/TpsData.h"
29 #include "Algebra/TpsMonomial.h"
31 #include "Algebra/VpsMap.h"
32 #include "Utilities/DivideError.h"
33 #include "Utilities/FormatError.h"
34 #include "Utilities/LogicalError.h"
35 #include "Utilities/CLRangeError.h"
36 #include "Utilities/SizeError.h"
37 #include <algorithm>
38 #include <iomanip>
39 #include <iostream>
40 #include <new>
41 #include <cstring>
42 #include <functional>
43 
44 
45 // Helper functions.
46 // ------------------------------------------------------------------------
47 
48 template <class T> inline
49 void Tps<T>::setMaxOrder(int order) {
50  rep->maxOrd = order;
51 }
52 
53 
54 template <class T> inline
56  if(rep->ref > 1) {
57  rep->ref--;
58  rep = rep->clone();
59  }
60 }
61 
62 
63 // Template class TpsRep<T>.
64 //
65 // The representation of a Tps<T> is based on a mechanism which avoids
66 // double memory allocation (one for the TpsRep<T> object, one for the
67 // table of monomials). If this causes problems, it can be reverted to
68 // using a double allocation by adding a data member "T *dat" to TpsRep<T>,
69 // changing "TpsRep<T>::data()" to return "dat", and adapting the methods
70 // "TpsRep<T>::operator new()" and "TpsRep<T>::operator delete()" so as
71 // to allocate/deallocate an array of "T", pointed to by "dat".
72 //
73 // A special memory allocator may help for speed.
74 // ------------------------------------------------------------------------
75 
76 template <class T> class TpsRep {
77 
78  friend class Tps<T>;
79 
80  // Memory management.
81  static void *operator new(size_t s, size_t extra);
82  static void operator delete(void *);
83  static TpsRep<T> *create(int maxOrder, int trcOrder, int variables);
84  static TpsRep<T> *zero();
85  static void release(TpsRep<T> *);
86 
87  // Make a copy of the representation.
88  TpsRep<T> *clone();
89 
90  // Grab a new reference.
91  TpsRep<T> *grab();
92 
93  // Return the monomial array.
94  T *data();
95 
96  // The reference count.
97  int ref;
98 
99  // Order and size of this object.
100  int maxOrd;
101  int trcOrd;
102 
103  // The length of the monomial table.
104  int len;
105 
106  // The data structure for bookkeeping.
108 
109  // Not implemented.
110  TpsRep<T> &operator=(const TpsRep<T> &);
111 
112  // May need to add this:
113  // T *dat;
114 };
115 
116 
117 template <class T> inline
119  return reinterpret_cast<T *>(this + 1);
120  // Could be changed to:
121  // return dat;
122 }
123 
124 
125 template <class T> inline
126 void *TpsRep<T>::operator new(size_t s, size_t extra) {
127  return new char[s + extra * sizeof(double)];
128  // Could be changed to:
129  // TpsRep<T> *p = new char[s];
130  // p->dat = new T[extra];
131  // return p;
132 }
133 
134 
135 template <class T> inline
136 void TpsRep<T>::operator delete(void *p) {
137  // May have to add this:
138  // delete [] reinterpret_cast<TpsRep<T>*>(p)->dat;
139  delete [] reinterpret_cast<char *>(p);
140 }
141 
142 
143 template <class T> inline
144 TpsRep<T> *TpsRep<T>::create(int maxOrder, int trcOrder, int variables) {
145  // Construct descriptor and size.
146  TpsData *d = 0;
147  int s = 1;
148  if(variables) {
149  d = TpsData::getTpsData(maxOrder, variables);
150  s = d->getSize(maxOrder);
151  }
152 
153  // Allocate representation and fill in data.
154  TpsRep<T> *p = new(s) TpsRep<T>;
155  p->ref = 1;
156  p->maxOrd = maxOrder;
157  p->trcOrd = trcOrder;
158  p->len = s;
159  p->help = d;
160 
161  // Fill monomial coefficients with zeroes.
162  std::fill(p->data() + 0, p->data() + p->len, T(0));
163  return p;
164 }
165 
166 
167 template <class T> inline
169  // Allocate representation and fill in data.
170  TpsRep<T> *p = new(1) TpsRep<T>;
171  p->ref = 1;
172  p->maxOrd = 0;
173  p->trcOrd = Tps<T>::EXACT;
174  p->len = 1;
175  p->help = 0;
176 
177  // Fill monomial coefficients with zeroes.
178  new(&p->data()[0]) T(0);
179  return p;
180 }
181 
182 
183 template <class T> inline
185  // Allocate copy and copy monomial coefficients.
186  TpsRep<T> *p = new(len) TpsRep<T>;
187  for(int i = 0; i < len; ++i) {
188  new(&p->data()[i]) T(data()[i]);
189  }
190 
191  // Copy limits and descriptor.
192  p->ref = 1;
193  p->maxOrd = maxOrd;
194  p->trcOrd = trcOrd;
195  p->len = len;
196  p->help = help;
197  return p;
198 }
199 
200 
201 template <class T> inline
203  ++ref;
204  return this;
205 }
206 
207 
208 template <class T> inline
210  if(--(p->ref) <= 0) delete p;
211 }
212 
213 
214 // Template class Tps<T>.
215 // ------------------------------------------------------------------------
216 
217 template <class T> int Tps<T>::truncOrder = EXACT;
218 
219 
220 template <class T>
222  rep(TpsRep<T>::zero())
223 {}
224 
225 
226 template <class T>
227 Tps<T>::Tps(int maxOrder, int nVar):
228  rep(TpsRep<T>::create(maxOrder, EXACT, nVar))
229 {}
230 
231 
232 template <class T>
233 Tps<T>::Tps(const Tps<T> &rhs):
234  rep(rhs.rep->grab())
235 {}
236 
237 
238 template <class T>
239 Tps<T>::Tps(const T &rhs):
240  rep(TpsRep<T>::zero()) {
241  rep->data()[0] = rhs;
242 }
243 
244 
245 template <class T>
246 Tps<T>::Tps(int rhs):
247  rep(TpsRep<T>::zero()) {
248  rep->data()[0] = T(rhs);
249 }
250 
251 
252 template <class T>
255 }
256 
257 
258 template <class T>
260  if(rep != rhs.rep) {
262  rep = rhs.rep->grab();
263  }
264 
265  return *this;
266 }
267 
268 
269 template <class T>
270 Tps<T> &Tps<T>::operator=(const T &rhs) {
272  rep = TpsRep<T>::zero();
273  rep->data()[0] = rhs;
274  return *this;
275 }
276 
277 
278 template <class T>
279 Tps<T> Tps<T>::filter(int minOrder, int maxOrder) const {
280  // Compute order limits.
281  maxOrder = std::min(maxOrder, getMaxOrder());
282  int trcOrder = getTruncOrder();
283  int variables = getVariables();
284 
285  // Construct filtered TpsRep.
286  TpsRep<T> *p = TpsRep<T>::create(maxOrder, trcOrder, variables);
287  int bot = getSize(minOrder - 1);
288  int top = getSize(maxOrder);
289  std::copy(rep->data() + bot, rep->data() + top, p->data() + bot);
290  return Tps<T>(p);
291 }
292 
293 
294 template <class T>
296  return filter(0, trunc);
297 }
298 
299 
300 template <class T>
301 const T Tps<T>::operator[](int index) const {
302  return rep->data()[index];
303 }
304 
305 
306 template <class T>
307 T &Tps<T>::operator[](int index) {
308  unique();
309  return rep->data()[index];
310 }
311 
312 
313 template <class T>
314 const T Tps<T>::operator[](const TpsMonomial &monomial) const {
315  return rep->data()[monomial.getIndex()];
316 }
317 
318 
319 template <class T>
320 T &Tps<T>::operator[](const TpsMonomial &monomial) {
321  unique();
322  return rep->data()[monomial.getIndex()];
323 }
324 
325 
326 template <class T>
327 const T Tps<T>::getCoefficient(int index) const {
328  if(index > rep->len) {
329  throw CLRangeError("Tps::getCoefficients()", "Monomial index out of range.");
330  }
331 
332  return rep->data()[index];
333 }
334 
335 
336 template <class T>
337 void Tps<T>::setCoefficient(int index, const T &value) {
338  int order = getOrder(index);
339  if(order > rep->trcOrd) return;
340 
341  if(order > rep->maxOrd) {
342  TpsRep<T> *p = TpsRep<T>::create(order, rep->trcOrd, getVariables());
343  std::copy(rep->data(), rep->data() + rep->len, p->data());
345  rep = p;
346  } else {
347  unique();
348  }
349 
350  rep->data()[index] = value;
351 }
352 
353 
354 template <class T>
355 const T Tps<T>::getCoefficient(const TpsMonomial &monomial) const {
356  int v1 = monomial.getVariables();
357  int v2 = getVariables();
358 
359  if(v1 != v2) {
360  throw SizeError("Tps::getCoefficients()",
361  "Inconsistent number of variables.");
362  }
363 
364  return getCoefficient(monomial.getIndex());
365 }
366 
367 
368 template <class T>
369 void Tps<T>::setCoefficient(const TpsMonomial &monomial, const T &value) {
370  int v1 = monomial.getVariables();
371  int v2 = getVariables();
372 
373  if(v1 != v2) {
374  throw SizeError("Tps::getCoefficients()",
375  "Inconsistent number of variables.");
376  }
377 
378  setCoefficient(monomial.getIndex(), value);
379 }
380 
381 
382 template <class T>
383 Tps<T> Tps<T>::makeVariable(int nVar, int var) {
384  TpsRep<T> *p = TpsRep<T>::create(1, EXACT, nVar);
385  p->data()[var+1] = T(1);
386  return Tps<T>(p);
387 }
388 
389 
390 template <class T>
391 Tps<T> Tps<T>::makeVarPower(int nVar, int var, int order) {
392  TpsMonomial monomial(nVar);
393  monomial[var] = order;
394  Tps<T> z = Tps<T>(TpsRep<T>::create(order, EXACT, nVar));
395  z[monomial] = T(1);
396  return z;
397 }
398 
399 
400 template <class T>
401 Tps<T> Tps<T>::makeMonomial(const TpsMonomial &monomial, const T &cc) {
402  int order = monomial.getOrder();
403  int nVar = monomial.getVariables();
404  Tps<T> z = Tps<T>(TpsRep<T>::create(order, EXACT, nVar));
405  z[monomial] = cc;
406  return z;
407 }
408 
409 
410 template <class T>
412  return *this;
413 }
414 
415 
416 template <class T>
420  std::transform(rep->data(), rep->data() + rep->len, p->data(),
421  std::negate<T>());
422  return Tps<T>(p);
423 }
424 
425 
426 template <class T>
428  if(int v1 = getVariables()) {
429  if(int v2 = rhs.getVariables()) {
430  if(v1 != v2) {
431  throw SizeError("TpsRep::operator+=()",
432  "Number of variables inconsistent.");
433  }
434 
435  int trunc = std::min(getTruncOrder(), rhs.getTruncOrder());
436  int xOrder = std::min(getMaxOrder(), trunc);
437  int yOrder = std::min(rhs.getMaxOrder(), trunc);
438  int xLength = getSize(xOrder);
439  int yLength = getSize(yOrder);
440  int xyLength = std::min(xLength, yLength);
441  TpsRep<T> *p = TpsRep<T>::create(std::max(xOrder, yOrder), trunc, v1);
442  const T *x = rep->data();
443  const T *y = rhs.rep->data();
444  T *z = p->data();
445  std::transform(x, x + xyLength, y, z, std::plus<T>());
446  std::copy(x + xyLength, x + xLength, z + xyLength);
447  std::copy(y + xyLength, y + yLength, z + xyLength);
449  rep = p;
450  } else {
451  unique();
452  rep->data()[0] += rhs[0];
453  }
454  } else {
455  *this = rhs + rep->data()[0];
456  }
457  return *this;
458 }
459 
460 
461 template <class T>
463  if(int v1 = getVariables()) {
464  if(int v2 = rhs.getVariables()) {
465  if(v1 != v2) {
466  throw SizeError("TpsRep::operator-=()",
467  "Number of variables inconsistent.");
468  }
469 
470  int trunc = std::min(getTruncOrder(), rhs.getTruncOrder());
471  int xOrder = std::min(getMaxOrder(), trunc);
472  int yOrder = std::min(rhs.getMaxOrder(), trunc);
473  int xLength = getSize(xOrder);
474  int yLength = getSize(yOrder);
475  int xyLength = std::min(xLength, yLength);
476 
477  TpsRep<T> *p = TpsRep<T>::create(std::max(xOrder, yOrder), trunc, v1);
478  const T *x = rep->data();
479  const T *y = rhs.rep->data();
480  T *z = p->data();
481  std::transform(x, x + xyLength, y, z, std::minus<T>());
482  std::copy(x + xyLength, x + xLength, z + xyLength);
483  std::transform(y + xyLength, y + yLength, z + xyLength,
484  std::negate<T>());
486  rep = p;
487  } else {
488  unique();
489  rep->data()[0] -= rhs[0];
490  }
491  } else {
492  *this = - rhs + rep->data()[0];
493  }
494  return *this;
495 }
496 
497 
498 template <class T>
500  return *this = multiply(rhs, truncOrder);
501 }
502 
503 
504 template <class T>
506  return *this = multiply(rhs.inverse(truncOrder), truncOrder);
507 }
508 
509 
510 template <class T>
512  unique();
513  rep->data()[0] += rhs;
514  return *this;
515 }
516 
517 
518 template <class T>
520  unique();
521  rep->data()[0] -= rhs;
522  return *this;
523 }
524 
525 
526 template <class T>
528  unique();
529  T *x = rep->data();
530  std::transform(x, x + rep->len, x, std::bind(std::multiplies<T>(), std::placeholders::_1, rhs));
531  return *this;
532 }
533 
534 
535 template <class T>
537  if(rhs == T(0)) throw DivideError("Tps::operator/()");
538  T *x = rep->data();
539  std::transform(x, x + rep->len, x, std::bind(std::divides<T>(), std::placeholders::_1, rhs));
540  return *this;
541 }
542 
543 
544 template <class T>
545 bool Tps<T>::operator==(const Tps<T> &rhs) const {
546  if(int v1 = getVariables()) {
547  if(int v2 = rhs.getVariables()) {
548  if(v1 == v2) {
549  int trunc = std::min(getTruncOrder(), rhs.getTruncOrder());
550  int xOrder = std::min(getMaxOrder(), trunc);
551  int yOrder = std::min(rhs.getMaxOrder(), trunc);
552  int xLength = getSize(xOrder);
553  int yLength = getSize(yOrder);
554  int xyLength = getSize(std::min(xOrder, yOrder));
555  const T *x = rep->data();
556  const T *y = rhs.rep->data();
557 
558  for(int i = 0; i < xyLength; i++) {
559  if(x[i] != y[i]) return false;
560  }
561 
562  for(int i = xyLength; i < xLength; i++) {
563  if(x[i] != T(0)) return false;
564  }
565 
566  for(int i = xyLength; i < yLength; i++) {
567  if(y[i] != T(0)) return false;
568  }
569 
570  return true;
571  } else {
572  return false;
573  }
574  } else {
575  return false;
576  }
577  } else {
578  if(rhs.getVariables()) {
579  return false;
580  } else {
581  return rep->data()[0] == rhs.rep->data()[0];
582  }
583  }
584 }
585 
586 
587 template <class T>
588 bool Tps<T>::operator==(const T &rhs) const {
589  const T *x = rep->data();
590 
591  if(x[0] != rhs) return false;
592 
593  for(int i = 1; i < getSize(); ++i) {
594  if(x[i] != T(0)) return false;
595  }
596 
597  return true;
598 }
599 
600 
601 template <class T>
602 bool Tps<T>::operator!=(const Tps<T> &rhs) const {
603  return !(*this == rhs);
604 }
605 
606 
607 template <class T>
608 bool Tps<T>::operator!=(const T &rhs) const {
609  return !(*this == rhs);
610 }
611 
612 
613 template <class T>
615  if(getVariables()) {
616  int v1 = getVariables();
617  int v2 = M.nrows();
618  if(v1 != v2) {
619  throw SizeError("Tps::substitute()", "Matrix not consistent with Tps.");
620  }
621  int nRow = M.nrows();
622  int nCol = M.ncols();
623 
624  // Define the nRow linear transformations.
625  Array1D< Tps<T> > y(nRow);
626 
627  for(int i = 0; i < nRow; ++i) {
628  y[i] = Tps<T>(1, nCol);
629  for(int j = 0; j < nCol; ++j) y[i][j+1] = M[i][j];
630  }
631 
632  // Evaluate the substitution.
633  const T *x = rep->data();
634  Tps<T> z(x[0]);
635 
636  if(int maxOrd = getMaxOrder()) {
637  const Array1D<TpsSubstitution> &table = rep->help->getSubTable();
638  Array1D< Tps<T> > product(maxOrd + 1);
639  product[0] = Tps<T>(T(1));
640 
641  for(int next = 1; next < table.size();) {
642  const TpsSubstitution &s = table[next];
643  product[s.order] = product[s.order-1] * y[s.variable];
644  z += x[s.index] * product[s.order];
645  next = (s.order < maxOrd) ? next + 1 : s.skip;
646  }
647  }
648 
649  return z;
650  } else {
651  return *this;
652  }
653 }
654 
655 
656 template <class T>
658  int v1 = getVariables();
659  int v2 = rhs.getDimension();
660  if(v1 != v2) {
661  throw SizeError("Tps::substitute()", "VpsMap is inconsistent with Tps.");
662  }
663 
664  const T *x = rep->data();
665  Tps<T> z(x[0]);
666 
667  if(int maxOrd = getMaxOrder()) {
668  const Array1D<TpsSubstitution> &table = rep->help->getSubTable();
669  Array1D< Tps<T> > product(maxOrd + 1);
670  product[0] = Tps<T>(T(1));
671  int trunc = getTruncOrder();
672 
673  for(int next = 1; next < table.size();) {
674  const TpsSubstitution &s = table[next];
675  product[s.order] = product[s.order-1].multiply(rhs[s.variable], trunc);
676  z += x[s.index] * product[s.order];
677  next = (s.order < maxOrd) ? next + 1 : s.skip;
678  }
679  }
680 
681  return z;
682 }
683 
684 
685 template <class T>
686 T Tps<T>::evaluate(const Vector<T> &rhs) const {
687  int v1 = getVariables();
688  int v2 = rhs.size();
689  if(v1 != v2) {
690  throw SizeError("Tps::evaluate()", "Vector is inconsistent with Tps.");
691  }
692 
693  const T *x = rep->data();
694  T z = x[0];
695 
696  if(int maxOrd = getMaxOrder()) {
697  const Array1D<TpsSubstitution> &table = rep->help->getSubTable();
698  Array1D<T> product(maxOrd + 1);
699  product[0] = T(1);
700 
701  for(int next = 1; next < table.size();) {
702  const TpsSubstitution &s = table[next];
703  product[s.order] = product[s.order-1] * rhs[s.variable];
704  z += x[s.index] * product[s.order];
705  next = (s.order < maxOrd) ? next + 1 : s.skip;
706  }
707  }
708 
709  return z;
710 }
711 
712 
713 template <class T>
716  rep = TpsRep<T>::zero();
717 }
718 
719 
720 template <class T>
721 std::istream &Tps<T>::get(std::istream &is) {
722  is.flags(std::ios::skipws);
723  char head[4];
724  is.get(head, 4);
725  if(strcmp(head, "Tps") != 0) {
726  throw FormatError("Tps::get()", "Flag word \"Tps\" missing.");
727  }
728 
729  int maxOrder, truncOrder, nVar;
730  is >> maxOrder >> truncOrder >> nVar;
731  Tps<T> z(TpsRep<T>::create(maxOrder, truncOrder, nVar));
732  T coeff;
733 
734  if(nVar <= 0 || truncOrder == 0) {
735  is >> coeff;
736  z[0] = coeff;
737 
738  if(coeff != T(0)) {
739  z[0] = coeff;
740  is >> coeff;
741  }
742  } else {
743  TpsMonomial monomial(nVar);
744  maxOrder = 0;
745  bool done = false;
746  bool fail = false;
747 
748  while(true) {
749  is >> coeff;
750  fail = is.fail();
751 
752  int order = 0;
753  for(int var = 0; var < nVar; var++) {
754  int p;
755  is >> p;
756  fail |= is.fail();
757  if(p < 0) done = true;
758  monomial[var] = p;
759  order += monomial[var];
760  }
761 
762  if(done) break;
763  if(fail) throw FormatError("Tps::get()", "File read error");
764  int index = monomial.getIndex();
765 
766  if(coeff != T(0)) {
767  maxOrder = order;
768  } else if(index == 0) {
769  break;
770  }
771 
772  z[index] = coeff;
773  }
774 
775  z.setMaxOrder(maxOrder);
776  *this = z;
777  }
778 
779  return is;
780 }
781 
782 
783 template <class T>
784 std::ostream &Tps<T>::put(std::ostream &os) const {
785  std::streamsize old_prec = os.precision(14);
786  os.setf(std::ios::scientific, std::ios::floatfield);
787 
788  int nVar = getVariables();
789  os << "Tps " << getMaxOrder() << ' ' << getTruncOrder() << ' '
790  << nVar << std::endl;
791 
792  if(nVar == 0) {
793  os << std::setw(24) << rep->data()[0] << std::endl;
794  } else {
795  for(int i = 0; i < getSize(); ++i) {
796  if(rep->data()[i] != T(0)) {
797  os << std::setw(24) << rep->data()[i];
798 
799  for(int var = 0; var < nVar; var++) {
800  os << std::setw(3) << getExponents(i)[var];
801  }
802 
803  os << std::endl;
804  }
805  }
806 
807  os << std::setw(24) << T(0);
808 
809  for(int var = 0; var < nVar; var++) {
810  os << std::setw(3) << (-1);
811  }
812  }
813 
814  os << std::endl;
815 
816  os.precision(old_prec);
817  os.setf(std::ios::fixed, std::ios::floatfield);
818  return os;
819 }
820 
821 
822 template <class T>
823 Tps<T> Tps<T>::multiply(const Tps<T> &rhs, int trunc) const {
824  int v1 = getVariables();
825  int v2 = rhs.getVariables();
826  if(v1) {
827  if(v2) {
828  if(v1 != v2) {
829  throw SizeError("TpsRep::multiply()",
830  "Number of variables inconsistent.");
831  }
832 
833  if(getTruncOrder() != EXACT) {
834  int cut = getTruncOrder();
835  if(rhs[0] == 0.0) ++cut;
836  trunc = std::min(trunc, cut);
837  }
838 
839  if(rhs.getTruncOrder() != EXACT) {
840  int cut = rhs.getTruncOrder();
841  if((*this)[0] == 0.0) ++cut;
842  trunc = std::min(trunc, cut);
843  }
844 
845  int maxOrder = std::min(getMaxOrder() + rhs.getMaxOrder(), trunc);
846 
847  TpsRep<T> *p = TpsRep<T>::create(maxOrder, trunc, v1);
848  const T *x = rep->data();
849  T *z = p->data();
850  int yBot = 0;
851  int yHig = std::min(rhs.getMaxOrder(), trunc);
852 
853  for(int yOrd = 0; yOrd <= yHig; yOrd++) {
854  int xOrd = std::min(getMaxOrder(), trunc - yOrd);
855  int xTop = getSize(xOrd);
856  int yTop = getSize(yOrd);
857 
858  for(int yInd = yBot; yInd < yTop; yInd++) {
859  T y = rhs.rep->data()[yInd];
860  if(y != T(0)) {
861  const int *prod = rep->help->getProductArray(yInd);
862 
863  for(int xInd = 0; xInd < xTop; xInd++) {
864  z[prod[xInd]] += x[xInd] * y;
865  }
866  }
867  }
868 
869  yBot = yTop;
870  }
871 
872  return Tps<T>(p);
873  } else {
875  (getMaxOrder(), getTruncOrder(), v1));
876  const T *x = rep->data();
877  const T y = rhs.rep->data()[0];
878  T *z = result.rep->data();
879  std::transform(x, x + rep->len, z,
880  std::bind(std::multiplies<T>(), std::placeholders::_1, y));
881  return result;
882  }
883  } else {
885  (rhs.getMaxOrder(), rhs.getTruncOrder(), v2));
886  const T x = rep->data()[0];
887  const T *y = rhs.rep->data();
888  T *z = result.rep->data();
889  std::transform(y, y + rep->len, z,
890  std::bind(std::multiplies<T>(), std::placeholders::_1, x));
891  return result;
892  }
893 }
894 
895 
896 template <class T>
897 Tps<T> Tps<T>::inverse(int trunc) const {
898  T aZero = rep->data()[0];
899  if(aZero == T(0)) throw DivideError("Tps::inverse()");
900 
901  if(isConstant()) {
902  return Tps<T>(T(1) / aZero);
903  } else {
904  int cut = std::min(trunc, getTruncOrder());
905  T *series = new T[cut+1];
906  series[0] = T(1) / aZero;
907 
908  for(int i = 1; i <= cut; i++) {
909  series[i] = - series[i-1] / aZero;
910  }
911 
912  Tps<T> z = Taylor(series, cut);
913  delete [] series;
914  return z;
915  }
916 }
917 
918 
919 template <class T>
920 Tps<T> Tps<T>::derivative(int var) const {
921  if(getVariables() && getMaxOrder() > 0) {
922  int maxOrder = getMaxOrder() - 1;
923  int trcOrder = getTruncOrder();
924 
925  TpsRep<T> *p = TpsRep<T>::create(maxOrder, trcOrder, getVariables());
926  const T *x = rep->data();
927  T *z = p->data();
928 
929  const int *product = rep->help->getProductArray(var + 1);
930 
931  for(int i = getSize(maxOrder); i-- > 0;) {
932  int k = product[i];
933  z[i] = x[k] * double(getExponents(k)[var]);
934  }
935 
936  Tps<T> result(p);
937  return result;
938  } else {
939  Tps<T> result(TpsRep<T>::zero());
940  return result;
941  }
942 }
943 
944 
945 template <class T>
946 Tps<T> Tps<T>::integral(int var) const {
947  if(getVariables() == 0) {
948  throw LogicalError("TpsRep::integral()", "Cannot integrate a constant.");
949  }
950 
951  int trcO = std::min(rep->trcOrd + 1, truncOrder);
952  int maxO = std::min(rep->maxOrd + 1, trcO);
953  TpsRep<T> *p = TpsRep<T>::create(maxO, trcO, getVariables());
954 
955  const T *x = rep->data();
956  T *z = p->data();
957  const int *product = rep->help->getProductArray(var + 1);
958 
959  for(int i = getSize(maxO - 1); i-- > 0;) {
960  int k = product[i];
961  z[k] = x[i] / double(getExponents(k)[var]);
962  }
963 
964  return Tps<T>(p);
965 }
966 
967 
968 template <class T>
970  if(getVariables() == 0) {
971  throw LogicalError("TpsRep::multiplyVariable()",
972  "Cannot multiply a constant by a numbered variable.");
973  }
974 
975  int trcO = std::min(rep->trcOrd + 1, truncOrder);
976  int maxO = std::min(rep->maxOrd + 1, trcO);
977  TpsRep<T> *p = TpsRep<T>::create(maxO, trcO, getVariables());
978 
979  const T *x = rep->data();
980  T *z = p->data();
981  const int *product = rep->help->getProductArray(var + 1);
982 
983  for(int i = getSize(maxO - 1); i-- > 0;) {
984  z[product[i]] = x[i];
985  }
986 
987  return Tps<T>(p);
988 }
989 
990 
991 template <class T>
993  int v1 = getVariables();
994  int v2 = rhs.getVariables();
995 
996  if(v1 != v2) {
997  throw SizeError("TpsRep::scaleMonomials()",
998  "Number of variables inconsistent.");
999  }
1000 
1001  int order = std::min(getMaxOrder(), rhs.getMaxOrder());
1002  int trunc = std::min(getTruncOrder(), rhs.getTruncOrder());
1003 
1004  TpsRep<T> *p = TpsRep<T>::create(std::min(order, trunc), trunc, v1);
1005  const T *x = rep->data();
1006  const T *y = rhs.rep->data();
1007  T *z = p->data();
1008  std::transform(x, x + p->len, y, z, std::multiplies<T>());
1009  return Tps<T>(p);
1010 }
1011 
1012 
1013 template <class T>
1014 Tps<T> Tps<T>::Taylor(const T series[], int order) const {
1015  if(isConstant()) {
1016  return Tps<T>(series[0]);
1017  } else {
1018  Tps<T> x(*this);
1019  x[0] = T(0);
1020  Tps<T> z(series[order]);
1021  for(int maxOrder = 1; maxOrder <= order; maxOrder++) {
1022  z = x.multiply(z, maxOrder);
1023  z[0] = series[order-maxOrder];
1024  }
1025  return z;
1026  }
1027 }
1028 
1029 
1030 template <class T>
1031 int Tps<T>::getMaxOrder() const {
1032  return rep->maxOrd;
1033 }
1034 
1035 
1036 template <class T>
1038  return std::min(rep->trcOrd, truncOrder);
1039 }
1040 
1041 
1042 template <class T>
1044  return (rep->help != 0) ? rep->help->getVariables() : 0;
1045 }
1046 
1047 
1048 template <class T>
1049 int Tps<T>::getSize() const {
1050  return rep->len;
1051 }
1052 
1053 
1054 template <class T>
1055 bool Tps<T>::isConstant() const {
1056  return rep->help == 0;
1057 }
1058 
1059 
1060 template <class T>
1062  return truncOrder;
1063 }
1064 
1065 
1066 template <class T>
1068  truncOrder = order;
1069 }
1070 
1071 
1072 template <class T>
1073 const TpsMonomial &Tps<T>::getExponents(int index) const {
1074  if(rep->help == 0) {
1075  throw LogicalError("Tps::getExponents()",
1076  "Cannot get exponents of a constant.");
1077  }
1078 
1079  return rep->help->getExponents(index);
1080 }
1081 
1082 
1083 template <class T>
1084 int Tps<T>::getOrder(int index) const {
1085  return rep->help ? rep->help->getOrder(index) : 0;
1086 }
1087 
1088 
1089 template <class T>
1090 int Tps<T>::getSize(int order) const {
1091  return rep->help ? rep->help->getSize(order) : 1;
1092 }
1093 
1094 
1095 template <class T> inline
1097 {}
1098 
1099 #endif // CLASSIC_Tps_CC
static const int EXACT
Representation of infinite precision.
Definition: Tps.h:260
int getOrder(int index) const
Get order.
Definition: Tps.hpp:1084
TpsData * help
Definition: Tps.hpp:107
Tps< T > substitute(const Matrix< T > &M) const
Substitute.
Definition: Tps.hpp:614
TpsRep< T > * grab()
Definition: Tps.hpp:202
int trcOrd
Definition: Tps.hpp:101
Bookkeeping class for Tps&lt;T&gt;.
Definition: TpsData.h:35
static Tps< T > makeVarPower(int nVar, int var, int power)
Make power.
Definition: Tps.hpp:391
Definition: rbendmap.h:8
Tps< T > filter(int lowOrder, int highOrder) const
Extract orders.
Definition: Tps.hpp:279
Size error exception.
Definition: SizeError.h:33
int getSize() const
Get number of coefficients.
Definition: Tps.hpp:1049
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
Truncate power series map.
Definition: Tps.h:31
Tps< T > & operator=(const Tps< T > &y)
Definition: Tps.hpp:259
int getDimension() const
Get dimension (number of Tps&lt;T&gt; components).
Definition: Vps.hpp:247
const TpsMonomial & getExponents(int index) const
Get exponents.
Definition: Tps.hpp:1073
TpsRep< T > * rep
Definition: Tps.h:274
Tps()
Definition: Tps.hpp:221
int ncols() const
Get number of columns.
Definition: Array2D.h:307
int getOrder() const
Get order.
Definition: TpsMonomial.cpp:83
Tps< T > & operator/=(const Tps< T > &y)
Divide and assign.
Definition: Tps.hpp:505
int getTruncOrder() const
Get truncation order.
Definition: Tps.hpp:1037
Tps< T > Taylor(const T series[], int n) const
Taylor series.
Definition: Tps.hpp:1014
int len
Definition: Tps.hpp:104
int ref
Definition: Tps.hpp:97
std::istream & get(std::istream &is)
Get Tps from the stream is.
Definition: Tps.hpp:721
const T operator[](int index) const
Get coefficient.
Definition: Tps.hpp:301
bool isConstant() const
Test for constant.
Definition: Tps.hpp:1055
Tps< T > & operator*=(const Tps< T > &y)
Multiply and assign.
Definition: Tps.hpp:499
T evaluate(const Vector< T > &v) const
Substitute.
Definition: Tps.hpp:686
Tps< T > scaleMonomials(const Tps< T > &y) const
Multiply monomial-wise.
Definition: Tps.hpp:992
Tps< T > & operator+=(const Tps< T > &y)
Add and assign.
Definition: Tps.hpp:427
static TpsRep< T > * create(int maxOrder, int trcOrder, int variables)
Definition: Tps.hpp:144
Tps< T > operator+() const
Unary plus.
Definition: Tps.hpp:411
void unique()
Definition: Tps.hpp:55
int size() const
Get array size.
Definition: Array1D.h:228
std::ostream & put(std::ostream &os) const
Put Tps to the stream is.
Definition: Tps.hpp:784
void setMaxOrder(int)
Definition: Tps.hpp:49
Truncated power series.
Definition: Tps.h:27
Tps< T > multiply(const Tps< T > &y, int trunc) const
Truncated multiplication.
Definition: Tps.hpp:823
Definition: Tps.h:28
Zero divide error.
Definition: DivideError.h:32
static Tps< T > makeMonomial(const TpsMonomial &m, const T &t)
Make monomial.
Definition: Tps.hpp:401
Tps< T > inverse(int order=truncOrder) const
Reciprocal value.
Definition: Tps.hpp:897
Tps< T > multiplyVariable(int var) const
Multiply by variable [b]var[/b].
Definition: Tps.hpp:969
bool operator==(const Tps< T > &y) const
Equality operator.
Definition: Tps.hpp:545
bool operator!=(const Tps< T > &y) const
Inequality operator.
Definition: Tps.hpp:602
static int getGlobalTruncOrder()
Get global truncation order.
Definition: Tps.hpp:1061
static TpsData * getTpsData(int nOrd, int nVar)
Definition: TpsData.cpp:43
Tps< T > truncate(int trunc)
Truncate.
Definition: Tps.hpp:295
TpsRep< T > & operator=(const TpsRep< T > &)
~Tps()
Definition: Tps.hpp:253
int precision() const
Definition: Inform.h:115
int getMaxOrder() const
Get maximal order.
Definition: Tps.hpp:1031
void setCoefficient(int index, const T &value)
Set coefficient.
Definition: Tps.hpp:337
Substitution for Tps&lt;T&gt;.
int getVariables() const
Get number of variables.
Definition: Tps.hpp:1043
Exponent array for Tps&lt;T&gt;.
Definition: TpsMonomial.h:31
int getSize(int order) const
Definition: TpsData.h:124
static Tps< T > makeVariable(int nVar, int var)
Make variable.
Definition: Tps.hpp:383
Range error.
Definition: CLRangeError.h:33
Tps< T > integral(int var) const
Partial integral.
Definition: Tps.hpp:946
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1243
Matrix.
Definition: Matrix.h:38
static void release(TpsRep< T > *)
Definition: Tps.hpp:209
int maxOrd
Definition: Tps.hpp:100
Format error exception.
Definition: FormatError.h:32
One-dimensional array.
Definition: Array1D.h:36
static TpsRep< T > * zero()
Definition: Tps.hpp:168
Tps< T > operator-() const
Unary minus.
Definition: Tps.hpp:417
T * data()
Definition: Tps.hpp:118
void clear()
Set to zero.
Definition: Tps.hpp:714
const T getCoefficient(int index) const
Get coefficient.
Definition: Tps.hpp:327
Tps< T > & operator-=(const Tps< T > &y)
Subtract and assign.
Definition: Tps.hpp:462
int getIndex() const
Convert.
Definition: TpsMonomial.cpp:77
Vector.
static void setGlobalTruncOrder(int order)
Set global truncation order.
Definition: Tps.hpp:1067
int nrows() const
Get number of rows.
Definition: Array2D.h:301
Tps< T > derivative(int var) const
Partial derivative.
Definition: Tps.hpp:920
Logical error exception.
Definition: LogicalError.h:33
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
int getVariables() const
Get variables.
Definition: TpsMonomial.cpp:94
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
TpsRep< T > * clone()
Definition: Tps.hpp:184
static int truncOrder
Definition: Tps.h:277