Xmipp  v3.23.11-Nereus
integration.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Javier Rodriguez Falces (jrodriguez@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "integration.h"
27 #include "core/matrix1d.h"
28 #include "core/numerical_recipes.h"
29 #include <array>
30 
31 /* Integrate --------------------------------------------------------------- */
32 double integrateNewtonCotes(double(*f)(double),
33  double a, double b, int N)
34 {
35  if (N < 2 || N > 9)
36  REPORT_ERROR(ERR_VALUE_INCORRECT, "integrateNewtonCotes: N must be greater than 1");
37  double h = (b - a) / (N - 1);
38  Matrix1D<double> fx(N);
39  for (int i = 0; i < N; i++)
40  fx(i) = (*f)(a + i * h);
41  switch (N)
42  {
43  case 2:
44  return h / 2*(fx(0) + fx(1));
45  case 3:
46  return h / 3*(fx(0) + 4*fx(1) + fx(2));
47  case 4:
48  return h*3.0 / 8.0*((fx(0) + fx(3)) + 3*(fx(1) + fx(2)));
49  case 5:
50  return h*2.0 / 45.0*(7*(fx(0) + fx(4)) + 32*(fx(1) + fx(3)) + 12*fx(2));
51  case 6:
52  return h*5.0 / 288.0*(19*(fx(0) + fx(5)) + 75*(fx(1) + fx(4)) + 50*(fx(2) + fx(3)));
53  case 7:
54  return h / 140.0*(41*(fx(0) + fx(6)) + 216*(fx(1) + fx(5)) + 27*(fx(2) + fx(4)) +
55  272*fx(3));
56  case 8:
57  return h*7.0 / 17280.0*(751*(fx(0) + fx(7)) + 3577*(fx(1) + fx(6)) + 1323*(fx(2) + fx(5)) +
58  2989*(fx(3) + fx(4)));
59  case 9:
60  return 4.0 / 14175.0*h*(989*(fx(0) + fx(8)) + 5888*(fx(1) + fx(7)) +
61  -928*(fx(2) + fx(6)) + 10496*(fx(3) + fx(5)) - 4540*fx(4));
62  }
63  REPORT_ERROR(ERR_ARG_INCORRECT,"Number of points is too high");
64 }
65 
66 //**********************************************************
67 // Implementation of the integral using the Trapeze method
68 //**********************************************************
69 
71 { //adapted from qtrap
72  double s_internal;
73  double olds;
74  int j;
75  olds = -1.0e30;
76  for (j = 1;j <= JMAX;j++)
77  {
78  s_internal = Trap(j); //changed; Trap is integrating fcn
79  if (fabs(s_internal - olds) <= EPS*fabs(olds))
80  return s_internal;
81  if (s_internal == 0.0 && olds == 0.0 && j > 6)
82  return s_internal;
83  olds = s_internal;
84  }
85  REPORT_ERROR(ERR_NUMERICAL,"Too many steps in routine qtrap_y\n");
86 }
87 
88 
89 double Trapeze::Trap(int n)
90 { //adapted from trapzd
91  double tnm;
92  double sum;
93  double del;
94  int j;
95  int it;
96  if (n == 1)
97  {
98  it = 1;
99  x = a;
100  s = func(); //changed
101  x = b;
102  s += func(); //changed
103  return (s *= 0.5 * (b - a));
104  }
105  else
106  {
107  for (it = 1, j = 1;j < n - 1;j++)
108  it <<= 1;
109  tnm = it;
110  del = (b - a) / tnm;
111  x = a + 0.5 * del;
112  for (sum = 0.0, j = 1;j <= it;j++, x += del)
113  sum += func(); //changed
114  s = 0.5 * (s + (b - a) * sum / tnm);
115  return s;
116  }
117 }
118 
119 //**********************************************************
120 // Implementation of the integral using the Romberg method
121 //**********************************************************mask.cpp to adapt
122 constexpr int JMAXP = 30;
123 constexpr int K = 5;
124 
126 { //adapted from qromb
127  int j;
128  double ss;
129  double dss;
130  std::array<double, JMAXP+2> h;
131  std::array<double, JMAXP+2> s_internal;
132  h[1] = 1.0;
133  for (j = 1;j <= JMAXP;j++)
134  {
135  s_internal[j] = midpnt(j); //changed; midpnt is integrating
136  if (j >= K)
137  { //function
138  polint(&h[j-K], &s_internal[j-K], K, 0.0, ss, dss);
139  if (fabs(dss) <= EPS*fabs(ss))
140  return ss;
141  }
142  s_internal[j+1] = s_internal[j];
143  h[j+1] = h[j] / 9.0;
144  }
145  REPORT_ERROR(ERR_NUMERICAL,"Too many steps in routine Romberg");
146 }
147 
148 //*
149 // The midpnt function is used in the Romberg::operator only
150 //*
151 double Romberg::midpnt(int n)
152 { //adapted from midpoint
153  double tnm;
154  double sum;
155  double del;
156  double ddel;
157  int it;
158  int j;
159  if (n == 1)
160  {
161  x = 0.5 * (a + b); //changed; set x
162  return (s = (b - a) * func()); //changed; evaluate func
163  }
164  else
165  {
166  for (it = 1, j = 1;j < n - 1;j++)
167  it *= 3;
168  tnm = it;
169  del = (b - a) / (3.0 * tnm);
170  ddel = del + del;
171  x = a + 0.5 * del;
172  sum = 0.0;
173  for (j = 1;j <= it;j++)
174  {
175  sum += func(); //changed; evaluate func
176  x += ddel; //changed; set x
177  sum += func(); //changed; evaluate func
178  x += del; //changed; set x
179  }
180  s = (s + (b - a) * sum / tnm) / 3.0;
181  return s;
182  }
183 }
184 
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
float del
constexpr int JMAXP
#define i
double integrateNewtonCotes(double(*f)(double), double a, double b, int N)
Definition: integration.cpp:32
doublereal * b
double * f
Incorrect argument received.
Definition: xmipp_error.h:113
Error related to numerical calculation.
Definition: xmipp_error.h:179
void polint(double *xa, double *ya, int n, double x, double &y, double &dy)
virtual double operator()()
#define j
constexpr int K
virtual double operator()()
Definition: integration.cpp:70
double midpnt(int n)
double Trap(int n)
Definition: integration.cpp:89
Incorrect value received.
Definition: xmipp_error.h:195
int * n
doublereal * a