UNIVERS  15.3
UNIVERS base processing software API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
s2_ftrans.hpp
1 /* s2_ftrans.hpp */
2 /* $Id: s2_ftrans.hpp 21267 2011-11-23 15:19:39Z guser1 $ */
3 #ifndef __s2_ftrans_hpp
4 #define __s2_ftrans_hpp
5 
6 #include <stdio.h>
7 #include <vector>
8 #include <math.h>
9 
10 #ifdef GE_BUILD
11 #include <least_squares_2d.hpp>
12 #else
13 #include <mth/least_squares_2d.hpp>
14 #endif
15 
16 namespace FTrans{
17 
18  typedef double arg_type;
19 
21  class BaseFunc {
22 
23  public:
24 
25  virtual ~BaseFunc() {};
26 
28  arg_type operator ()(arg_type x) { return calc(x); };
29 
30  protected:
31 
33  virtual arg_type calc(arg_type x) const = 0;
34  };
35 
37  class InverseFunc : public BaseFunc {
38  protected:
39 
40  virtual arg_type calc(arg_type x) const;
41 
42  };
43 
44  template<typename TR>
45  void ftrans(std::vector<arg_type> &func, arg_type &xmn, arg_type &xmx)
46  {
47 #define FTRANS_REAL_EPS 1.e-6
48  int debug = 0;
49  TR trans;
50 
51  /* Recalculate argument limits */
52  arg_type zmn = trans(xmn);
53  arg_type zmx = trans(xmx);
54  if (debug>0)
55  printf("INFO: ftrans: new arg limits %lg->%lg\n", zmn, zmx);
56 
57  std::vector<arg_type> args(func.size());
58  arg_type dx = (xmx-xmn) / (func.size()-1.);
59 
60  /* Recalculate arguments */
61  arg_type x_cur = xmn;
62  for(int i=0; i<func.size(); ++i) {
63  args[i] = trans(x_cur);
64  if (debug>0)
65  printf("INFO: ftrans: arg[%ld] = %lg -> %lg\n", i, x_cur, args[i]);
66  x_cur += dx;
67  }
68  if (debug>0)
69  printf("INFO: ftrans: func recalculated...\n");
70 
71  std::vector<arg_type> func_new;
72 
73 #if 0
74  /* Save function on new irregular grid */
75  FILE* f = fopen("ftrans_res1_f.dat", "w");
76  for(int i=0; i<func.size(); ++i)
77  fprintf(f,"%g\t%g\n", args[i], func[i]);
78  fclose(f);
79 #endif
80 
81  std::size_t i_max = func.size()-1;
82 
83  /* Calculate regular argument grid step */
84  arg_type dz = (zmx-zmn) / (func.size()-1.);
85 #if 1
86  /* Find the minimal step in new irregular argument grid, and use it as the step of new regular grid. */
87  for(int i=1; i<func.size(); ++i) {
88  if (fabs(dz) > fabs(args[i]-args[i-1]))
89  dz = args[i]-args[i-1];
90  }
91  i_max = int(fabs((zmx-zmn)/dz));
92 #endif
93  if (debug>0)
94  printf("INFO: ftrans: dz=%lg...\n", dz);
95  arg_type z_cur = zmn+dz;
96 
97  /* Add first function value (immovable) */
98  func_new.push_back(func[0]);
99 
100  for(std::size_t i=1; i<i_max; ++i) {
101  std::size_t j=0;
102  bool bingo = false;
103 
104  /* Search two values of argument (irregular grid) on both sides from the current argument value (regular grid) */
105  for(; j<func.size()-1; ++j) {
106  //double tmp = double(args[j]-z_cur);
107  if (fabs(args[j]-z_cur) < FTRANS_REAL_EPS) { bingo = true; break; }
108  if (args[j]>z_cur && args[j+1]<z_cur) break;
109  if (args[j]<z_cur && args[j+1]>z_cur) break;
110  }
111  if (j == func.size()-1) {
112  printf("ERROR: arg=%lg was not found...\n", z_cur);
113  z_cur+=dz;
114  continue;
115  }
116  else
117  if (debug>0)
118  printf("INFO: ftrans: arg=%lg limits found, j0=%zu...\n", z_cur, j);
119 
120  if (bingo) { /* The current argument value is equal to some value of argument of irregular grid */
121  func_new.push_back(func[j]);
122  z_cur+=dz;
123  continue;
124  }
125 
126  /* Form arrays of points (irregular grid argument values) in the neighbourhood of current argument value.
127  Mean goal - to form the polynom and calculate function value with respect to current argument value.
128  Number of selected points = degree of selected polynom + 1. Default polynom - parabolic. */
129  unsigned int p_num = 3;
130  std::vector<double> xp(p_num); //xp[0] = args[j]; xp[1] = args[j+1]; xp[2] = (j<(func.size()-2)) ? args[j+2] : args[j-1];
131  std::vector<double> yp(p_num); //yp[0] = func[j]; yp[1] = func[j+1]; yp[2] = (j<(func.size()-2)) ? func[j+2] : func[j-1];
132 
133  if ((j+p_num-1) >= func.size())
134  j = func.size()-p_num;
135 
136  for (std::size_t i=0; i<p_num; ++i) {
137  xp[i] = args[j];
138  yp[i] = func[j];
139  if (debug>0)
140  printf("INFO: ftrans: arg=%lg func[%zu] = %lg\n", z_cur, j, yp[i]);
141  ++j;
142  }
143 
144  unsigned int deg = p_num-1;
145  //deg = 2;
146  LeastSquares2D::PolyCoeffs coeffs(deg+1);
147  bool ok = LeastSquares2D::getPoly(xp, yp, coeffs);
148  if (!ok) {
149  printf("ERROR: ftrans: arg=%lg : failed to form poly...", z_cur);
150  }
151  else {
152  double res = LeastSquares2D::calcPoly(coeffs, (double)z_cur);
153  func_new.push_back(res);
154 
155  if (debug>0)
156  printf("INFO: ftrans: arg=%lg process complete... val=%lg\n", z_cur, res);
157  }
158 
159  z_cur+=dz;
160  } // end of the cycle along argument range
161 
162 
163  /* Add last function value (immovable) */
164  func_new.push_back(func[func.size()-1]);
165  if (debug>0)
166  printf("INFO: ftrans: new func formed...\n");
167 
168  /* Clear initial function data */
169  func.clear();
170 
171  /* Form result */
172  for(std::size_t i=0; i<func_new.size(); ++i) {
173  if (zmn>zmx)
174  func.push_back(func_new[func_new.size()-i-1]);
175  else
176  func.push_back(func_new[i]);
177  if (debug>0)
178  printf("INFO: ftrans: new func [%zu] = %lg\n", i, func[i]);
179  }
180 
181  /* Define correct argument limits sequence */
182  if (zmn>zmx) {
183  arg_type tmp = zmn;
184  zmn = zmx;
185  zmx = tmp;
186  }
187 
188  xmn = zmn;
189  xmx = zmx;
190  //printf("INFO: ftrans: xmn=%lg xmx=%lg\n", xmn, xmx);
191  if (debug>0)
192  printf("INFO: ftrans: complete...\n");
193 #undef FTRANS_REAL_EPS
194  };
195 
196 };
197 
198 
199 #endif /* s2_ftrans.hpp */
bool getPoly(const vector< double > &x, const vector< double > &y, const vector< double > &w, PolyCoeffs &cfs)
Definition: s2_ftrans.hpp:21
virtual arg_type calc(arg_type x) const =0
arg_type operator()(arg_type x)
Definition: s2_ftrans.hpp:28
Definition: s2_ftrans.hpp:37
std::vector< PolyCoeff > PolyCoeffs
Definition: least_squares_2d.hpp:25
double calcPoly(const PolyCoeffs &coeffs, double x)
virtual arg_type calc(arg_type x) const