Grid 0.7.0
RemezGeneral.h
Go to the documentation of this file.
1/*
2 C.Kelly Jan 2020 based on implementation by M. Clark May 2005
3
4 AlgRemezGeneral is an implementation of the Remez algorithm for approximating an arbitrary function by a rational polynomial
5 It includes optional restriction to odd/even polynomials for the numerator and/or denominator
6*/
7
8#ifndef INCLUDED_ALG_REMEZ_GENERAL_H
9#define INCLUDED_ALG_REMEZ_GENERAL_H
10
11#include <stddef.h>
12#include <Grid/GridStd.h>
13
14#ifdef HAVE_LIBGMP
15#include "bigfloat.h"
16#else
17#include "bigfloat_double.h"
18#endif
19
20
22 public:
23 enum PolyType { Even, Odd, Full };
24
25 private:
26
27 // In GSL-style, pass the function as a function pointer. Any data required to evaluate the function is passed in as a void pointer
28 bigfloat (*f)(bigfloat x, void *data);
29 void *data;
30
31 // The approximation parameters
32 std::vector<bigfloat> param;
34
35 // The number of non-zero terms in the numerator and denominator
36 int n, d;
37 // The numerator and denominator degree (i.e. the largest power)
39
40 // Specify if the numerator and/or denominator are odd/even polynomials
43 std::vector<int> num_pows; //contains the mapping, with -1 if not present
44 std::vector<int> den_pows;
45
46 // The bounds of the approximation
48
49 // Variables used to calculate the approximation
50 int nd1, iter;
51 std::vector<bigfloat> xx;
52 std::vector<bigfloat> mm;
53 std::vector<bigfloat> step;
54
56
57 // Variables used in search
58 std::vector<bigfloat> yy;
59
60 // Variables used in solving linear equations
61 std::vector<bigfloat> A;
62 std::vector<bigfloat> B;
63 std::vector<int> IPS;
64
65 // The number of equations we must solve at each iteration (n+d+1)
66 int neq;
67
68 // The precision of the GNU MP library
69 long prec;
70
71 // Initialize member variables associated with the polynomial's properties
72 void setupPolyProperties(int num_degree, int den_degree, PolyType num_type_in, PolyType den_type_in);
73
74 // Initial values of maximal and minmal errors
75 void initialGuess();
76
77 // Initialise step sizes
78 void stpini();
79
80 // Initialize the algorithm
82
83 // Solve the equations
84 void equations();
85
86 // Search for error maxima and minima
87 void search();
88
89 // Calculate function required for the approximation
90 inline bigfloat func(bigfloat x) const{
91 return f(x, data);
92 }
93
94 // Compute size and sign of the approximation error at x
95 bigfloat getErr(bigfloat x, int *sign) const;
96
97 // Solve the system AX=B where X = param
98 int simq();
99
100 // Evaluate the rational form P(x)/Q(x) using coefficients from the solution vector param
101 bigfloat approx(bigfloat x) const;
102
103 public:
104
105 AlgRemezGeneral(double lower, double upper, long prec,
106 bigfloat (*f)(bigfloat x, void *data), void *data);
107
108 inline int getDegree(void) const{
109 assert(n==d);
110 return n;
111 }
112 // Reset the bounds of the approximation
113 inline void setBounds(double lower, double upper) {
114 apstrt = lower;
115 apend = upper;
116 apwidt = apend - apstrt;
117 }
118
119 // Get the bounds of the approximation
120 inline void getBounds(double &lower, double &upper) const{
121 lower=(double)apstrt;
122 upper=(double)apend;
123 }
124
125 // Run the algorithm to generate the rational approximation
126 double generateApprox(int num_degree, int den_degree,
128 const double tolerance = 1e-15, const int report_freq = 1000);
129
130 inline double generateApprox(int num_degree, int den_degree,
131 const double tolerance = 1e-15, const int report_freq = 1000){
132 return generateApprox(num_degree, den_degree, Full, Full, tolerance, report_freq);
133 }
134
135 // Evaluate the rational form P(x)/Q(x) using coefficients from the
136 // solution vector param
137 inline double evaluateApprox(double x) const{
138 return (double)approx((bigfloat)x);
139 }
140
141 // Evaluate the rational form Q(x)/P(x) using coefficients from the solution vector param
142 inline double evaluateInverseApprox(double x) const{
143 return 1.0/(double)approx((bigfloat)x);
144 }
145
146 // Calculate function required for the approximation
147 inline double evaluateFunc(double x) const{
148 return (double)func((bigfloat)x);
149 }
150
151 // Calculate inverse function required for the approximation
152 inline double evaluateInverseFunc(double x) const{
153 return 1.0/(double)func((bigfloat)x);
154 }
155
156 // Dump csv of function, approx and error
157 void csv(std::ostream &os = std::cout) const;
158
159 // Get the coefficient of the term x^i in the numerator
160 inline double getCoeffNum(const int i) const{
161 return num_pows[i] == -1 ? 0. : double(param[num_pows[i]]);
162 }
163 // Get the coefficient of the term x^i in the denominator
164 inline double getCoeffDen(const int i) const{
165 if(i == pow_d) return 1.0;
166 else return den_pows[i] == -1 ? 0. : double(param[den_pows[i]+n+1]);
167 }
168};
169
170#endif
PolyType num_type
std::vector< bigfloat > xx
std::vector< bigfloat > A
double generateApprox(int num_degree, int den_degree, PolyType num_type, PolyType den_type, const double tolerance=1e-15, const int report_freq=1000)
void setupPolyProperties(int num_degree, int den_degree, PolyType num_type_in, PolyType den_type_in)
std::vector< int > num_pows
double evaluateApprox(double x) const
bigfloat approx(bigfloat x) const
bigfloat func(bigfloat x) const
void csv(std::ostream &os=std::cout) const
bigfloat(* f)(bigfloat x, void *data)
double getCoeffNum(const int i) const
bigfloat getErr(bigfloat x, int *sign) const
PolyType den_type
double evaluateFunc(double x) const
void setBounds(double lower, double upper)
std::vector< bigfloat > param
void reinitializeAlgorithm()
double getCoeffDen(const int i) const
double evaluateInverseFunc(double x) const
AlgRemezGeneral(double lower, double upper, long prec, bigfloat(*f)(bigfloat x, void *data), void *data)
void getBounds(double &lower, double &upper) const
std::vector< bigfloat > step
double evaluateInverseApprox(double x) const
std::vector< bigfloat > B
int getDegree(void) const
std::vector< int > IPS
std::vector< int > den_pows
double generateApprox(int num_degree, int den_degree, const double tolerance=1e-15, const int report_freq=1000)
std::vector< bigfloat > mm
std::vector< bigfloat > yy