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