24
24
// ====
25
25
// Author: Ximenes R. Resende
26
26
27
- // affiliation: LNLS - Laboratorio Nacional de Luz Sincrotron
28
- // Date: August 31st, 2006 @ LNLS
27
+ // affiliation: LNLS - Laboratório Nacional de Luz Síncrotron
28
+ // Date: August 31st, 2006 @ LNLS
29
29
//
30
30
// Notes:
31
31
//
32
- // 01. This is an implementation for a pre-defined-at-compile-time number of variables
33
- // and of polynomial order.
34
- // 02. Multiplication algorithm makes use of one OSIP (one-step index pointer) in a
35
- // forward scheme (as thought by A. Dragt, according to Y. Yan) in order to achieve
36
- // optimized efficiency.
37
- // 03. I have to better understand template friend functions and operators. This way I
38
- // should be able to convert some non-member functions to friends and improve
39
- // their algorithms by having access to protected class members. Try to ask folks
40
- // from the C++ community?
41
- // 04. Is it worth trying to implement syntactic sugars with expression templates in order
42
- // to minimize the problem of temporaries? It is not clear for me that, for the TPS class,
43
- // something is to be gained in terms of efficiency...
44
- // 05. Is it worth trying to implement multiplication with FFT? How to map multivariate
45
- // polynomials into (can it be onto?) univariate polynomials of higher order? The prospects
46
- // of using FFT are interesting since the Beam Dynamics community does not seem to have
47
- // realized that the method could speed up calculation of taylor maps...
32
+ // 01. This is an implementation for a pre-defined-at-compile-time number
33
+ // of variables and of polynomial order.
34
+ // 02. Multiplication algorithm makes use of one OSIP (one-step index pointer)
35
+ // in a forward scheme (as thought by A. Dragt, according to Y. Yan) in
36
+ // order to achieve optimized efficiency.
37
+ // 03. I have to better understand template friend functions and operators.
38
+ // This way I should be able to convert some non-member functions to
39
+ // friends and improve their algorithms by having access to protected
40
+ // class members. Try to ask folks from the C++ community?
41
+ // 04. Is it worth trying to implement syntactic sugars with expression
42
+ // templates in order to minimize the problem of temporaries ?
43
+ // It is not clear for me that, for the TPS class, something is to be
44
+ // gained in terms of efficiency...
45
+ // 05. Is it worth trying to implement multiplication with FFT? How to map
46
+ // multivariate polynomials into (can it be onto?) univariate polynomials
47
+ // of higher order? The prospects of using FFT are interesting since the
48
+ // beam dynamics community does not seem to have realized that the method
49
+ // could speed up calculation of taylor maps...
48
50
49
51
50
52
54
56
#include < complex>
55
57
#include < cstring>
56
58
#include < ostream>
59
+ #include < vector>
57
60
58
61
59
- // Expression Templates: IMPLEMENTATION OF BINOMIALS COEFFICIENTS AND RELATED RELEVANT EXPRESSIONS
60
- // -----------------------------------------------------------------------------------------------
62
+ // Expression Templates:
63
+ // IMPLEMENTATION OF BINOMIALS COEFFICIENTS AND RELATED RELEVANT EXPRESSIONS
64
+ // -------------------------------------------------------------------------
61
65
62
66
template <int N, int K> struct et_binomial { enum { val = et_binomial<N-1 ,K-1 >::val + et_binomial<N-1 ,K>::val }; };
63
67
template <int K> struct et_binomial <0 ,K> { enum { val = 0 }; };
@@ -158,9 +162,11 @@ class Tpsa {
158
162
static unsigned int get_size () { return et_binomial<N+V,V>::val; }
159
163
static unsigned int get_osip_size () { return et_osip<V,N,N>::val; }
160
164
static unsigned int get_index (const unsigned int * power_);
161
- static void get_power (const unsigned int idx, unsigned int * power);
165
+ static void get_power (const unsigned int idx,
166
+ unsigned int * power);
162
167
const TYPE& get_c (unsigned int index) const { return c[index ]; }
163
168
TYPE& set_c (unsigned int index) { return c[index ]; }
169
+ TYPE eval (const std::vector<TYPE>& val) const ;
164
170
165
171
// private:
166
172
public:
@@ -172,9 +178,15 @@ class Tpsa {
172
178
static unsigned int osip[et_osip<V,N,N>::val];
173
179
static unsigned int powers[et_osip<V,N,N>::val][V];
174
180
175
- static unsigned int & C (unsigned int v, unsigned int n) { return binomials[(((v+n-1 )*(n+v))>>1 ) + n]; }
176
- static unsigned int first_at_order (unsigned int order) { return (order==0 ) ? 0 : C (V,order-1 ); }
177
- static unsigned int last_at_order (unsigned int order) { return (order==0 ) ? 1 : C (V,order); }
181
+ static unsigned int & C (unsigned int v, unsigned int n) {
182
+ return binomials[(((v+n-1 )*(n+v))>>1 ) + n];
183
+ }
184
+ static unsigned int first_at_order (unsigned int order) {
185
+ return (order==0 ) ? 0 : C (V,order-1 );
186
+ }
187
+ static unsigned int last_at_order (unsigned int order) {
188
+ return (order==0 ) ? 1 : C (V,order);
189
+ }
178
190
179
191
};
180
192
@@ -464,12 +476,30 @@ void Tpsa<V,N,TYPE>::get_power(unsigned int idx_, unsigned int* power_) {
464
476
}
465
477
}
466
478
479
+ template <unsigned int V, unsigned int N, typename TYPE>
480
+ TYPE Tpsa<V,N,TYPE>::eval(const std::vector<TYPE>& val) const {
481
+ if (val.size () != V) {
482
+ std::cerr << " Invalid vector size in Tpsa::eval!" << std::endl;
483
+ return 0 ;
484
+ }
485
+ TYPE r = 0 ;
486
+ unsigned int power[V];
487
+ for (unsigned int i=0 ; i<this ->get_size (); i++) {
488
+ TYPE mon = this ->c [i];
489
+ this ->get_power (i,power);
490
+ for (unsigned int j=0 ; j<val.size (); j++) {
491
+ mon *= std::pow (val[j], power[j]);
492
+ }
493
+ r += mon;
494
+ }
495
+ return r;
496
+ }
467
497
468
-
469
- // Implementation: NON-MEMBER FUNCTIONS AND OPERATORS WITH ARGUMENTS OF CLASS TYPE
470
- // -------------------------------------------------------------------------------
471
- // Note : these functions are generating Stack Overflow at run-time for large N,V
472
- // (N=10,V=10 for example) at a P4 with 1Gb of RAM
498
+ // Implementation:
499
+ // NON-MEMBER FUNCTIONS AND OPERATORS WITH ARGUMENTS OF CLASS TYPE
500
+ // ---------------------------------------------------------------
501
+ // NOTE : these functions are generating Stack Overflow at run-time for
502
+ // large N,V (N=10,V=10 for example) at a P4 with 1Gb of RAM
473
503
474
504
template <typename T, unsigned int V, unsigned int N, typename TYPE>
475
505
Tpsa<V,N,TYPE> operator + (const T& o1, const Tpsa<V,N,TYPE>& o2) { return o2 + o1; }
@@ -493,7 +523,8 @@ Tpsa<V,N,TYPE> pow(const Tpsa<V,N,TYPE>& a_, const int n) {
493
523
return r;
494
524
} else {
495
525
// for more efficient computation when n >~ N,
496
- // multiplication implemented as N-truncated binomial expansion a0^n*(1 + x/a0)^n, x^(N+1) = 0
526
+ // multiplication implemented as N-truncated binomial expansion
527
+ // a0^n*(1 + x/a0)^n, x^(N+1) = 0
497
528
Tpsa<V,N,TYPE> r;
498
529
Tpsa<V,N,TYPE> x (a_); x.c [0 ] = 0 ; x /= a_.c [0 ];
499
530
Tpsa<V,N,TYPE> p (1 );
@@ -622,7 +653,8 @@ Tpsa<V,N,TYPE> atan(const Tpsa<V,N,TYPE>& a_) {
622
653
TYPE s1 = a_.c [0 ] * c1;
623
654
TYPE ci = c1;
624
655
TYPE si = s1;
625
- // ArcTan function implementation based on expression D[1/(1+x^2)] = (1/2) D[1/(1+xi) + 1/(1-xi)]
656
+ // ArcTan function implementation based on expression
657
+ // D[1/(1+x^2)] = (1/2) D[1/(1+xi) + 1/(1-xi)]
626
658
for (int i=1 ; i<=N; i++) {
627
659
if (i&1 ) {
628
660
// odd terms
@@ -673,7 +705,8 @@ Tpsa<V,N,TYPE> atanh(const Tpsa<V,N,TYPE>& a_) {
673
705
TYPE s1 = a_.c [0 ] * c1;
674
706
TYPE ci = c1;
675
707
TYPE si = s1;
676
- // ArcTan function implementation based on expression D[1/(1+x^2)] = (1/2) D[1/(1+xi) + 1/(1-xi)]
708
+ // ArcTan function implementation based on expression
709
+ // D[1/(1+x^2)] = (1/2) D[1/(1+xi) + 1/(1-xi)]
677
710
for (int i=1 ; i<=N; i++) {
678
711
if (i&1 ) {
679
712
// odd terms
0 commit comments