Skip to content

Commit d23d207

Browse files
authored
Merge pull request #77 from lnls-fac/add-eval-tpsa
Add eval function in Tpsa class
2 parents bb21dc0 + bf2af2f commit d23d207

File tree

1 file changed

+65
-32
lines changed

1 file changed

+65
-32
lines changed

include/trackcpp/tpsa.h

+65-32
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,29 @@
2424
// ====
2525
// Author: Ximenes R. Resende
2626
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
2929
//
3030
// Notes:
3131
//
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...
4850

4951

5052

@@ -54,10 +56,12 @@
5456
#include <complex>
5557
#include <cstring>
5658
#include <ostream>
59+
#include <vector>
5760

5861

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+
// -------------------------------------------------------------------------
6165

6266
template <int N, int K> struct et_binomial { enum { val = et_binomial<N-1,K-1>::val + et_binomial<N-1,K>::val }; };
6367
template <int K> struct et_binomial<0,K> { enum { val = 0 }; };
@@ -158,9 +162,11 @@ class Tpsa {
158162
static unsigned int get_size() { return et_binomial<N+V,V>::val; }
159163
static unsigned int get_osip_size() { return et_osip<V,N,N>::val; }
160164
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);
162167
const TYPE& get_c(unsigned int index) const { return c[index]; }
163168
TYPE& set_c(unsigned int index) { return c[index]; }
169+
TYPE eval(const std::vector<TYPE>& val) const;
164170

165171
//private:
166172
public:
@@ -172,9 +178,15 @@ class Tpsa {
172178
static unsigned int osip[et_osip<V,N,N>::val];
173179
static unsigned int powers[et_osip<V,N,N>::val][V];
174180

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+
}
178190

179191
};
180192

@@ -464,12 +476,30 @@ void Tpsa<V,N,TYPE>::get_power(unsigned int idx_, unsigned int* power_) {
464476
}
465477
}
466478

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+
}
467497

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
473503

474504
template <typename T, unsigned int V, unsigned int N, typename TYPE>
475505
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) {
493523
return r;
494524
} else {
495525
// 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
497528
Tpsa<V,N,TYPE> r;
498529
Tpsa<V,N,TYPE> x(a_); x.c[0] = 0; x /= a_.c[0];
499530
Tpsa<V,N,TYPE> p(1);
@@ -622,7 +653,8 @@ Tpsa<V,N,TYPE> atan(const Tpsa<V,N,TYPE>& a_) {
622653
TYPE s1 = a_.c[0] * c1;
623654
TYPE ci = c1;
624655
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)]
626658
for(int i=1; i<=N; i++) {
627659
if (i&1) {
628660
// odd terms
@@ -673,7 +705,8 @@ Tpsa<V,N,TYPE> atanh(const Tpsa<V,N,TYPE>& a_) {
673705
TYPE s1 = a_.c[0] * c1;
674706
TYPE ci = c1;
675707
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)]
677710
for(int i=1; i<=N; i++) {
678711
if (i&1) {
679712
// odd terms

0 commit comments

Comments
 (0)