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