File indexing completed on 2024-05-12 15:27:08
0001 /*************************************************************************** 0002 File : nsl_int.c 0003 Project : LabPlot 0004 Description : NSL numerical integration functions 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2016 by Stefan Gerlach (stefan.gerlach@uni.kn) 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, * 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0019 * GNU General Public License for more details. * 0020 * * 0021 * You should have received a copy of the GNU General Public License * 0022 * along with this program; if not, write to the Free Software * 0023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0024 * Boston, MA 02110-1301 USA * 0025 * * 0026 ***************************************************************************/ 0027 0028 /* TODO: 0029 * absolute area for Simpson/Simpson-3/8 rules (needs more numerics) 0030 */ 0031 0032 #include "nsl_int.h" 0033 #include "nsl_common.h" 0034 #include "nsl_sf_poly.h" 0035 0036 0037 const char* nsl_int_method_name[] = {i18n("rectangle (1-point)"), i18n("trapezoid (2-point)"), i18n("Simpson's (3-point)"), i18n("Simpson's 3/8 (4-point)")}; 0038 0039 int nsl_int_rectangle(const double *x, double *y, const size_t n, int abs) { 0040 if (n == 0) 0041 return -1; 0042 0043 size_t i, j; 0044 double sum = 0, xdata[2]; 0045 for (i = 0; i < n-1; i++) { 0046 for (j=0; j < 2; j++) 0047 xdata[j] = x[i+j]; 0048 double s = nsl_sf_poly_interp_lagrange_0_int(xdata, y[i]); 0049 if (abs) 0050 s = fabs(s); 0051 y[i] = sum; 0052 sum += s; 0053 } 0054 y[n-1] = sum; 0055 0056 return 0; 0057 } 0058 0059 int nsl_int_trapezoid(const double *x, double *y, const size_t n, int abs) { 0060 if (n < 2) 0061 return -1; 0062 0063 size_t i, j; 0064 double sum = 0, xdata[2], ydata[2]; 0065 for (i = 0; i < n-1; i++) { 0066 for (j = 0; j < 2; j++) 0067 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0068 y[i] = sum; 0069 if (abs) 0070 sum += nsl_sf_poly_interp_lagrange_1_absint(xdata, ydata); 0071 else 0072 sum += nsl_sf_poly_interp_lagrange_1_int(xdata, ydata); 0073 } 0074 y[n-1] = sum; 0075 0076 return 0; 0077 } 0078 0079 size_t nsl_int_simpson(double *x, double *y, const size_t n, int abs) { 0080 if (n < 3) 0081 return 0; 0082 if (abs != 0) { 0083 printf("absolute area Simpson rule not implemented yet.\n"); 0084 return 0; 0085 } 0086 0087 size_t i, j, np=1; 0088 double sum=0, xdata[3], ydata[3]; 0089 for (i = 0; i < n-2; i+=2) { 0090 for (j=0; j < 3; j++) 0091 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0092 0093 sum += nsl_sf_poly_interp_lagrange_2_int(xdata, ydata); 0094 y[np] = sum; 0095 x[np++] = (x[i]+x[i+1]+x[i+2])/3.; 0096 /*printf("i/sum: %zu-%zu %g\n", i, i+2, sum);*/ 0097 } 0098 0099 /* handle possible last point: use trapezoid rule */ 0100 if (i == n-2) { 0101 for (j=0; j < 2; j++) 0102 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0103 sum += nsl_sf_poly_interp_lagrange_1_int(xdata, ydata); 0104 y[np] = sum; 0105 x[np++] = x[i]; 0106 } 0107 0108 /* first point */ 0109 y[0]=0; 0110 0111 return np; 0112 } 0113 0114 size_t nsl_int_simpson_3_8(double *x, double *y, const size_t n, int abs) { 0115 if (n < 4) { 0116 printf("minimum number of points is 4 (given %d).\n", (int)n); 0117 return 0; 0118 } 0119 if (abs != 0) { 0120 printf("absolute area Simpson 3/8 rule not implemented yet.\n"); 0121 return 0; 0122 } 0123 0124 size_t i, j, np=1; 0125 double sum=0, xdata[4], ydata[4]; 0126 for (i = 0; i < n-3; i+=3) { 0127 for (j=0; j < 4; j++) 0128 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0129 0130 sum += nsl_sf_poly_interp_lagrange_3_int(xdata, ydata); 0131 y[np] = sum; 0132 x[np++] = (x[i]+x[i+1]+x[i+2]+x[i+3])/4.; 0133 /*printf("i/sum: %zu-%zu %g\n", i, i+3, sum);*/ 0134 } 0135 0136 /* handle possible last point(s): use trapezoid (one point) or simpson rule (two points) */ 0137 if (i == n-2) { 0138 for (j=0; j < 2; j++) 0139 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0140 sum += nsl_sf_poly_interp_lagrange_1_int(xdata, ydata); 0141 y[np] = sum; 0142 x[np++] = x[i]; 0143 } else if ( i == n-3) { 0144 for (j=0; j < 3; j++) 0145 xdata[j] = x[i+j], ydata[j] = y[i+j]; 0146 sum += nsl_sf_poly_interp_lagrange_2_int(xdata, ydata); 0147 y[np] = sum; 0148 x[np++] = (x[i]+x[i+1]+x[i+2])/3.; 0149 } 0150 0151 /* first point */ 0152 y[0]=0; 0153 0154 return np; 0155 }