OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
FTps.hpp
Go to the documentation of this file.
1#ifndef CLASSIC_FTps_CC
2#define CLASSIC_FTps_CC
3
4// ------------------------------------------------------------------------
5// $RCSfile: FTps.cpp,v $
6// ------------------------------------------------------------------------
7// $Revision: 1.5.2.15 $
8// ------------------------------------------------------------------------
9// Copyright: see Copyright.readme
10// ------------------------------------------------------------------------
11//
12// Template class: FTps<T,N>
13// Representation of a truncated power series
14// with values of type T and a fixed number of variables N.
15//
16// ------------------------------------------------------------------------
17// Class category: FixedAlgebra
18// ------------------------------------------------------------------------
19//
20// $Date: 2003/11/07 18:06:20 $
21// $Author: dbruhwil $
22//
23// ------------------------------------------------------------------------
24
25//#define DEBUG_FTps_CC
26
27#include "FixedAlgebra/FTps.h"
29#include "Algebra/Array1D.h"
38#include <climits>
39#include <algorithm>
40#include <iomanip>
41#include <iostream>
42#include <functional>
43#include <string>
44
45
46// Representation class FTpsRep<T,N>.
47// The representation of an FTps<T,N> is based on a mechanism which avoids
48// frequent memory allocations.
49// This code contains various tweaks for speed.
50// ------------------------------------------------------------------------
52template<class T, int N>
53const int FTps<T, N> :: EXACT = INT_MAX;
55template <class T, int N>
56class FTpsRep {
57
58 // The only classes allowed access to the representation.
59 friend class FTps<T, N>;
60 friend class FVps<T, N>;
62 // Constructor.
63 FTpsRep(int minOrder, int maxOrder, int trcOrder);
65 // Destructor.
68 // Clear FTpsRep<T,N> to zero.
69 void clear();
71 // Clear FTpsRep<T,N> orders minOrder through maxOrder to zero.
72 void clear(int minOrder, int maxOrder);
74 // Return beginning of monomial array.
75 T *begin() const
76 { return data; }
77
78 // Return end of monomial array.
79 T *end() const
80 { return data + len; }
81
82 // Return beginning of coefficient storage for given order.
83 T *begin(int order) const
84 { return data + FTpsData<N>::orderStart(order); }
85
86 // Return end of coefficient storage for given order.
87 T *end(int order) const
88 { return data + FTpsData<N>::orderEnd(order); }
89
90 // Pointer to next object in memory pool, when free.
92
93 // Reference count.
94 int ref;
95
96 // Orders of this object.
97 int minOrd; // The lowest order which contains non-zero coefficients.
98 int maxOrd; // The highest order which contains non-zero coefficients.
99 int trcOrd; // The truncation (precision) order, beyond which terms are truncated.
100 int allocOrd; // The allocation order: the maximum order for which this FTpsRep has memory.
101 // Note: We must have: 0 <= minOrd <= maxOrd <= allocOrd < EXACT,
102 // maxOrd <= trcOrd,
103 // and trcOrd _either_ <= allocOrd _or_ = EXACT.
104 // Also, if trcOrd == EXACT, then (initially) allocOrd == maxOrd.
105
106 // Length of coefficient array.
107 int len;
108
109 // Coefficient array.
111};
112
113
114// Implementation of representation class FTpsRep<T,N>.
115// ------------------------------------------------------------------------
116
117template <class T, int N>
118FTpsRep<T, N>::FTpsRep(int minOrder, int maxOrder, int trcOrder):
119 next(0), ref(1), minOrd(minOrder), maxOrd(maxOrder), trcOrd(trcOrder) {
124 data = new T[len];
125}
126
127
128template <class T, int N>
130 delete [] data;
131}
132
133
134template <class T, int N>
136 clear(minOrd, maxOrd);
137}
138
139
140template <class T, int N>
141void FTpsRep<T, N>::clear(int minOrder, int maxOrder) {
142 std::fill(data + FTpsData<N>::orderStart(minOrder),
143 data + FTpsData<N>::orderEnd(maxOrder), T(0));
144}
145
146
147
148// Implementation of template class FTps<T,N>.
149// ------------------------------------------------------------------------
150
151template <class T, int N>
153
154template <class T, int N>
156
157
158template <class T, int N>
160 itsRep = allocate(0, 0, EXACT);
161 itsRep->data[0] = T(0);
163
164
165template <class T, int N>
167 itsRep = rhs.itsRep;
168 itsRep->ref++;
169}
170
172template <class T, int N>
173FTps<T, N>::FTps(int minOrder, int maxOrder, int trcOrder) {
174 itsRep = allocate(minOrder, maxOrder, trcOrder);
175 itsRep->clear(minOrder, maxOrder);
176}
177
178
179template <class T, int N>
180FTps<T, N>::FTps(const T &rhs) {
181 itsRep = allocate(0, 0, EXACT);
182 itsRep->data[0] = rhs;
183}
184
185
186template <class T, int N>
188 itsRep = allocate(0, 0, EXACT);
189 itsRep->data[0] = T(rhs);
190}
191
192
193template <class T, int N>
195 itsRep->ref--;
196 if(itsRep->ref == 0) deallocate(itsRep);
197}
199
200template <class T, int N>
202 if(itsRep != rhs.itsRep) {
203 itsRep->ref--;
204 if(itsRep->ref == 0) deallocate(itsRep);
205 itsRep = rhs.itsRep;
206 itsRep->ref++;
207 }
208 return *this;
209}
211
212template <class T, int N>
214 itsRep->ref--;
215 if(itsRep->ref == 0) deallocate(itsRep);
216 itsRep = allocate(0, 0, EXACT);
217 itsRep->data[0] = T(rhs);
218 return *this;
219}
220
221
222template <class T, int N>
223const T FTps<T, N>::getCoefficient(int index) const {
224 if(index < 0) {
225 std::cerr << " <*** WARNING ***> from FTps<T,N>::getCoefficient(index):\n"
226 << " No coefficient has a negative index; returning 0." << std::endl;
227 return T(0);
228 }
229
230 if(index < orderStart(itsRep->minOrd) || orderEnd(itsRep->maxOrd) <= index) return T(0);
231 return itsRep->data[index];
232}
234
235template <class T, int N>
236void FTps<T, N>::setCoefficient(int index, const T &value) {
237 if(index < 0) {
238 std::cerr << " <*** WARNING ***> from FTps<T,N>::setCoefficient(index, value):\n"
239 << " Ignoring request because index < 0." << std::endl;
240 return;
241 }
243 int order = FTpsData<N>::getOrder(index);
244
245 // Ignore requests beyond truncation order.
246 if(order > itsRep->trcOrd) return;
247
248 // If necessary, allocate more space.
249 // (This happens _only_ if itsRep->trcOrd == EXACT.)
250 if(order > itsRep->allocOrd) grow(order, EXACT);
252 // Set coefficient.
253 unique();
254 if(order < itsRep->minOrd) setMinOrder(order);
255 else if(order > itsRep->maxOrd) setMaxOrder(order);
256 itsRep->data[index] = value;
258
259
260template <class T, int N>
261const T FTps<T, N>::getCoefficient(const FMonomial<N> &mono) const {
262 int index = FTpsData<N>::getIndex(mono);
263 return getCoefficient(index);
264}
265
267template <class T, int N>
268void FTps<T, N>::setCoefficient(const FMonomial<N> &mono, const T &value) {
269 int index = FTpsData<N>::getIndex(mono);
270 setCoefficient(index, value);
271}
273
274template <class T, int N>
275inline const T FTps<T, N>::operator[](int index) const {
276 return itsRep->data[index];
277}
278
279
280template <class T, int N>
281inline T &FTps<T, N>::operator[](int index) {
282 unique();
283 return itsRep->data[index];
285
286
287template <class T, int N>
288const T FTps<T, N>::operator[](const FMonomial<N> &mono) const {
289 int index = FTpsData<N>::getIndex(mono);
290 return itsRep->data[index];
291}
292
293
294template <class T, int N>
296 unique();
297 int index = FTpsData<N>::getIndex(mono);
298 return itsRep->data[index];
299}
300
301
302template <class T, int N>
303int FTps<T, N>::getSize(int order) {
304 return FTpsData<N>::getSize(order);
305}
307
308template <class T, int N>
310 return FTpsData<N>::getExponents(index);
311}
312
313
314template <class T, int N>
316 return FTpsData<N>::getIndex(mono);
317}
318
319
320template <class T, int N>
321void FTps<T, N>::setMinOrder(int order) {
322 // Check sanity.
323 if(order == EXACT)
324 throw LogicalError("FTps<T,N>::setMinOrder(order)", "Cannot set minimum order to EXACT.");
325 if(order < 0)
326 throw LogicalError("FTps<T,N>::setMinOrder(order)", "Cannot set a negative minimum order.");
327 if(order > globalTruncOrder)
328 throw LogicalError("FTps<T,N>::setMinOrder(order)",
329 "Cannot set minimum order beyond globalTruncOrder.");
330
331 unique();
332 // Ignore requests beyond truncation order, but issue a warning.
333 if(order > itsRep->trcOrd) {
334 std::cerr << " <*** WARNING ***> from FTps<T,N>::setMinOrder(order):\n"
335 << " Cannot set minimum order above truncation order;\n"
336 << " raising both minimum and maximum orders to truncation order." << std::endl;
337 order = itsRep->trcOrd;
338 }
339 // If necessary, allocate more space.
340 // (This can happen _only_ if itsRep->trcOrd == EXACT.)
341 else if(order > itsRep->allocOrd) grow(order, EXACT);
343 // If raising minOrd above maxOrd, drag max with it and clear that order.
344 if(order > itsRep->maxOrd) {
345 itsRep->maxOrd = order;
346 itsRep->clear(order, order);
348 // If decreasing minOrd, stuff zeroes into new coefficients.
349 else if(order < itsRep->minOrd) itsRep->clear(order, itsRep->minOrd - 1);
351 // Set new minimum order.
352 itsRep->minOrd = order;
353}
355
356template <class T, int N>
357void FTps<T, N>::setMaxOrder(int order) {
358 // Check sanity.
359 if(order == EXACT)
360 throw LogicalError("FTps<T,N>::setMaxOrder(order)", "Cannot set maximum order to EXACT.");
361 if(order < 0)
362 throw LogicalError("FTps<T,N>::setMaxOrder(order)", "Cannot set a negative maximum order.");
363 if(order > globalTruncOrder)
364 throw LogicalError("FTps<T,N>::setMaxOrder(order)",
365 "Cannot set maximum order beyond globalTruncOrder.");
367 unique();
368 // Ignore requests beyond truncation order, but issue a warning.
369 if(order > itsRep->trcOrd) {
370 std::cerr << " <*** WARNING ***> from FTps<T,N>::setMaxOrder(order):\n"
371 << " Cannot set maximum order above truncation order;\n"
372 << " raising maximum order to truncation order." << std::endl;
373 order = itsRep->trcOrd;
375 // If necessary, allocate more space.
376 // (This can happen _only_ if itsRep->trcOrd == EXACT.)
377 else if(order > itsRep->allocOrd) grow(order, EXACT);
378
379 // If increasing maxOrd, stuff zeroes into new coefficients.
380 if(order > itsRep->maxOrd) itsRep->clear(itsRep->maxOrd + 1, order);
381 // If lowering maxOrd below minOrd, drag min with it and clear that order.
382 else if(order < itsRep->minOrd) {
383 itsRep->minOrd = order;
384 itsRep->clear(order, order);
385 }
386
387 // Set new maximum order.
388 itsRep->maxOrd = order;
389}
390
392template <class T, int N>
394 // Check sanity.
395 if(order != EXACT && order < 0)
396 throw LogicalError("FTps<T,N>::setTruncOrder(order)", "Cannot set a negative truncation order.");
397 if(order != EXACT && order > globalTruncOrder)
398 throw LogicalError("FTps<T,N>::setTruncOrder(order)",
399 "Cannot set truncation order beyond globalTruncOrder.");
400
401 unique();
402 // If lowering trcOrd below minOrd, drag min and max with it, and clear that order.
403 if(order < itsRep->minOrd) {
404 itsRep->minOrd = order;
405 itsRep->maxOrd = order;
406 itsRep->clear(order, order);
407 }
408 // If lowering trcOrd below maxOrd, drag max with it.
409 else if(order < itsRep->maxOrd) itsRep->maxOrd = order;
410 // If necessary, allocate more space.
411 else if(order != EXACT && order > itsRep->allocOrd) grow(itsRep->maxOrd, order);
412
413 // Set new truncation order.
414 itsRep->trcOrd = order;
415}
416
417
418template <class T, int N>
420 // Check sanity.
421 if(order == EXACT)
422 throw LogicalError("FTps<T,N>::setGlobalTruncOrder(order)", "Cannot make globalTruncOrder EXACT.");
423 if(order <= 0)
424 throw LogicalError("FTps<T,N>::setGlobalTruncOrder(order)",
425 "Cannot set a negative global truncation order.");
426
427 globalTruncOrder = order;
428 FTpsData<N>::setup(order);
429}
430
431
432template <class T, int N>
434 return FTpsData<N>::getProductArray(index);
435}
436
437
438template <class T, int N>
440 return FTpsData<N>::getVariableList(index);
441}
442
443
444template <class T, int N>
447}
448
449
450template <class T, int N>
451FTps<T, N> FTps<T, N>::filter(int minOrder, int maxOrder, int trcOrder) const {
452 // Default: trcOrder = EXACT
453 checkOrders("filter(minOrder, maxOrder, trcOrder)", minOrder, maxOrder, trcOrder);
454
455 // Compute order limits.
456 int myMin = std::max(minOrder, itsRep->minOrd);
457 int myMax = std::min(maxOrder, itsRep->maxOrd);
458 int myTrc = std::min(trcOrder, itsRep->trcOrd);
459
460 bool OLflag = true;
461 if(myMin > myMax) { // no overlap exists
462 OLflag = false;
463 myMin = std::min(minOrder, myTrc);
464 myMax = std::min(maxOrder, myTrc);
465 }
466 // Construct filtered FTpsRep.
467 FTps<T, N> result(myMin, myMax, myTrc);
468 if(OLflag) std::copy(begin(myMin), end(myMax), result.begin(myMin));
469
470 return result;
471}
472
473
474template <class T, int N> inline
476 return filter(0, trunc, trunc);
477}
478
479
480template <class T, int N>
482 FTps<T, N> result(1, 1, EXACT);
483 result[var + 1] = T(1);
484 return result;
485}
486
487
488template <class T, int N>
490 FMonomial<N> mono;
491 mono[var] = order;
492 FTps<T, N> result(order, order, EXACT);
493 result[mono] = T(1);
494 return result;
495}
496
497
498template <class T, int N>
499FTps<T, N> FTps<T, N>::makeMonomial(int index, const T &val) {
500 int order = FTpsData<N>::getOrder(index);
501 FTps<T, N> result(order, order, EXACT);
502 result[index] = val;
503 return result;
504}
505
506
507template <class T, int N>
509 int order = mono.getOrder();
510 FTps<T, N> result(order, order, EXACT);
511 result[mono] = val;
512 return result;
513}
514
515
516template <class T, int N>
518 return *this;
519}
520
521
522template <class T, int N>
524 int minOrder = getMinOrder();
525 int maxOrder = getMaxOrder();
526 FTps<T, N> result(minOrder, maxOrder, getTruncOrder());
527 std::transform(begin(minOrder), end(maxOrder), result.begin(minOrder), std::negate<T>());
528 return result;
529}
530
531
532template <class T, int N>
534 return *this = *this + rhs;
535}
536
537
538template <class T, int N>
540 return *this = *this - rhs;
541}
542
543
544template <class T, int N>
546 return *this = multiply(rhs);
547}
548
549
550template <class T, int N>
552 return *this = divide(rhs);
553}
554
555
556template <class T, int N>
558 unique();
559 setMinOrder(0);
560 itsRep->data[0] += rhs;
561 return *this;
562}
563
564
565template <class T, int N>
567 unique();
568 setMinOrder(0);
569 itsRep->data[0] -= rhs;
570 return *this;
571}
572
573
574template <class T, int N>
576 unique();
577 std::transform(begin(getMinOrder()), end(getMaxOrder()), begin(getMinOrder()),
578 std::bind(std::multiplies<T>(), std::placeholders::_1, rhs));
579 return *this;
580}
581
582template <class T, int N>
584 if(rhs == T(0)) throw DivideError("FTps::operator/=()");
585 return *this *= T(1) / rhs;
586}
587
588template <class T, int N>
590 // Determine orders of result.
591 int f_min = getMinOrder();
592 int g_min = rhs.getMinOrder();
593 int f_max = getMaxOrder();
594 int g_max = rhs.getMaxOrder();
595 int trcOrder = std::min(getTruncOrder(), rhs.getTruncOrder());
596 int minOrder = std::max(f_min, g_min);
597 int maxOrder = std::min(f_max, g_max);
598
599 if(minOrder <= maxOrder) { // overlap exists
600 FTps<T, N> result(minOrder, maxOrder, trcOrder);
601 std::transform(begin(minOrder), end(maxOrder), rhs.begin(minOrder),
602 result.begin(minOrder), std::multiplies<T>());
603 return result;
604 } else // no overlap ==> complain big time!
605 throw LogicalError("FTps<T,N>::scaleMonomials(rhs)", "No overlap exists.");
606}
607
608
609template <class T, int N>
610FTps<T, N> FTps<T, N>::multiplyVariable(int var, int trunc) const {
611 // Default: trunc = EXACT
612
613 int f_min = getMinOrder();
614 if(trunc <= f_min) {
615#ifdef DEBUG_FTps_CC
616 std::cerr << " <*** WARNING ***> from FTps<T,N>::multiplyVariable(var, trunc):\n"
617 << " Result truncated out of existence; returning a zero polynomial."
618 << std::endl;
619#endif
620 return FTps<T, N>(trunc, trunc, trunc);
621 } else {
622 // Determine orders of result.
623 int trcOrder = getTruncOrder();
624 if (trcOrder == EXACT) {
625 trcOrder = trunc;
626 } else {
627 ++ trcOrder;
628 trcOrder = std::min(trcOrder, trunc);
629 }
630 // trcOrder = (trcOrder == EXACT) ? trunc : std::min((++trcOrder), trunc);
631 int maxOrder = std::min(1 + getMaxOrder(), trcOrder);
632
633 // Allocate result.
634 FTps<T, N> result(1 + f_min, maxOrder, trcOrder);
635 const T *f = begin();
636 T *g = result.begin();
637 const Array1D<int> &product = FTpsData<N>::getProductArray(var + 1);
638
639 // Do multiplication.
640 int ie = orderStart(maxOrder);
641 for(int i = orderStart(f_min); i < ie; i++)
642 g[product[i]] = f[i];
643 return result;
644 }
645
646}
647
648
649template <class T, int N>
650FTps<T, N> FTps<T, N>::multiply(const FTps<T, N> &rhs, int trunc) const {
651 // Default: trunc = EXACT
652
653 //Determine orders of result.
654 int trcOrder;
655 if(itsRep->trcOrd == EXACT) {
656 if(rhs.itsRep->trcOrd == EXACT) trcOrder = EXACT;
657 else trcOrder = itsRep->minOrd + rhs.itsRep->trcOrd;
658 } else if(rhs.itsRep->trcOrd == EXACT) trcOrder = itsRep->trcOrd + rhs.itsRep->minOrd;
659 else trcOrder = std::min(itsRep->trcOrd + rhs.itsRep->minOrd, itsRep->minOrd + rhs.itsRep->trcOrd);
660 trcOrder = std::min(trcOrder, trunc);
661 int maxOrder = std::min(itsRep->maxOrd + rhs.itsRep->maxOrd, trcOrder);
662 int minOrder = itsRep->minOrd + rhs.itsRep->minOrd;
663
664 if(minOrder <= maxOrder) {
665 // Allocate result.
666 FTps<T, N> result(minOrder, maxOrder, trcOrder);
667
668 // Assign data pointers and starting indices.
669 T *f = begin();
670 T *g = rhs.begin();
671 T *h = result.begin();
672 int first_f = orderStart(itsRep->minOrd);
673 int first_g = orderStart(rhs.itsRep->minOrd);
674
675 int f_max = itsRep->maxOrd;
676 int g_max = std::min(rhs.itsRep->maxOrd, maxOrder);
677
678 // Loop over orders in rhs.
679 for(int gOrd = rhs.itsRep->minOrd; gOrd <= g_max; gOrd++) {
680 // Set ending indices.
681 int last_f = orderEnd(std::min(f_max, maxOrder - gOrd));
682 int last_g = orderEnd(gOrd);
683 // Do multiplies for each entry (of order gOrd) in rhs.
684 for(int j = first_g; j < last_g; j++) {
685 T gj = g[j];
686 if(gj != T(0)) {
688 for(int i = first_f; i < last_f; i++) h[prod[i]] += f[i] * gj;
689 }
690 }
691 // Reset starting index for next order of rhs.
692 first_g = last_g;
693 }
694 return result;
695 } else {
696#ifdef DEBUG_FTps_CC
697 std::cerr << " <*** WARNING ***> from FTps<T,N>::multiply(rhs, trunc):\n"
698 << " Result truncated out of existence; returning a zero polynomial."
699 << std::endl;
700#endif
701 return FTps<T, N>(trcOrder, trcOrder, trcOrder);
702 }
703}
704
705
706template <class T, int N>
708 // Default: trunc = EXACT
709
710 // Check sanity.
711 T b0 = itsRep->data[0];
712 if(b0 == T(0) || itsRep->minOrd != 0) {
713 std::cerr << " <*** ERROR ***> in FTps::inverse():\n"
714 << " Cannot invert a polynomial with zero constant term." << std::endl;
715 throw DivideError("FTps::inverse()");
716 }
717
718 // Get orders.
719 int trcOrder = std::min(itsRep->trcOrd, trunc);
720 int maxOrder = std::min(itsRep->maxOrd, trcOrder);
721 if(trcOrder > globalTruncOrder)
722 throw LogicalError("FTps::inverse(trunc)", "Truncation order exceeds globalTruncOrder!");
723
724 // Allocate result.
725 FTps<T, N> result(0, trcOrder, trcOrder);
726
727 // Initialisations.
728 const T *b = itsRep->data;
729 T *c = result.itsRep->data;
730 c[0] = T(1) / b0;
731 T neg_c0 = -c[0];
732
733 // Return trivial result.
734 if(trcOrder == 0) return result;
735
736 // Loop over orders to construct.
737 for(int m = 1; m <= trcOrder; ++m) {
738 // Use the c_k's from previous orders to build this order.
739 for(int mc = 0; mc < m; ++mc) {
740 int mb = m - mc;
741 if(mb > maxOrder) continue;
742 int start_c = orderStart(mc), end_c = orderEnd(mc);
743 int start_b = orderStart(mb), end_b = orderEnd(mb);
744 for(int k = start_c; k < end_c; ++k) {
745 T ck = c[k];
746 if(ck != T(0)) {
748 for(int i = end_b; i-- > start_b;) c[prod[i]] += b[i] * ck;
749 }
750 }
751 }
752 int je = orderEnd(m);
753 for(int j = orderStart(m); j < je; ++j) c[j] *= neg_c0;
754 }
755
756 return result;
757}
758
759
760template <class T, int N>
761FTps<T, N> FTps<T, N>::divide(const FTps<T, N> &rhs, int trunc) const {
762 // Default: trunc = EXACT
763
764 // Algorithm: To compute C = A / B, we may form A = B * C and equate coefficients
765 // of like terms on each side. The resulting system of equations has a "triangular"
766 // nature and can be solved explicitly in an order-by-order fashion. The
767 // coefficients of C are given by
768 // c_0 = a_0 / b_0,
769 // and c_j = (a_j - \sum_{i+k=j, i!=0} b_i * c_k) / b_0, for j!=0.
770 // These formulae hold for multivariate polynomials if we interpret the subscripts
771 // j, i, and k as exponent vectors.
772
773 // Check sanity.
774 T b0 = rhs.itsRep->data[0];
775 if(b0 == T(0) || rhs.itsRep->minOrd != 0) {
776 std::cerr << " <*** ERROR ***> in FTps::divide(rhs,trunc):\n"
777 << " Cannot divide by a polynomial with zero constant term." << std::endl;
778 throw DivideError("FTps::divide()");
779 }
780
781 // Get orders.
782 int a_min = getMinOrder(), a_max = getMaxOrder(), a_trc = getTruncOrder();
783 int b_max = rhs.getMaxOrder(), b_trc = rhs.getTruncOrder();
784 int c_trc;
785 if(b_trc == EXACT) c_trc = std::min(a_trc, trunc);
786 else { c_trc = std::min(a_trc, b_trc + a_min); c_trc = std::min(c_trc, trunc); }
787 if(c_trc > globalTruncOrder)
788 throw LogicalError("FTps::divide(rhs,trunc)", "Truncation order exceeds globalTruncOrder!");
789 int c_max = c_trc, c_min = a_min;
790 int ac_max_min = std::min(a_max, c_max);
791
792 // Allocate result.
793 FTps<T, N> result(c_min, c_max, c_trc);
794
795 // Initialisations.
796 std::copy(begin(c_min), end(ac_max_min), result.begin(c_min)); // start w/ C = A
797 const T *b = rhs.itsRep->data;
798 T *c = result.itsRep->data;
799 T b0inv = T(1) / b0;
800 if(c_min == 0) c[0] *= b0inv;
801
802 // Return trivial result.
803 if(c_trc == 0) return result;
804
805 // Loop over orders to construct.
806 int mi = std::max(1, c_min);
807 for(int m = mi; m <= c_max; ++m) {
808 // Use the lower-order c_k's to build the present order.
809 for(int mc = c_min; mc < m; ++mc) {
810 int mb = m - mc;
811 if(mb > b_max) continue;
812 int start_c = orderStart(mc), end_c = orderEnd(mc);
813 int start_b = orderStart(mb), end_b = orderEnd(mb);
814 for(int k = start_c; k < end_c; ++k) {
815 T ck = c[k];
816 if(ck != T(0)) {
818 for(int i = end_b; i-- > start_b;) c[prod[i]] -= b[i] * ck;
819 }
820 }
821 }
822 int je = orderEnd(m);
823 for(int j = orderStart(m); j < je; ++j) c[j] *= b0inv;
824 }
825
826 return result;
827}
828
829
830template <class T, int N>
831bool FTps<T, N>::operator==(const FTps<T, N> &rhs) const {
832 if(itsRep == rhs.itsRep) return true;
833 // else ...
834
835 // Determine ranges (of indices) to test.
836 int r_trc = std::min(getTruncOrder(), rhs.getTruncOrder());
837 int f_min = orderStart(getMinOrder()), f_max = orderEnd(std::min(getMaxOrder(), r_trc));
838 int g_min = orderStart(rhs.getMinOrder()), g_max = orderEnd(std::min(rhs.getMaxOrder(), r_trc));
839 int r_min = std::min(f_min, g_min), r_max = std::max(f_max, g_max);
840
841 const T *f = begin();
842 const T *g = rhs.begin();
843
844 // Test *this == rhs (f == g).
845 if(g_min < f_max && f_min < g_max) { // overlap exists
846 int i = r_min, fg_max_min = std::min(f_max, g_max);
847 for(; i < g_min; i++) if(f[i] != T(0)) return false; //: test below
848 for(; i < f_min; i++) if(g[i] != T(0)) return false; // overlap
849 for(; i < fg_max_min; i++) if(f[i] != g[i]) return false; //: test overlap
850 for(; i < f_max; i++) if(f[i] != T(0)) return false; //: test above
851 for(; i < g_max; i++) if(g[i] != T(0)) return false; // overlap
852 } else { // gap exists
853 if(f_max <= g_min) { // |f| < |g|
854 for(int i = r_min ; i < f_max; i++) if(f[i] != T(0)) return false;
855 for(int i = g_min ; i < r_max; i++) if(g[i] != T(0)) return false;
856 } else { // |g| < |f|
857 for(int i = r_min; i < g_max; i++) if(g[i] != T(0)) return false;
858 for(int i = f_min; i < r_max; i++) if(f[i] != T(0)) return false;
859 }
860 }
861
862 return true;
863}
864
865
866template <class T, int N>
867bool FTps<T, N>::operator==(const T &rhs) const {
868 int f_min = getMinOrder();
869 const T *f = begin();
870
871 if(f_min == 0) {
872 if(*f != rhs) return false;
873 f_min++;
874 } else if(rhs != T(0)) return false;
875
876 int i = orderStart(f_min);
877 int iend = orderEnd(getMaxOrder());
878 for(; i < iend; i++)
879 if(f[i] != T(0)) return false;
880
881 return true;
882}
883
884
885template <class T, int N>
886bool FTps<T, N>::operator!=(const FTps<T, N> &rhs) const {
887 return !(*this == rhs);
888}
889
890
891template <class T, int N>
892bool FTps<T, N>::operator!=(const T &rhs) const {
893 return !(*this == rhs);
894}
895
896
897template <class T, int N>
899 int size = getSize(maxOrder);
900
901 // Allocate result.
902 Array1D<T> result(size);
903
904 // Initialize pointers to monomials and argument vector.
905 T *mon = result.begin();
906 const T *z = rhs.begin();
907
908 // Constant term.
909 *mon++ = T(1);
910
911 // Linear terms.
912 if(maxOrder > 0) std::copy(z, z + N, mon);
913
914 // Higher-order terms.
915 if(maxOrder > 1) {
916 mon += N;
917 int N1 = N - 1;
918 int m = 2;
919 for(; m <= maxOrder; ++m) {
920 // Build monomials of order m from those of order m-1.
921 T *monx = mon; // Remember where to stop.
922 for(int k = 0, k1 = N1; k < N; k++, k1--) {
923 T zk = z[k]; // The zk times monomials
924 T *mona = monx - FTpsData<N>::orderStart(m, k1); // [mona..monx) yield the
925 while(mona != monx) *mon++ = zk * *mona++; // next ones of order m.
926 }
927 }
928 }
929
930 return result;
931}
932
933template <class T, int N>
935 // Note: We evaluate the linear part separately
936 // not out of necessity, but to speed execution.
937
938 // Get coefficient array, f, argument vector, z, and orders.
939 const T *f = begin();
940 const T *z = rhs.begin();
941 int minOrder = getMinOrder();
942 int maxOrder = getMaxOrder();
943
944 // Allocate array for monomials and pointer to run along it.
945 // Using static local variable to avoid fragmenting memory.
946 // Last allocated monoms array is never deleted, but OS
947 // will take care of this when program exits.
948 static T *monoms = 0;
949 static int myOrd = -1;
950 if(maxOrder > myOrd) {
951 if(monoms) delete [] monoms;
952 monoms = new T[getSize(maxOrder)];
953 myOrd = maxOrder;
954 }
955 T *mon = monoms;
956
957 // Initialize monomials and result.
958 *mon++ = T(1);
959 T result = T(0);
960 if(minOrder == 0) {
961 result = *f++;
962 if(maxOrder == 0) return result;
963 } else f++;
964
965 // Load order one monomials.
966 std::copy(z, z + N, mon);
967
968 // Accumulate linear contribution.
969 T *monx = mon + N;
970 if(minOrder <= 1) while(mon != monx) result += *f++ * *mon++;
971 else { f += N; mon = monx; }
972
973 // Evaluate higher-order contributions.
974 // First build monomials below minOrder.
975 int N1 = N - 1;
976 int m = 2;
977 for(; m < minOrder; m++) {
978 // Build monomials of order m from those of order m-1.
979 monx = mon; // Remember where to stop.
980 for(int k = 0, k1 = N1; k < N; k++, k1--) {
981 T zk = z[k]; // The zk times monomials
982 T *mona = monx - FTpsData<N>::orderStart(m, k1); // [mona..monx)
983 while(mona != monx) { // yield the next ones
984 *mon++ = zk * *mona++; // of order m.
985 f++; // Skip coefficient.
986 }
987 }
988 }
989 // Now add in the higher-order terms.
990 for(; m <= maxOrder; m++) {
991 // Build monomials of order m from those of order m-1.
992 monx = mon; // Remember where to stop.
993 for(int k = 0, k1 = N1; k < N; k++, k1--) {
994 T zk = z[k]; // The zk times monomials
995 T *mona = monx - FTpsData<N>::orderStart(m, k1); // [mona..monx)
996 while(mona != monx) { // yield the next ones
997 *mon = zk * *mona++; // of order m.
998 result += *f++ * *mon++; // Accumulate result.
999 }
1000 }
1001 }
1002
1003 return result;
1004}
1005
1006
1007template <class T, int N>
1009 // Default: trunc = EXACT
1010
1011 // Get orders.
1012 Array1D<int> ordersL(3), ordersR(3);
1013 ordersL[0] = getMinOrder(), ordersL[1] = getMaxOrder(), ordersL[2] = getTruncOrder();
1014 ordersR[0] = rhs.getMinOrder(), ordersR[1] = rhs.getMaxOrder(), ordersR[2] = rhs.getTruncOrder();
1015
1016 Array1D<int> result = getSubstOrders(ordersL, ordersR, trunc);
1017 return result;
1018}
1019
1020
1021template <class T, int N>
1023 // Default: trunc = EXACT
1024
1025 // Get orders.
1026 int f_min = ordersL[0], f_max = ordersL[1], f_trc = ordersL[2];
1027 int r_min = ordersR[0], r_max = ordersR[1], r_trc = ordersR[2];
1028 int g_min = f_min * r_min, g_max = f_max * r_max, g_trc;
1029 if(f_trc == EXACT) {
1030 if(r_trc == EXACT) {g_trc = (g_max <= trunc) ? EXACT : trunc;}
1031 else {
1032 if(f_max == 0) g_trc = EXACT;
1033 else {
1034 g_trc = r_trc;
1035 if(f_min != 0) g_trc += g_min - r_min;
1036 g_trc = std::min(g_trc, trunc);
1037 }
1038 }
1039 } else { // f_trc != EXACT
1040 if(r_min != 0) {
1041 g_trc = std::min((f_trc + 1) * r_min - 1, trunc);
1042 if(r_trc != EXACT && f_max != 0) {
1043 int t_trc = r_trc;
1044 if(f_min != 0) t_trc += g_min - r_min;
1045 g_trc = std::min(g_trc, t_trc);
1046 }
1047 } else { // r_min == 0
1048#ifdef DEBUG_FTps_CC
1049 std::cerr << " <*** WARNING ***> from FTps<T,N>::getSubstOrders(ordersL,ordersR,trunc):\n"
1050 << " Incomplete computation of feed-down terms.\n" << std::endl;
1051#endif
1052 if(f_max == 0) g_trc = 0;
1053 else {
1054 g_trc = std::min(f_trc, r_trc);
1055 g_trc = std::min(g_trc, trunc);
1056 }
1057 }
1058 }
1059
1060 g_max = std::min(g_max, g_trc);
1061 // NB: If trunc is sufficiently small, it can happen that this last line sets
1062 // g_max (== g_trc) below g_min. This will mean that g = 0 + O(z^{g_trc+1}).
1063 // Any routine that calls this one MUST check for this possibility.
1064
1065 Array1D<int> orders(3);
1066 orders[0] = g_min;
1067 orders[1] = g_max;
1068 orders[2] = g_trc;
1069
1070 return orders;
1071}
1072
1073
1074template <class T, int N>
1076 // Check sanity.
1077 if(n < 0)
1078 throw LogicalError("FTps<T,N>::substitute(mat,n)",
1079 "Transformation order, n, is negative.");
1080 else if(n > globalTruncOrder)
1081 throw LogicalError("FTps<T,N>::substitute(mat,n)",
1082 "Transformation order, n, exceeds globalTruncOrder.");
1083
1084 // Get orders.
1085 int minOrder = getMinOrder(), maxOrder = getMaxOrder(), trcOrder = getTruncOrder();
1086
1087 //Allocate result.
1088 FTps<T, N> result(minOrder, maxOrder, trcOrder);
1089 std::copy(begin(minOrder), end(maxOrder), result.begin(minOrder));
1090
1091 // Return trivial cases.
1092 if(n > trcOrder) {
1093#ifdef DEBUG_FTps_CC
1094 std::cerr << " <*** WARNING ***> from FTps<T,N>::substitute(mat,n):\n"
1095 << " Transformation order exceeds truncation order;\n"
1096 << " returning polynomial unchanged." << std::endl;
1097#endif
1098 return result;
1099 }
1100 if(n == 0 || n < minOrder || maxOrder < n) return result;
1101
1102 // Allocate working array; use static
1103 // local memory to avoid fragmentation.
1104 // NB: Instead of static local memory, one could use the data storage of an FTps
1105 // ---it's the correct size, it's reference counted, and it's retained on a stack.
1106 static T *t = 0;
1107 static int max_n = -1;
1108 if(n > max_n) {
1109 if(t) delete [] t;
1110 t = new T[getSize(n)];
1111 max_n = n;
1112 }
1113
1114 // Initialisations.
1115 const T *fj = begin(n);
1116 T *g = result.begin();
1117 T *t1 = t + 1;
1118 const Array1D<int> *oldvrbl = 0;
1119 int start_n = orderStart(n), end_n = orderEnd(n);
1120
1121 // Clear order n.
1122 std::fill(g + start_n, g + end_n, T(0));
1123
1124 // Loop over order n monomials.
1125 for(int j = start_n; j < end_n; ++j, ++fj) {
1126 // Skip monomials with coefficient zero.
1127 if(*fj == T(0)) continue;
1128
1129 // Get current monomial's variable list; compare with old variable list.
1131 int vi = 0;
1132 if(oldvrbl)
1133 while((*vrbl)[vi] == (*oldvrbl)[vi]) ++vi;
1134
1135 const T *mv;
1136 int ord;
1137 // If vi = 0, we must start at the beginning; otherwise,
1138 // we may re-use the first vi orders stored in t.
1139 if(vi == 0) {
1140 mv = mat[(*vrbl)[0]];
1141 std::copy(mv, mv + N, t1);
1142 ord = 2;
1143 } else ord = vi + 1;
1144
1145 // In working array t, clear orders we can't use.
1146 std::fill(t + orderStart(ord), t + end_n, T(0));
1147 // Build the remainder.
1148 while(ord <= n) {
1149 // Build next order part of transformed monomial by multiplying
1150 // the part that is one order lower by the transformed version
1151 // of the next variable in the variable list.
1152 int ord1 = ord - 1;
1153 int start_l = orderStart(ord1), end_l = orderEnd(ord1);
1154 mv = mat[(*vrbl)[ord1]]; // transformed version of next variable
1155 for(int k = 0; k < N; k++) {
1156 T mvk = mv[k];
1157 if(mvk == T(0)) continue;
1159 for(int l = start_l; l < end_l; l++) t[prod[l]] += mvk * t[l];
1160 }
1161 ++ord;
1162 }
1163 //Increment g by f[j] * transformed monomial.
1164 for(int i = start_n; i < end_n; i++) g[i] += *fj * t[i];
1165 // Save variable list for comparison with the next one.
1166 oldvrbl = vrbl;
1167 }
1168
1169 return result;
1170}
1171
1172
1173template <class T, int N>
1174FTps<T, N> FTps<T, N>::substitute(const FMatrix<T, N, N> &mat, int nl, int nh) const {
1175 // Check sanity.
1176 if(nl > nh)
1177 throw LogicalError("FTps<T,N>::substitute(mat,nl,nh)",
1178 "Inconsistent transformation orders: nl > nh.");
1179 if(nl < 0)
1180 throw LogicalError("FTps<T,N>::substitute(mat,nl,nh)",
1181 "Transformation order nl is negative.");
1182 else if(nh > globalTruncOrder)
1183 throw LogicalError("FTps<T,N>::substitute(mat,nl,nh)",
1184 "Transformation order nh exceeds globalTruncOrder.");
1185
1186 // Get orders.
1187 int minOrder = getMinOrder(), maxOrder = getMaxOrder(), trcOrder = getTruncOrder();
1188
1189 //Allocate result.
1190 FTps<T, N> result(minOrder, maxOrder, trcOrder);
1191 std::copy(begin(minOrder), end(maxOrder), result.begin(minOrder));
1192
1193 if(nh > trcOrder) {
1194#ifdef DEBUG_FTps_CC
1195 std::cerr << " <*** WARNING ***> from FTps<T,N>::substitute(mat,nl,nh):\n"
1196 << " Transformation order nh exceeds truncation order;\n"
1197 << " truncation order unchanged." << std::endl;
1198#endif
1199 }
1200
1201 // Return trivial cases.
1202 if(nh == 0 || nh < minOrder || maxOrder < nl) return result;
1203
1204 // Set and clear actual range of orders to transform.
1205 if(nl == 0) nl = 1;
1206 nl = std::max(nl, minOrder);
1207 nh = std::min(nh, maxOrder);
1208 std::fill(result.begin(nl), result.end(nh), T(0));
1209
1210 // Allocate working arrays; use static
1211 // local memory to avoid fragmentation.
1212 static T *t = 0;
1213 static const T **fp;
1214 static int max_nh = -1;
1215 if(nh > max_nh) {
1216 if(t) {
1217 delete [] t;
1218 delete [] fp;
1219 }
1220 t = new T[getSize(nh)];
1221 fp = new const T*[nh+1];
1222 max_nh = nh;
1223 }
1224 T *t1 = t + 1;
1225
1226 // Initialisations.
1227 // Array element fp[m] points to the next order m monomial to transform.
1228 for(int m = nl; m <= nh; ++m) fp[m] = begin(m);
1229 T *g = result.begin();
1230 const Array1D<int> *oldvrbl = 0;
1231 int start_nh = orderStart(nh), end_nh = orderEnd(nh), nh1 = nh - 1, nh2 = nh - 2;
1232
1233 // Loop over order nh monomials; construct lower orders along the way.
1234 for(int j = start_nh; j < end_nh; ++j) {
1235 // Get current monomial's variable list; compare with old variable list.
1237 int vk = 0;
1238 if(oldvrbl)
1239 while((*vrbl)[vk] == (*oldvrbl)[vk]) ++vk;
1240
1241 // Determine which monomial pointers we shall need to increment.
1242 int jl = (*vrbl)[nh1], ni = nh2;
1243 while(ni >= 0 && (*vrbl)[ni] == jl) --ni;
1244 ni += 2;
1245 ni = std::max(ni, nl);
1246 // Determine which monomials contribute this round.
1247 int n1 = std::max(nl, ni), n2 = nh;
1248 while(n1 <= n2 && *fp[n1] == 0) ++n1;
1249 while(n2 > n1 && *fp[n2] == 0) --n2;
1250 // Skip if all monomials have coefficient zero.
1251 if(n1 > n2) {
1252 for(int m = ni; m <= nh; ++m) ++fp[m];
1253 continue;
1254 }
1255
1256 const T *mv;
1257 int ord;
1258 // If vk = 0, we must start at the beginning; otherwise,
1259 // we may keep the first vk orders stored in t.
1260 if(vk == 0) {
1261 mv = mat[(*vrbl)[0]];
1262 std::copy(mv, mv + N, t1);
1263 ord = 2;
1264 } else ord = vk + 1;
1265
1266 // In working array t, clear orders we can't use.
1267 std::fill(t + orderStart(ord), t + end_nh, T(0));
1268
1269 // Build the remainder.
1270 while(ord <= nh) {
1271 // Build next order part of transformed monomial by multiplying
1272 // the part that is one order lower by the transformed version
1273 // of the next variable in the variable list.
1274 int ord1 = ord - 1;
1275 int start_l = orderStart(ord1), end_l = orderEnd(ord1);
1276 mv = mat[(*vrbl)[ord1]]; // transformed version of next variable
1277 for(int k = 0; k < N; k++) {
1278 T mvk = mv[k];
1279 if(mvk == T(0)) continue;
1281 for(int l = start_l; l < end_l; ++l) t[prod[l]] += mvk * t[l];
1282 }
1283 ++ord;
1284 }
1285 //Increment g by f[j] * transformed monomial.
1286 for(int m = n1; m <= n2; ++m) {
1287 T fj = *fp[m];
1288 int start_m = orderStart(m), end_m = orderEnd(m);
1289 for(int i = start_m; i < end_m; i++) g[i] += fj * t[i];
1290 }
1291 // Increment pointers in fp[].
1292 for(int m = ni; m <= nh; ++m) ++fp[m];
1293 // Save variable list for comparison with the next one.
1294 oldvrbl = vrbl;
1295 }
1296
1297 return result;
1298}
1299
1300
1301template <class T, int N>
1303 return substitute(mat, getMinOrder(), getMaxOrder());
1304}
1305
1306
1307template <class T, int N>
1308FTps<T, N> FTps<T, N>::substitute(const FVps<T, N> &rhs, int trunc) const {
1309 // Default: trunc = EXACT
1310
1311 // Get orders.
1312 int f_min = getMinOrder(), f_max = getMaxOrder();
1313 Array1D<int> orders = getSubstOrders(rhs, trunc);
1314 int g_min = orders[0], g_max = orders[1], g_trc = orders[2];
1315
1316 // Make sure we don't trip over globalTruncOrder.
1317 if(g_trc != EXACT && g_trc > globalTruncOrder)
1318 throw LogicalError("FTps::substitute(FVps rhs, int trunc)",
1319 "Truncation order exceeds globalTruncOrder!");
1320
1321 // Return trivial case.
1322 if(g_min > g_max) return FTps<T, N>(g_trc, g_trc, g_trc);
1323
1324 //Allocate result.
1325 FTps<T, N> result(g_min, g_max, g_trc);
1326 if(f_min == 0) result[0] = *begin();
1327 if(f_max == 0) return result;
1328
1329 // Set actual range of orders to transform.
1330 int nl = f_min, nh = f_max;
1331 if(nl == 0) nl = 1;
1332
1333 // Allocate working arrays.
1334 const T *fp[nh+1];
1335 Array1D< FTps<T, N> > t(nh + 1);
1336
1337 // Initialisations.
1338 // Array element fp[m] points to the next order m monomial to transform.
1339 for(int m = nl; m <= nh; ++m) fp[m] = begin(m);
1340 const Array1D<int> *oldvrbl = 0;
1341 int start_nh = orderStart(nh), end_nh = orderEnd(nh), nh1 = nh - 1, nh2 = nh - 2;
1342
1343 // Loop over order nh monomials; construct lower orders along the way.
1344 for(int j = start_nh; j < end_nh; ++j) {
1345 // Get current monomial's variable list; compare with old variable list.
1347 int vk = 0;
1348 if(oldvrbl)
1349 while((*vrbl)[vk] == (*oldvrbl)[vk]) ++vk;
1350
1351 // Determine which monomial pointers we shall need to increment.
1352 int jl = (*vrbl)[nh1], ni = nh2;
1353 while(ni >= 0 && (*vrbl)[ni] == jl) --ni;
1354 ni += 2;
1355 ni = std::max(ni, nl);
1356 // Determine which monomials contribute this round.
1357 int n1 = std::max(nl, ni), n2 = nh;
1358 while(n1 <= n2 && *fp[n1] == 0) ++n1;
1359 while(n2 > n1 && *fp[n2] == 0) --n2;
1360 // Skip if all monomials have coefficient zero.
1361 if(n1 > n2) {
1362 for(int m = ni; m <= nh; ++m) ++fp[m];
1363 continue;
1364 }
1365
1366 int ord;
1367 // If vk = 0, we must start at the beginning; otherwise,
1368 // we may keep the first vk orders stored in t.
1369 if(vk == 0) {
1370 t[1] = rhs[(*vrbl)[0]];
1371 ord = 2;
1372 } else ord = vk + 1;
1373
1374 // Build the remainder.
1375 while(ord <= nh) {
1376 // Build next order part of transformed monomial by multiplying
1377 // the part that is one order lower by the transformed version
1378 // of the next variable in the variable list.
1379 int ord1 = ord - 1;
1380 t[ord] = t[ord1].multiply(rhs[(*vrbl)[ord1]], g_trc);
1381 ++ord;
1382 }
1383 //Increment result by f[j] * transformed monomial.
1384 for(int m = n1; m <= n2; ++m) result += *fp[m] * t[m];
1385 // Increment pointers in fp[].
1386 for(int m = ni; m <= nh; ++m) ++fp[m];
1387 // Save variable list for comparison with the next one.
1388 oldvrbl = vrbl;
1389 }
1390
1391 return result;
1392}
1393
1394
1395template <class T, int N>
1397 // Get orders.
1398 int f_min = getMinOrder(), f_max = getMaxOrder(), f_trc = getTruncOrder();
1399 int df_min = (f_min == 0) ? f_min : f_min - 1;
1400 int df_max = (f_max == 0) ? f_max : f_max - 1;
1401 int df_trc = (f_trc == 0 || f_trc == EXACT) ? f_trc : f_trc - 1;
1402 if(f_min == 0 && f_min < f_max) f_min = 1;
1403
1404 //Allocate result.
1405 FTps<T, N> result(df_min, df_max, df_trc);
1406 // Return trivial case.
1407 if(f_max == 0) return result;
1408
1409 // Initialisations.
1410 const int *product = FTpsData<N>::getProductArray(var + 1).begin();
1411 const T *f = begin();
1412 T *df = result.begin();
1413 T *dfe = df + orderEnd(df_max);
1414 int ks = orderStart(df_min);
1415 df += ks;
1416 product += ks;
1417
1418 // Compute derivative.
1419 // For the contribution to the k-th monomial in the derivative, we look
1420 // at the monomial whose index is the k-th entry in the product array for
1421 // variable var. The var-th entry in that monomial's exponent array is
1422 // the power brought down by the differentiation.
1423 while(df != dfe) {
1424 int kp = *product++;
1425 *df++ = T(FTpsData<N>::getExponents(kp)[var]) * *(f + kp);
1426 }
1427
1428 return result;
1429}
1430
1431
1432template <class T, int N>
1434 FVps<T, N> result;
1435 for(int i = 0; i < N; ++i) result[i] = derivative(i);
1436 return result;
1437}
1438
1439
1440template <class T, int N>
1441FTps<T, N> FTps<T, N>::integral(int var, int trunc) const {
1442 // Default: trunc = EXACT
1443
1444 // Get orders.
1445 int f_min = getMinOrder(), f_max = getMaxOrder(), f_trc = getTruncOrder();
1446 int minOrder = std::min(f_min + 1, trunc);
1447 int maxOrder = std::min(f_max + 1, trunc);
1448 int trcOrder;
1449 if(f_trc == EXACT) trcOrder = trunc;
1450 else trcOrder = std::min(f_trc + 1, trunc);
1451 if(maxOrder > globalTruncOrder || (trcOrder != EXACT && trcOrder > globalTruncOrder))
1452 throw LogicalError("FTps::integral(int var, int trunc)", "Some order exceeds globalTruncOrder!");
1453
1454 // Allocate result.
1455 FTps<T, N> result(minOrder, maxOrder, trcOrder);
1456
1457 // Return trivial result.
1458 if(f_min >= maxOrder) return result;
1459
1460 // Initialisations.
1461 const T *f = begin();
1462 T *r = result.begin();
1463 int is = orderStart(f_min);
1464 int ie = orderEnd(maxOrder - 1);
1465
1466 // Compute integral.
1467 // The contribution from the k-th monomial we insert into the integral
1468 // at the monomial whose index is the k-th entry in the product array
1469 // for variable var. The var-th entry in that (the result) monomial's
1470 // exponent array is the power kicked up by the integration.
1471 const Array1D<int> &product = FTpsData<N>::getProductArray(var + 1);
1472 for(int i = is; i < ie; ++i) {
1473 int k = product[i];
1474 r[k] = f[i] / double(FTpsData<N>::getExponents(k)[var]);
1475 }
1476 return result;
1477}
1478
1479
1480template <class T, int N>
1481FTps<T, N> FTps<T, N>::taylor(const Array1D<T> &series, int order) const {
1482 FTps<T, N> x(*this);
1483 x.unique();
1484 x.itsRep->data[0] = T(0);
1485 FTps<T, N> result(series[order]);
1486
1487 for(int m = 1; m <= order; ++m) {
1488 if(result.itsRep->trcOrd < m) result.setTruncOrder(m);
1489 result = x.multiply(result, m);
1490
1491 /*
1492 * has to be set, otherwise if coefficient is zero --> next coefficient doesn't get
1493 * counted, e.g. with cos(x)
1494 */
1495 result.setMinOrder(0);
1496
1497 result.itsRep->data[0] = series[order-m];
1498 }
1499
1500 return result;
1501}
1502
1503
1504template <class T, int N> inline
1506 if(itsRep->ref > 1) {
1507 FTpsRep<T, N> *oldRep = itsRep;
1508 oldRep->ref--;
1509 itsRep = FTps<T, N>::allocate(itsRep->minOrd, itsRep->maxOrd, itsRep->trcOrd);
1510 std::copy(oldRep->begin(), oldRep->end(itsRep->maxOrd), itsRep->begin());
1511 }
1512}
1513
1514template <class T, int N>
1516
1517 // get total number of coefficients
1518 int size = getSize();
1519
1520 // initialize list
1521 std::list<int> coeffs;
1522
1523 // loop over all coefficients
1524 for (int i = 0; i < size; ++i) {
1525 // get index of non-zero coefficients
1526 if (getCoefficient(i) != 0) {
1527 coeffs.push_back(i);
1528 }
1529 }
1530
1531 return coeffs;
1532}
1533
1534template <class T, int N>
1536
1537 // check index
1538 if ( index < 0 || getSize() - 1 < index)
1539 throw LogicalError("FVps<T,N>::extractExponents(var)","Index out of range.");
1540
1541 // get exponents of monomial
1543
1544 // array of exponents
1545 FArray1D<int, N> expons;
1546
1547 // copy monomials to array
1548 for (int i = 0; i < N; ++i)
1549 expons[i] = mono[i];
1550
1551 return expons;
1552}
1553
1554template <class T, int N>
1556
1557 if (power < 0)
1558 throw LogicalError("FTps<T,N>::makePower(power)","Power is negative.");
1559
1560 FTps<T, N> result = *this;
1561
1562 // gets truncated in case of being bigger than global truncation order
1563 for (int i = 1; i < power; ++i) {
1564 //result *= *this;
1565 result = result.multiply(*this, globalTruncOrder);
1566 }
1567 return result;
1568}
1569
1570template <class T, int N>
1571std::istream &FTps<T, N>::get(std::istream &is) {
1572 // is.flags(std::ios::skipws);
1573 // char head[4];
1574 // is.get(head, 4);
1575 //
1576 // // Check for Tps.
1577 // if (strcmp(head, "Tps") != 0)
1578 // throw FormatError("FTps::get()", "Flag word \"Tps\" missing.");
1579
1580 // Check for Tps.
1581 std::string head;
1582 is >> head;
1583 if(head != "Tps")
1584 throw FormatError("FTps::get()", "Flag word \"Tps\" missing.");
1585
1586 // Read in order data.
1587 int minOrder, maxOrder, trcOrder, nVar;
1588 std::string trunc;
1589 is >> minOrder >> maxOrder >> trunc >> nVar;
1590 if(trunc == "EXACT") trcOrder = EXACT;
1591 else trcOrder = std::atoi(trunc.c_str());
1592
1593 // Check sanity.
1594 if(nVar != N)
1595 throw FormatError("FTps::get()", "Invalid number of variables.");
1596
1597 // Allocate result.
1598 FTps<T, N> result(minOrder, maxOrder, trcOrder);
1599 T coeff;
1600 FMonomial<N> mono(nVar);
1601 bool done = false;
1602 bool fail = false;
1603 bool first = true;
1604
1605 while(true) {
1606 is >> coeff;
1607 fail = is.fail();
1608
1609 int order = 0;
1610 for(int var = 0; var < nVar; var++) {
1611 int p;
1612 is >> p;
1613 fail |= is.fail();
1614 if(p < 0) done = true;
1615 mono[var] = p;
1616 order += mono[var];
1617 }
1618
1619 if(fail) throw FormatError("FTps::get()", "File read error");
1620 if(done) break;
1621
1622 if(coeff != T(0)) {
1623 if(first) {
1624 first = false;
1625 minOrder = maxOrder = order;
1626 } else {
1627 if(order < minOrder) minOrder = order;
1628 else if(order > maxOrder) maxOrder = order;
1629 }
1630 int index = FTpsData<N>::getIndex(mono);
1631 result[index] = coeff;
1632 }
1633 }
1634
1635 if(minOrder < result.getMinOrder())
1636 throw FormatError("FTps::get()", "minOrder incorrect in file");
1637 if(maxOrder > result.getMaxOrder())
1638 throw FormatError("FTps::get()", "maxOrder incorrect in file");
1639 result.itsRep->minOrd = minOrder;
1640 result.itsRep->maxOrd = maxOrder;
1641
1642 *this = result;
1643 return is;
1644}
1645
1646
1647template <class T, int N>
1648std::ostream &FTps<T, N>::put(std::ostream &os) const {
1649 // Print out order data.
1650 os << "Tps " << itsRep->minOrd << ' ' << itsRep->maxOrd << ' ';
1651 if(itsRep->trcOrd == EXACT)
1652 os << "EXACT";
1653 else
1654 os << itsRep->trcOrd;
1655 os << " " << N << std::endl;
1656 // os << "<*** allocOrd = " << itsRep->allocOrd << " ***>" << std::endl;
1657
1658 // Save old and set new formats.
1659 std::streamsize old_prec = os.precision(14);
1660 os.setf(std::ios::scientific, std::ios::floatfield);
1661
1662 // Print out FTps coefficients and exponents.
1663 int i = orderStart(itsRep->minOrd);
1664 const T *f = begin(getMinOrder());
1665 const T *fe = end(getMaxOrder());
1666 for(; f != fe; f++, i++) {
1667 if(*f != T(0)) {
1668 os << std::setw(24) << *f;
1669 for(int var = 0; var < N; var++)
1670 os << std::setw(3) << FTpsData<N>::getExponents(i)[var];
1671 os << std::endl;
1672 }
1673 }
1674 // End FTps w/ "0.00 -1 .. -1".
1675 os << std::setw(24) << T(0);
1676 for(int var = 0; var < N; var++) os << std::setw(3) << (-1);
1677 os << std::endl;
1678
1679 // Restore old formats.
1680 os.precision(old_prec);
1681 os.setf(std::ios::fixed, std::ios::floatfield);
1682
1683 return os;
1684}
1685
1686
1687// Template class FTps<T,N>, private methods.
1688// ------------------------------------------------------------------------
1689
1690template <class T, int N> inline
1692FTps<T, N>::allocate(int minOrder, int maxOrder, int trcOrder) {
1693 checkOrders("FTps<T,N>::allocate(minOrder, maxOrder, trcOrder)", minOrder, maxOrder, trcOrder);
1694
1695 // Determine allocation order.
1696 int allocOrder = trcOrder == EXACT ? maxOrder : trcOrder;
1697
1698 // Do the allocating.
1699 FTpsRep<T, N> *rep = freeList[allocOrder];
1700 if(rep) {
1701 // There exists a free object of the correct order: take 'rep' off
1702 // the stack, point freeList to next element in the linked list, ...
1703 freeList[allocOrder] = rep->next;
1704 // ... and set the values of next, ref, and *Ord.
1705 rep->next = 0;
1706 rep->ref = 1;
1707 rep->minOrd = minOrder;
1708 rep->maxOrd = maxOrder;
1709 rep->trcOrd = trcOrder;
1710 //rep->allocOrd = allocOrder; // This should already be the case! (Don't alter rep->allocOrd!)
1711#ifdef DEBUG_FTps_CC
1712 if(allocOrder != rep->allocOrd)
1713 std::cerr << " <*** allocOrder error ***> " << allocOrder << " != " << rep->allocOrd << std::endl;
1714#endif
1715 } else {
1716 // We must allocate a new object.
1717 rep = new FTpsRep<T, N>(minOrder, maxOrder, trcOrder);
1718 }
1719
1720 // The data array for the returned object is uninitialised.
1721 return rep;
1722}
1723
1724
1725template <class T, int N> inline
1727 int order = rep->allocOrd;
1728 rep->next = FTps<T, N>::freeList[order];
1729 FTps<T, N>::freeList[order] = rep;
1730}
1731
1732
1733template <class T, int N>
1734void FTps<T, N>::grow(int maxOrder, int trcOrder) {
1735 int minOrder = itsRep->minOrd;
1736
1737 // Allocate new representation.
1738 FTpsRep<T, N> *newRep = allocate(minOrder, maxOrder, trcOrder);
1739
1740 // Copy old representation.
1741 T *f = itsRep->begin(minOrder);
1742 T *fe = itsRep->end(std::min(itsRep->maxOrd, maxOrder));
1743 T *g = newRep->begin(minOrder);
1744 T *ge = newRep->end(maxOrder);
1745 while(f < fe) *g++ = *f++;
1746 while(g < ge) *g++ = T(0);
1747
1748 // Discard old representation and attach new one.
1749 itsRep->ref--;
1750 if(itsRep->ref == 0) deallocate(itsRep);
1751 itsRep = newRep;
1752}
1753
1754
1755template <class T, int N>
1757 Array1D<int> result(4);
1758 result[0] = itsRep->minOrd;
1759 result[1] = itsRep->maxOrd;
1760 result[2] = itsRep->trcOrd;
1761 result[3] = itsRep->allocOrd;
1762 return result;
1763}
1764
1765
1766template <class T, int N>
1767void FTps<T, N>::checkOrders(const std::string &method, int minOrder, int maxOrder, int &trcOrder) {
1768 bool errF = false;
1769 std::string message;
1770
1771 // Check that min-, max-, and trcOrder's have the correct relationships.
1772 if(!(0 <= minOrder && minOrder <= maxOrder && maxOrder <= trcOrder && maxOrder < EXACT)) {
1773 errF = true;
1774 message = "Invalid, or inconsistent, arguments.";
1775 }
1776 // Make sure we don't trip over globalTruncOrder.
1777 else if(maxOrder > globalTruncOrder) {
1778 errF = true;
1779 message = "The argument maxOrder exceeds globalTruncOrder.";
1780 } else if(trcOrder != EXACT && trcOrder > globalTruncOrder) {
1781 errF = true;
1782 message = "The argument trcOrder has a finite value that exceeds globalTruncOrder.";
1783 }
1784 if(errF) {
1785 std::cerr << "Method " << method << ", called with arguments (";
1786 if(minOrder == EXACT) std::cerr << "EXACT,";
1787 else std::cerr << minOrder << ",";
1788 if(maxOrder == EXACT) std::cerr << "EXACT,";
1789 else std::cerr << maxOrder << ",";
1790 if(trcOrder == EXACT) std::cerr << "EXACT";
1791 else std::cerr << trcOrder;
1792 std::cerr << ")." << std::endl;
1793 throw LogicalError(method, message);
1794 }
1795}
1796
1797
1798// Global functions acting on FTps<T> objects.
1799// ------------------------------------------------------------------------
1800
1801template <class T, int N>
1803 // Determine orders of result.
1804 int f_min = lhs.getMinOrder(), f_max = lhs.getMaxOrder();
1805 int g_min = rhs.getMinOrder(), g_max = rhs.getMaxOrder();
1806 int h_trc = std::min(lhs.getTruncOrder(), rhs.getTruncOrder());
1807 int h_min = std::min(f_min, g_min), h_max = std::min(std::max(f_max, g_max), h_trc);
1808 if(h_trc < f_min) h_max = g_max;
1809 else if(h_trc < g_min) h_max = f_max;
1810
1811 // Allocate result.
1812 FTps<T, N> result(h_min, h_max, h_trc);
1813
1814 // Change from orders to indices.
1815 f_min = FTps<T, N>::orderStart(f_min);
1816 f_max = FTps<T, N>::orderEnd(std::min(f_max, h_max));
1817 g_min = FTps<T, N>::orderStart(g_min);
1818 g_max = FTps<T, N>::orderEnd(std::min(g_max, h_max));
1819 h_min = std::min(f_min, g_min);
1820 h_max = std::max(f_max, g_max);
1821
1822 const T *f = lhs.begin();
1823 const T *g = rhs.begin();
1824 T *h = result.begin();
1825
1826 // Do the "addition" h = f + g.
1827 int i = h_min;
1828 if(g_min < f_max && f_min < g_max) { // overlap exists
1829 int fg_max_min = std::min(f_max, g_max);
1830 for(; i < g_min; i++) h[i] = f[i]; //: copy below
1831 for(; i < f_min; i++) h[i] = g[i]; // overlap
1832 for(; i < fg_max_min; i++) h[i] = f[i] + g[i]; //: do f + g
1833 for(; i < f_max; i++) h[i] = f[i]; //: copy above
1834 for(; i < g_max; i++) h[i] = g[i]; // overlap
1835 } else { // gap exists
1836 if(f_max <= g_min) { // |f| < |g|
1837 // Check for special case (corresponds to h_trc in gap).
1838 if(g_min > h_max) g_min = h_max;
1839 // Then load h.
1840 for(; i < f_max; i++) h[i] = f[i];
1841 for(; i < g_min; i++) h[i] = 0;
1842 for(; i < h_max; i++) h[i] = g[i];
1843 } else { // |g| < |f|
1844 // Check for special case (corresponds to h_trc in gap).
1845 if(f_min > h_max) f_min = h_max;
1846 // Then load h.
1847 for(; i < g_max; i++) h[i] = g[i];
1848 for(; i < f_min; i++) h[i] = 0;
1849 for(; i < h_max; i++) h[i] = f[i];
1850 }
1851 }
1852
1853 return result;
1854}
1855
1856
1857template <class T, int N>
1859 // Determine orders of result.
1860 int f_min = lhs.getMinOrder(), f_max = lhs.getMaxOrder();
1861 int g_min = rhs.getMinOrder(), g_max = rhs.getMaxOrder();
1862 int h_trc = std::min(lhs.getTruncOrder(), rhs.getTruncOrder());
1863 int h_min = std::min(f_min, g_min), h_max = std::min(std::max(f_max, g_max), h_trc);
1864 if(h_trc < f_min) h_max = g_max;
1865 else if(h_trc < g_min) h_max = f_max;
1866
1867 // Allocate result.
1868 FTps<T, N> result(h_min, h_max, h_trc);
1869
1870 // Change from orders to indices.
1871 f_min = FTps<T, N>::orderStart(f_min);
1872 f_max = FTps<T, N>::orderEnd(std::min(f_max, h_max));
1873 g_min = FTps<T, N>::orderStart(g_min);
1874 g_max = FTps<T, N>::orderEnd(std::min(g_max, h_max));
1875 h_min = std::min(f_min, g_min);
1876 h_max = std::max(f_max, g_max);
1877
1878 const T *f = lhs.begin();
1879 const T *g = rhs.begin();
1880 T *h = result.begin();
1881
1882 // Do the "subtraction" h = f - g.
1883 int i = h_min;
1884 if(g_min < f_max && f_min < g_max) { // overlap exists
1885 int fg_max_min = std::min(f_max, g_max);
1886 for(; i < g_min; i++) h[i] = f[i]; //: copy below
1887 for(; i < f_min; i++) h[i] = -g[i]; // overlap
1888 for(; i < fg_max_min; i++) h[i] = f[i] - g[i]; //: do f - g
1889 for(; i < f_max; i++) h[i] = f[i]; //: copy above
1890 for(; i < g_max; i++) h[i] = -g[i]; // overlap
1891 } else { // gap exists
1892 if(f_max <= g_min) { // |f| < |g|
1893 // Check for special case (corresponds to h_trc in gap).
1894 if(g_min > h_max) g_min = h_max;
1895 // Then load h.
1896 for(; i < f_max; i++) h[i] = f[i];
1897 for(; i < g_min; i++) h[i] = 0;
1898 for(; i < h_max; i++) h[i] = -g[i];
1899 } else { // |g| < |f|
1900 // Check for special case (corresponds to h_trc in gap).
1901 if(f_min > h_max) f_min = h_max;
1902 // Then load h.
1903 for(; i < g_max; i++) h[i] = -g[i];
1904 for(; i < f_min; i++) h[i] = 0;
1905 for(; i < h_max; i++) h[i] = f[i];
1906 }
1907 }
1908
1909 return result;
1910}
1911
1912
1913template <class T, int N>
1914FTps<T, N> operator+(const FTps<T, N> &lhs, const T &rhs) {
1915 FTps<T, N> result(lhs);
1916 return result += rhs;
1917}
1918
1919
1920template <class T, int N>
1921FTps<T, N> operator-(const FTps<T, N> &lhs, const T &rhs) {
1922 FTps<T, N> result(lhs);
1923 return result -= rhs;
1924}
1925
1926
1927template <class T, int N>
1928FTps<T, N> operator+(const T &lhs, const FTps<T, N> &rhs) {
1929 FTps<T, N> result(rhs);
1930 return result += lhs;
1931}
1932
1933
1934template <class T, int N>
1935FTps<T, N> operator-(const T &lhs, const FTps<T, N> &rhs) {
1936 FTps<T, N> result(- rhs);
1937 return result += lhs;
1938}
1939
1940
1941template <class T, int N>
1943 return lhs.multiply(rhs);
1944 // return lhs.multiply(rhs, FTps<T,N>::getGlobalTruncOrder());
1945}
1946
1947
1948template <class T, int N>
1950 return lhs.divide(rhs);
1951}
1952
1953
1954template <class T, int N>
1955FTps<T, N> operator*(const FTps<T, N> &lhs, const T &rhs) {
1956 FTps<T, N> result(lhs);
1957 return result *= rhs;
1958}
1959
1960
1961template <class T, int N>
1962FTps<T, N> operator/(const FTps<T, N> &lhs, const T &rhs) {
1963 FTps<T, N> result(lhs);
1964 return result /= rhs;
1965}
1966
1967
1968template <class T, int N>
1969FTps<T, N> operator*(const T &lhs, const FTps<T, N> &rhs) {
1970 FTps<T, N> result(rhs);
1971 return result *= lhs;
1972}
1973
1974
1975template <class T, int N>
1976FTps<T, N> operator/(const T &lhs, const FTps<T, N> &rhs) {
1977 return rhs.inverse() * lhs;
1978}
1979
1980
1981template <class T, int N>
1982bool operator==(const T &lhs, const FTps<T, N> &rhs) {
1983 return rhs == lhs;
1984}
1985
1986
1987template <class T, int N>
1988bool operator!=(const T &lhs, const FTps<T, N> &rhs) {
1989 return rhs != lhs;
1990}
1991
1992
1993template <class T, int N> FVps<T, N>
1994ExpMap(const FTps<T, N> &H, int trunc) {
1995 return ExpMap(H, FVps<T, N>(), trunc);
1996}
1997
1998
1999template <class T, int N> FTps<T, N>
2000ExpMap(const FTps<T, N> &H, const FTps<T, N> &f, int trunc) {
2001 // Default: trunc = EXACT
2002
2003 // Limit number of iterations.
2004 const int MAX_ITER = 100;
2005
2006 // We really ought to throw an exception if H contains linear terms and is not exact,
2007 // but we're just going to complain!!
2008 bool FD = false;
2009 if(H.getTruncOrder() != FTps<T, N>::EXACT && H.getMinOrder() < 2) {
2010 FD = true;
2011#ifdef DEBUG_FTps_CC
2012 std::cerr << " <*** WARNING ***> from ExpMap(H,f,trunc):\n"
2013 << " Incomplete computation of feed-down terms.\n" << std::endl;
2014#endif
2015 }
2016 int fd_trc = std::min(H.getTruncOrder() - 1, f.getTruncOrder());
2017
2018 // Construct dH = grad(H).J, s.t :H:f = dH.grad(f).
2019 FVps<T, N> dH;
2020 for(int i = 0; i < N; i += 2) {
2021 dH[i] = - H.derivative(i + 1);
2022 dH[i+1] = H.derivative(i);
2023 }
2024
2025 // Allocate and initialize result.
2026 FTps<T, N> expHf = f;
2027
2028 // Initialize variables.
2029 FTps<T, N> dHkf = f;
2030 FTps<T, N> old = T(0);
2031
2032 // Compute series; quit computation if we added nothing last time through loop.
2033 for(int k = 1; expHf != old; ++k) {
2034 if(k > MAX_ITER)
2035 throw ConvergenceError("ExpMap(const FTps<T,N> &H, const FTps<T,N> &f)",
2036 "No convergence in ExpMap(H,f)");
2037
2038 // Don't initialize dHk1f to 0, as that sets minOrder to 0!
2039 old = expHf;
2040 FTps<T, N> ddHkf = dHkf.derivative(0);
2041 if(FD) ddHkf.setTruncOrder(fd_trc);
2042 FTps<T, N> dHk1f = dH[0].multiply(ddHkf, trunc);
2043 for(int v = 1; v < N; ++v) {
2044 ddHkf = dHkf.derivative(v);
2045 if(FD) ddHkf.setTruncOrder(fd_trc);
2046 dHk1f += dH[v].multiply(ddHkf, trunc);
2047 //dHk1f += dH[v].multiply(dHkf.derivative(v),trunc);
2048 }
2049 dHkf = dHk1f / T(k); // :H:^{k}/(k!)
2050 expHf += dHkf;
2051 }
2052
2053 return expHf;
2054}
2055
2056
2057template <class T, int N>
2058FTps<T, N> PoissonBracket(const FTps<T, N> &f, const FTps<T, N> &g, int trunc) {
2059 // Default: trunc = EXACT
2060
2061 // Determine orders of result.
2062 int f_min = f.getMinOrder(), f_max = f.getMaxOrder(), f_trc = f.getTruncOrder();
2063 int g_min = g.getMinOrder(), g_max = g.getMaxOrder(), g_trc = g.getTruncOrder();
2064 int h_min = std::max(f_min + g_min - 2, 0), h_max = std::max(f_max + g_max - 2, 0), h_trc;
2065 if(f_trc == FTps<T, N>::EXACT) {
2066 if(g_trc == FTps<T, N>::EXACT) {h_trc = (h_max <= trunc) ? FTps<T, N>::EXACT : trunc;}
2067 else h_trc = std::min(std::max(f_min + g_trc - 2, 0), trunc);
2068 } else if(g_trc == FTps<T, N>::EXACT) h_trc = std::min(std::max(f_trc + g_min - 2, 0), trunc);
2069 else {
2070 h_trc = std::min(f_trc + g_min - 2, f_min + g_trc - 2);
2071 h_trc = std::min(std::max(h_trc, 0), trunc);
2072 }
2073 h_max = std::min(h_max, h_trc);
2074
2075 // Return trivial result.
2076 if(h_min > h_max) return FTps<T, N>();
2077
2078 // Allocate result.
2079 FTps<T, N> h(h_min, h_max, h_trc);
2080
2081 for(int q = 0; q < N; q += 2) {
2082 int p = q + 1;
2083 //h += f.derivative(q) * g.derivative(p) - f.derivative(p) * g.derivative(q);
2084 h += f.derivative(q).multiply(g.derivative(p), h_trc)
2085 - f.derivative(p).multiply(g.derivative(q), h_trc);
2086 }
2087 return h;
2088}
2089
2090
2091template <class T, int N>
2092std::istream &operator>>(std::istream &is, FTps<T, N> &tps) {
2093 return tps.get(is);
2094}
2095
2096
2097template <class T, int N>
2098std::ostream &operator<<(std::ostream &os, const FTps<T, N> &tps) {
2099 return tps.put(os);
2100}
2101
2102#endif // CLASSIC_FTps_CC
std::istream & operator>>(std::istream &is, FTps< T, N > &tps)
Extract FTps from stream [b]is[/b].
Definition: FTps.hpp:2092
FTps< T, N > operator+(const FTps< T, N > &lhs, const FTps< T, N > &rhs)
Add.
Definition: FTps.hpp:1802
FVps< T, N > ExpMap(const FTps< T, N > &H, int trunc)
Build the exponential series.
Definition: FTps.hpp:1994
FTps< T, N > operator/(const FTps< T, N > &lhs, const FTps< T, N > &rhs)
Divide.
Definition: FTps.hpp:1949
bool operator==(const T &lhs, const FTps< T, N > &rhs)
Equality.
Definition: FTps.hpp:1982
bool operator!=(const T &lhs, const FTps< T, N > &rhs)
Inequality.
Definition: FTps.hpp:1988
FTps< T, N > operator-(const FTps< T, N > &lhs, const FTps< T, N > &rhs)
Subtract.
Definition: FTps.hpp:1858
FTps< T, N > operator*(const FTps< T, N > &lhs, const FTps< T, N > &rhs)
Multiply.
Definition: FTps.hpp:1942
FTps< T, N > PoissonBracket(const FTps< T, N > &f, const FTps< T, N > &g, int trunc)
Poisson bracket.
Definition: FTps.hpp:2058
std::ostream & operator<<(std::ostream &os, const FTps< T, N > &tps)
Insert FTps into stream [b]os[/b].
Definition: FTps.hpp:2098
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
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
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
bool ge(double x, double y)
Vector truncated power series in n variables.
Definition: FVps.h:39
Array1D< int > getSubstOrders(const FVps< T, N > &rhs, int trunc=(FTps< T, N >::EXACT)) const
Return orders {min, max, trc} of f(rhs(z)).
Definition: FVps.hpp:594
FTps< T, N > data[N]
Definition: FVps.h:247
void setMinOrder(int order)
Set minimum order.
Definition: FVps.hpp:175
FVps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Definition: FVps.hpp:608
int getMaxOrder() const
Get highest order contained in any component.
Definition: FVps.hpp:181
void setMaxOrder(int order)
Set maximum order.
Definition: FVps.hpp:191
FVps derivative(int var) const
Partial derivative.
Definition: FVps.hpp:524
FVps filter(int minOrder, int maxOrder, int trcOrder=(FTps< T, N >::EXACT)) const
Extract given range of orders, with truncation.
Definition: FVps.hpp:223
int getTruncOrder() const
Get lowest truncation order in any component.
Definition: FVps.hpp:207
int getMinOrder() const
Get lowest order contained in any component.
Definition: FVps.hpp:165
iterator begin()
Get beginning of data.
Definition: Array1D.h:204
iterator begin()
Get iterator pointing to beginning of array.
Definition: FArray1D.h:192
Truncated power series in N variables of type T.
Definition: FTps.h:45
static void deallocate(FTpsRep< T, N > *)
Definition: FTps.hpp:1726
static const Array1D< int > & getProductArray(int index)
Index array for products of monomial "index".
Definition: FTps.hpp:433
FTps< T, N > makePower(int power) const
Multiply FTps with itself.
Definition: FTps.hpp:1555
Array1D< int > getRepOrders() const
Definition: FTps.hpp:1756
FTps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Definition: FTps.hpp:1075
const T getCoefficient(int index) const
Get coefficient.
Definition: FTps.hpp:223
std::list< int > getListOfNonzeroCoefficients() const
Get a list containing the indexes of non-zero coefficients of a FTps.
Definition: FTps.hpp:1515
FTps inverse(int trunc=EXACT) const
Reciprocal, 1/(*this).
Definition: FTps.hpp:707
FTps taylor(const Array1D< T > &series, int order) const
Taylor series.
Definition: FTps.hpp:1481
FTps & operator/=(const FTps &y)
Divide and assign.
Definition: FTps.hpp:551
void setTruncOrder(int order)
Set truncation order.
Definition: FTps.hpp:393
std::istream & get(std::istream &is)
Read FTps on the stream [b]is[/b].
Definition: FTps.hpp:1571
FTps & operator+=(const FTps &y)
Add and assign.
Definition: FTps.hpp:533
FTps()
Default constructor.
Definition: FTps.hpp:159
static FTps makeVarPower(int var, int power)
Make power.
Definition: FTps.hpp:489
FTps integral(int var, int trunc=EXACT) const
Partial integral.
Definition: FTps.hpp:1441
~FTps()
Destructor.
Definition: FTps.hpp:194
int getMinOrder() const
Get minimum order.
Definition: FTps.h:165
static FTpsRep< T, N > * allocate(int minOrder, int maxOrder, int trcOrder)
Definition: FTps.hpp:1692
FTps truncate(int trunc)
Truncate.
Definition: FTps.hpp:475
int getTruncOrder() const
Get truncation order.
Definition: FTps.h:183
static void checkOrders(const std::string &method, int minOrder, int maxOrder, int &trcOrder)
Definition: FTps.hpp:1767
FTps multiply(const FTps &y, int trunc=EXACT) const
Multiplication.
Definition: FTps.hpp:650
std::ostream & put(std::ostream &os) const
Write FTps on the stream [b]os[/b].
Definition: FTps.hpp:1648
const T operator[](int index) const
Get coefficient.
Definition: FTps.hpp:275
FTps & operator-=(const FTps &y)
Subtract and assign.
Definition: FTps.hpp:539
FTps operator+() const
Unary plus.
Definition: FTps.hpp:517
static FTps makeMonomial(int index, const T &t)
Make monomial.
Definition: FTps.hpp:499
int getSize() const
Get total number of coefficients.
Definition: FTps.h:136
FTps & operator=(const FTps &y)
Assign.
Definition: FTps.hpp:201
static Array1D< T > evalMonoms(const FVector< T, N > &, int)
Evaluate monomials at point.
Definition: FTps.hpp:898
FTps multiplyVariable(int var, int trunc=EXACT) const
Multiply by variable [b]var[/b].
Definition: FTps.hpp:610
FTps derivative(int var) const
Partial derivative.
Definition: FTps.hpp:1396
void unique()
Make representation unique.
Definition: FTps.hpp:1505
FVps< T, N > gradient() const
Gradient.
Definition: FTps.hpp:1433
bool operator!=(const FTps &y) const
Inequality operator.
Definition: FTps.hpp:886
FTps & operator*=(const FTps &y)
Multiply and assign.
Definition: FTps.hpp:545
T * begin() const
Return beginning of monomial array.
Definition: FTps.h:118
void setCoefficient(int index, const T &value)
Set coefficient.
Definition: FTps.hpp:236
static FTps makeVariable(int var)
Make variable.
Definition: FTps.hpp:481
static int orderEnd(int order)
Get one plus index at which [b]order[/b] ends.
Definition: FTps.h:147
FTps divide(const FTps &y, int trunc=EXACT) const
Division.
Definition: FTps.hpp:761
T evaluate(const FVector< T, N > &) const
Evaluate FTps at point.
Definition: FTps.hpp:934
static void setGlobalTruncOrder(int order)
Set the global truncation order.
Definition: FTps.hpp:419
static const Array1D< TpsSubstitution > & getSubTable()
Return the substitution table.
Definition: FTps.hpp:445
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
FTpsRep< T, N > * itsRep
Definition: FTps.h:405
static int orderStart(int order)
Get index at which [b]order[/b] starts.
Definition: FTps.h:143
void setMaxOrder(int order)
Set maximum order.
Definition: FTps.hpp:357
T * end() const
Return end of monomial array.
Definition: FTps.h:121
Array1D< int > getSubstOrders(const FVps< T, N > &rhs, int trunc=EXACT) const
Return orders {min, max, trc} of f(rhs(z)).
Definition: FTps.hpp:1008
static const FMonomial< N > & getExponents(int index)
Get exponents for given index.
Definition: FTps.hpp:309
bool operator==(const FTps &y) const
Equality operator.
Definition: FTps.hpp:831
static const Array1D< int > & getVariableList(int index)
List of variables contained in monomial "index".
Definition: FTps.hpp:439
FTps scaleMonomials(const FTps &y) const
Scale monomial coefficients by coefficients in [b]y[/b].
Definition: FTps.hpp:589
FTps filter(int minOrder, int maxOrder, int trcOrder=EXACT) const
Extract given range of orders, with truncation.
Definition: FTps.hpp:451
FArray1D< int, N > extractExponents(int index) const
Extract exponents of coefficient.
Definition: FTps.hpp:1535
FTps operator-() const
Unary minus.
Definition: FTps.hpp:523
static int getIndex(const FMonomial< N > &mono)
Get Giorgilli index for monomial.
Definition: FTps.hpp:315
void setMinOrder(int order)
Set minimum order.
Definition: FTps.hpp:321
void grow(int maxOrder, int trcOrder)
Definition: FTps.hpp:1734
Representation of the exponents for a monomial with fixed dimension.
Definition: FMonomial.h:32
int getOrder() const
Compute the monomial's order.
Definition: FMonomial.h:124
Definition: FTps.hpp:56
T * begin() const
Definition: FTps.hpp:75
void clear()
Definition: FTps.hpp:135
int len
Definition: FTps.hpp:107
int maxOrd
Definition: FTps.hpp:98
int allocOrd
Definition: FTps.hpp:100
int ref
Definition: FTps.hpp:94
T * end(int order) const
Definition: FTps.hpp:87
int minOrd
Definition: FTps.hpp:97
FTpsRep(int minOrder, int maxOrder, int trcOrder)
Definition: FTps.hpp:118
T * data
Definition: FTps.hpp:110
int trcOrd
Definition: FTps.hpp:99
FTpsRep< T, N > * next
Definition: FTps.hpp:91
T * end() const
Definition: FTps.hpp:79
~FTpsRep()
Definition: FTps.hpp:129
void clear(int minOrder, int maxOrder)
Definition: FTps.hpp:141
T * begin(int order) const
Definition: FTps.hpp:83
A templated representation for vectors.
Definition: FVector.h:38
Internal utility class for FTps<T,N> class.
Definition: FTpsData.h:33
static int orderEnd(int order)
Definition: FTpsData.h:208
static const FMonomial< N > & getExponents(int index)
Definition: FTpsData.h:158
static int getIndex(const FMonomial< N > &)
Definition: FTpsData.h:165
static const Array1D< TpsSubstitution > & getSubTable()
Definition: FTpsData.h:268
static int getOrder(int index)
Definition: FTpsData.h:180
static int getSize(int order)
Definition: FTpsData.h:187
static const Array1D< int > & getVariableList(int index)
Definition: FTpsData.h:244
static void setup(int order)
Definition: FTpsData.h:275
static int orderStart(int order)
Definition: FTpsData.h:194
static const Array1D< int > & getProductArray(int index)
Definition: FTpsData.h:237
Convergence error exception.
Zero divide error.
Definition: DivideError.h:32
Format error exception.
Definition: FormatError.h:32
Logical error exception.
Definition: LogicalError.h:33
int precision() const
Definition: Inform.h:112