OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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// 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
76template <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.
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.
102
103 // The length of the monomial table.
104 int len;
105
106 // The data structure for bookkeeping.
108
109 // Not implemented.
111
112 // May need to add this:
113 // T *dat;
114};
115
116
117template <class T> inline
119 return reinterpret_cast<T *>(this + 1);
120 // Could be changed to:
121 // return dat;
122}
123
124
125template <class T> inline
126void *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
135template <class T> inline
136void 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
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 if(--(p->ref) <= 0) delete p;
211}
212
213
214// Template class Tps<T>.
215// ------------------------------------------------------------------------
216
217template <class T> int Tps<T>::truncOrder = EXACT;
218
219
220template <class T>
222 rep(TpsRep<T>::zero())
223{}
224
225
226template <class T>
227Tps<T>::Tps(int maxOrder, int nVar):
228 rep(TpsRep<T>::create(maxOrder, EXACT, nVar))
229{}
230
231
232template <class T>
233Tps<T>::Tps(const Tps<T> &rhs):
234 rep(rhs.rep->grab())
235{}
236
237
238template <class T>
239Tps<T>::Tps(const T &rhs):
240 rep(TpsRep<T>::zero()) {
241 rep->data()[0] = rhs;
242}
243
244
245template <class T>
246Tps<T>::Tps(int rhs):
247 rep(TpsRep<T>::zero()) {
248 rep->data()[0] = T(rhs);
249}
250
251
252template <class T>
255}
256
257
258template <class T>
260 if(rep != rhs.rep) {
262 rep = rhs.rep->grab();
263 }
264
265 return *this;
266}
267
268
269template <class T>
273 rep->data()[0] = rhs;
274 return *this;
275}
276
277
278template <class T>
279Tps<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
294template <class T>
296 return filter(0, trunc);
297}
298
299
300template <class T>
301const T Tps<T>::operator[](int index) const {
302 return rep->data()[index];
303}
304
305
306template <class T>
308 unique();
309 return rep->data()[index];
310}
311
312
313template <class T>
314const T Tps<T>::operator[](const TpsMonomial &monomial) const {
315 return rep->data()[monomial.getIndex()];
316}
317
318
319template <class T>
321 unique();
322 return rep->data()[monomial.getIndex()];
323}
324
325
326template <class T>
327const 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
336template <class T>
337void 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
354template <class T>
355const 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
368template <class T>
369void 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
382template <class T>
383Tps<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
390template <class T>
391Tps<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
400template <class T>
401Tps<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
410template <class T>
412 return *this;
413}
414
415
416template <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
426template <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
461template <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
498template <class T>
500 return *this = multiply(rhs, truncOrder);
501}
502
503
504template <class T>
506 return *this = multiply(rhs.inverse(truncOrder), truncOrder);
507}
508
509
510template <class T>
512 unique();
513 rep->data()[0] += rhs;
514 return *this;
515}
516
517
518template <class T>
520 unique();
521 rep->data()[0] -= rhs;
522 return *this;
523}
524
525
526template <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
535template <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
544template <class T>
545bool 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
587template <class T>
588bool 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
601template <class T>
602bool Tps<T>::operator!=(const Tps<T> &rhs) const {
603 return !(*this == rhs);
604}
605
606
607template <class T>
608bool Tps<T>::operator!=(const T &rhs) const {
609 return !(*this == rhs);
610}
611
612
613template <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
656template <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
685template <class T>
686T 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
713template <class T>
717}
718
719
720template <class T>
721std::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
783template <class T>
784std::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
822template <class T>
823Tps<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
896template <class T>
897Tps<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
919template <class T>
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
945template <class T>
946Tps<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
968template <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
991template <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
1013template <class T>
1014Tps<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
1030template <class T>
1032 return rep->maxOrd;
1033}
1034
1035
1036template <class T>
1038 return std::min(rep->trcOrd, truncOrder);
1039}
1040
1041
1042template <class T>
1044 return (rep->help != 0) ? rep->help->getVariables() : 0;
1045}
1046
1047
1048template <class T>
1049int Tps<T>::getSize() const {
1050 return rep->len;
1051}
1052
1053
1054template <class T>
1056 return rep->help == 0;
1057}
1058
1059
1060template <class T>
1062 return truncOrder;
1063}
1064
1065
1066template <class T>
1068 truncOrder = order;
1069}
1070
1071
1072template <class T>
1073const 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
1083template <class T>
1084int Tps<T>::getOrder(int index) const {
1085 return rep->help ? rep->help->getOrder(index) : 0;
1086}
1087
1088
1089template <class T>
1090int Tps<T>::getSize(int order) const {
1091 return rep->help ? rep->help->getSize(order) : 1;
1092}
1093
1094
1095template <class T> inline
1097{}
1098
1099#endif // CLASSIC_Tps_CC
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1121
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
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:1043
Tps< T > & operator=(const Tps< T > &y)
Definition: Tps.hpp:259
void setMaxOrder(int)
Definition: Tps.hpp:49
std::ostream & put(std::ostream &os) const
Put Tps to the stream is.
Definition: Tps.hpp:784
Tps< T > multiply(const Tps< T > &y, int trunc) const
Truncated multiplication.
Definition: Tps.hpp:823
Tps< T > substitute(const Matrix< T > &M) const
Substitute.
Definition: Tps.hpp:614
int getSize() const
Get number of coefficients.
Definition: Tps.hpp:1049
void unique()
Definition: Tps.hpp:55
static Tps< T > makeMonomial(const TpsMonomial &m, const T &t)
Make monomial.
Definition: Tps.hpp:401
Tps< T > multiplyVariable(int var) const
Multiply by variable [b]var[/b].
Definition: Tps.hpp:969
Tps< T > integral(int var) const
Partial integral.
Definition: Tps.hpp:946
~Tps()
Definition: Tps.hpp:253
bool operator==(const Tps< T > &y) const
Equality operator.
Definition: Tps.hpp:545
const TpsMonomial & getExponents(int index) const
Get exponents.
Definition: Tps.hpp:1073
static int getGlobalTruncOrder()
Get global truncation order.
Definition: Tps.hpp:1061
Tps< T > truncate(int trunc)
Truncate.
Definition: Tps.hpp:295
Tps< T > & operator+=(const Tps< T > &y)
Add and assign.
Definition: Tps.hpp:427
TpsRep< T > * rep
Definition: Tps.h:274
Tps< T > inverse(int order=truncOrder) const
Reciprocal value.
Definition: Tps.hpp:897
void setCoefficient(int index, const T &value)
Set coefficient.
Definition: Tps.hpp:337
Tps< T > filter(int lowOrder, int highOrder) const
Extract orders.
Definition: Tps.hpp:279
Tps< T > derivative(int var) const
Partial derivative.
Definition: Tps.hpp:920
static const int EXACT
Representation of infinite precision.
Definition: Tps.h:260
const T operator[](int index) const
Get coefficient.
Definition: Tps.hpp:301
static void setGlobalTruncOrder(int order)
Set global truncation order.
Definition: Tps.hpp:1067
static int truncOrder
Definition: Tps.h:277
Tps< T > operator+() const
Unary plus.
Definition: Tps.hpp:411
static Tps< T > makeVarPower(int nVar, int var, int power)
Make power.
Definition: Tps.hpp:391
Tps< T > scaleMonomials(const Tps< T > &y) const
Multiply monomial-wise.
Definition: Tps.hpp:992
Tps()
Definition: Tps.hpp:221
Tps< T > Taylor(const T series[], int n) const
Taylor series.
Definition: Tps.hpp:1014
const T getCoefficient(int index) const
Get coefficient.
Definition: Tps.hpp:327
T evaluate(const Vector< T > &v) const
Substitute.
Definition: Tps.hpp:686
bool isConstant() const
Test for constant.
Definition: Tps.hpp:1055
static Tps< T > makeVariable(int nVar, int var)
Make variable.
Definition: Tps.hpp:383
Tps< T > & operator*=(const Tps< T > &y)
Multiply and assign.
Definition: Tps.hpp:499
Tps< T > operator-() const
Unary minus.
Definition: Tps.hpp:417
std::istream & get(std::istream &is)
Get Tps from the stream is.
Definition: Tps.hpp:721
int getTruncOrder() const
Get truncation order.
Definition: Tps.hpp:1037
int getMaxOrder() const
Get maximal order.
Definition: Tps.hpp:1031
int getOrder(int index) const
Get order.
Definition: Tps.hpp:1084
void clear()
Set to zero.
Definition: Tps.hpp:714
Tps< T > & operator-=(const Tps< T > &y)
Subtract and assign.
Definition: Tps.hpp:462
bool operator!=(const Tps< T > &y) const
Inequality operator.
Definition: Tps.hpp:602
Tps< T > & operator/=(const Tps< T > &y)
Divide and assign.
Definition: Tps.hpp:505
Definition: Tps.hpp:76
int len
Definition: Tps.hpp:104
TpsRep< T > & operator=(const TpsRep< T > &)
TpsData * help
Definition: Tps.hpp:107
T * data()
Definition: Tps.hpp:118
int trcOrd
Definition: Tps.hpp:101
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:100
static TpsRep< T > * zero()
Definition: Tps.hpp:168
TpsRep< T > * grab()
Definition: Tps.hpp:202
int ref
Definition: Tps.hpp:97
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.
Definition: TpsMonomial.cpp:77
int getVariables() const
Get variables.
Definition: TpsMonomial.cpp:94
int getOrder() const
Get order.
Definition: TpsMonomial.cpp:83
Substitution for Tps<T>.
int getDimension() const
Get dimension (number of Tps<T> components).
Definition: Vps.hpp:247
Range error.
Definition: CLRangeError.h:33
Zero divide error.
Definition: DivideError.h:32
Format error exception.
Definition: FormatError.h:32
Logical error exception.
Definition: LogicalError.h:33
Size error exception.
Definition: SizeError.h:33
int precision() const
Definition: Inform.h:112