File indexing completed on 2024-05-12 03:47:53
0001 /* 0002 File : nsl_sf_poly.c 0003 Project : LabPlot 0004 Description : NSL special polynomial functions 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2016 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "nsl_sf_poly.h" 0011 #include <gsl/gsl_math.h> 0012 #include <gsl/gsl_sf_pow_int.h> 0013 #include <math.h> 0014 #include <stdio.h> // debugging 0015 0016 /* see https://en.wikipedia.org/wiki/Chebyshev_polynomials */ 0017 double nsl_sf_poly_chebyshev_T(int n, double x) { 0018 if (fabs(x) <= 1) 0019 return cos(n * acos(x)); 0020 else if (x > 1) 0021 return cosh(n * gsl_acosh(x)); 0022 else 0023 return pow(-1., n) * cosh(n * gsl_acosh(-x)); 0024 } 0025 0026 double nsl_sf_poly_chebyshev_U(int n, double x) { 0027 double sq = sqrt(x * x - 1); 0028 return (pow(x + sq, n + 1) - pow(x - sq, n + 1)) / 2. / sq; 0029 } 0030 0031 /* from http://www.crbond.com/papers/lopt.pdf */ 0032 double nsl_sf_poly_optimal_legendre_L(int n, double x) { 0033 if (n < 1 || n > 10) 0034 return 0.0; 0035 0036 switch (n) { 0037 case 1: 0038 return x; 0039 case 2: 0040 return x * x; 0041 case 3: 0042 return (1. + (-3. + 3. * x) * x) * x; 0043 case 4: 0044 return (3. + (-8. + 6 * x) * x) * x * x; 0045 case 5: 0046 return (1. + (-8. + (28. + (-40. + 20 * x) * x) * x) * x) * x; 0047 case 6: 0048 return (6. + (-40. + (105. + (-120. + 50. * x) * x) * x) * x) * x * x; 0049 case 7: 0050 return (1. + (-15. + (105. + (-355. + (615. + (-525. + 175. * x) * x) * x) * x) * x) * x) * x; 0051 case 8: 0052 return (10. + (-120. + (615. + (-1624. + (2310. + (-1680. + 490. * x) * x) * x) * x) * x) * x) * x * x; 0053 case 9: 0054 return (1. + (-24. + (276. + (-1624. + (5376. + (-10416. + (11704. + (-7056. + 1764 * x) * x) * x) * x) * x) * x) * x) * x) * x; 0055 case 10: 0056 return (15. + (-280. + (2310. + (-10416. + (27860. + (-45360. + (44100. + (23520. + 5292. * x) * x) * x) * x) * x) * x) * x) * x) * x * x; 0057 } 0058 0059 return 0.0; 0060 } 0061 0062 /* 0063 * https://en.wikipedia.org/wiki/Bessel_polynomials 0064 * using recursion 0065 */ 0066 gsl_complex nsl_sf_poly_bessel_y(int n, gsl_complex x) { 0067 if (n == 0) 0068 return gsl_complex_rect(1.0, 0.0); 0069 if (n == 1) 0070 return gsl_complex_add_real(x, 1.0); 0071 0072 gsl_complex z1 = gsl_complex_mul(x, gsl_complex_mul_real(nsl_sf_poly_bessel_y(n - 1, x), 2. * n - 1.)); 0073 gsl_complex z2 = nsl_sf_poly_bessel_y(n - 2, x); 0074 return gsl_complex_add(z1, z2); 0075 } 0076 0077 gsl_complex nsl_sf_poly_reversed_bessel_theta(int n, gsl_complex x) { 0078 if (n == 0) 0079 return gsl_complex_rect(1.0, 0.0); 0080 if (n == 1) 0081 return gsl_complex_add_real(x, 1.0); 0082 0083 gsl_complex z1 = gsl_complex_mul_real(nsl_sf_poly_reversed_bessel_theta(n - 1, x), 2. * n - 1.); 0084 gsl_complex z2 = gsl_complex_mul(gsl_complex_mul(x, x), nsl_sf_poly_reversed_bessel_theta(n - 2, x)); 0085 return gsl_complex_add(z1, z2); 0086 } 0087 0088 /***************** interpolating polynomials *************/ 0089 0090 double nsl_sf_poly_interp_lagrange_0_int(const double* x, double y) { 0091 /* rectangle rule */ 0092 return (x[1] - x[0]) * y; 0093 } 0094 0095 double nsl_sf_poly_interp_lagrange_1(double v, const double* x, const double* y) { 0096 return (y[0] * (x[1] - v) + y[1] * (v - x[0])) / (x[1] - x[0]); 0097 } 0098 double nsl_sf_poly_interp_lagrange_1_deriv(const double* x, const double* y) { 0099 return (y[0] - y[1]) / (x[1] - x[0]); 0100 } 0101 double nsl_sf_poly_interp_lagrange_1_int(const double* x, const double* y) { 0102 /* trapezoid rule (2-point) */ 0103 return (x[1] - x[0]) * (y[0] + y[1]) / 2.; 0104 } 0105 double nsl_sf_poly_interp_lagrange_1_absint(const double* x, const double* y) { 0106 double dx = x[1] - x[0]; 0107 if (y[0] * y[1] < 0) /* sign change */ 0108 return dx * ((fabs(y[0]) - fabs(y[1])) / (fabs(y[1] / y[0]) + 1) + fabs(y[1])) / 2.; 0109 if (y[0] < 0 && y[1] < 0) 0110 return dx * (fabs(y[0]) + fabs(y[1])) / 2.; 0111 else 0112 return dx * (y[0] + y[1]) / 2.; 0113 } 0114 0115 double nsl_sf_poly_interp_lagrange_2(double v, const double* x, const double* y) { 0116 double h1 = x[1] - x[0], h2 = x[2] - x[1]; 0117 double h12 = h1 + h2; 0118 0119 return y[0] * (v - x[1]) * (v - x[2]) / (h1 * h12) + y[1] * (x[0] - v) * (v - x[2]) / (h1 * h2) + y[2] * (x[0] - v) * (x[1] - v) / (h12 * h2); 0120 } 0121 double nsl_sf_poly_interp_lagrange_2_deriv(double v, const double* x, const double* y) { 0122 double h1 = x[1] - x[0], h2 = x[2] - x[1]; 0123 double h12 = h1 + h2; 0124 0125 return y[0] * (2. * v - x[1] - x[2]) / (h1 * h12) + y[1] * (x[0] - 2. * v + x[2]) / (h1 * h2) + y[2] * (2. * v - x[0] - x[1]) / (h12 * h2); 0126 } 0127 double nsl_sf_poly_interp_lagrange_2_deriv2(const double* x, const double* y) { 0128 double h1 = x[1] - x[0], h2 = x[2] - x[1]; 0129 double h12 = h1 + h2; 0130 0131 return 2. * (y[0] / (h1 * h12) - y[1] / (h1 * h2) + y[2] / (h12 * h2)); 0132 } 0133 double nsl_sf_poly_interp_lagrange_2_int(const double* x, const double* y) { 0134 /* Simpson's 1/3 rule for non-uniform grid (3-point) */ 0135 double h1 = x[1] - x[0], h2 = x[2] - x[1]; 0136 double h12 = h1 + h2, h1_2 = h1 / h2; 0137 0138 return h12 / 6. * ((2. - 1. / h1_2) * y[0] + (2. + h1_2 + 1. / h1_2) * y[1] + (2. - h1_2) * y[2]); 0139 } 0140 0141 double nsl_sf_poly_interp_lagrange_3(double v, const double* x, const double* y) { 0142 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2]; 0143 double h12 = h1 + h2, h23 = h2 + h3, h13 = h12 + h3; 0144 0145 return y[0] * (v - x[1]) * (v - x[2]) * (v - x[3]) / (h1 * h12 * h13) + y[1] * (v - x[0]) * (v - x[2]) * (v - x[3]) / (h1 * h2 * h23) 0146 - y[2] * (v - x[0]) * (v - x[1]) * (v - x[3]) / (h12 * h2 * h3) + y[3] * (v - x[0]) * (v - x[1]) * (v - x[2]) / (h13 * h23 * h3); 0147 } 0148 double nsl_sf_poly_interp_lagrange_3_deriv(double v, const double* x, const double* y) { 0149 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], S = x[0] + x[1] + x[2] + x[3]; 0150 double h12 = h1 + h2, h23 = h2 + h3, h13 = h12 + h3; 0151 0152 return -y[0] * (3 * v * v - 2. * v * (S - x[0]) + x[1] * x[2] + (S - x[0] - x[3]) * x[3]) / (h1 * h12 * h13) 0153 + y[1] * (3 * v * v - 2. * v * (S - x[1]) + (x[0] + x[2]) * x[3]) / (h1 * h2 * h23) 0154 + y[2] * (3 * v * v + x[0] * x[1] - 2. * v * (S - x[2]) + (x[0] + x[1]) * x[3]) / (h12 * h2 * h3) 0155 + y[3] * (3 * v * v + x[0] * x[1] + (x[0] + x[1]) * x[2] - 2. * v * (S - x[3])) / (h13 * h23 * h3); 0156 } 0157 double nsl_sf_poly_interp_lagrange_3_deriv2(double v, const double* x, const double* y) { 0158 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], S = x[0] + x[1] + x[2] + x[3]; 0159 double h12 = h1 + h2, h23 = h2 + h3, h13 = h12 + h3; 0160 0161 return 2. 0162 * (y[0] * (S - 3. * v - x[0]) / (h1 * h12 * h13) + y[1] * (3. * v - S + x[1]) / (h1 * h2 * h23) + y[2] * (S - 3. * v - x[2]) / (h12 * h2 * h3) 0163 + y[3] * (3. * v - S + x[3]) / (h13 * h23 * h3)); 0164 } 0165 double nsl_sf_poly_interp_lagrange_3_deriv3(const double* x, const double* y) { 0166 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2]; 0167 double h12 = h1 + h2, h23 = h2 + h3, h13 = h12 + h3; 0168 0169 return 6. * (-y[0] / (h1 * h12 * h13) + y[1] / (h1 * h2 * h23) - y[2] / (h12 * h2 * h3) + y[3] / (h13 * h23 * h3)); 0170 } 0171 double nsl_sf_poly_interp_lagrange_3_int(const double* x, const double* y) { 0172 /* Simpson's 3/8 rule for non-uniform grid (4-point) */ 0173 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2]; 0174 double h12 = h1 + h2, h23 = h2 + h3, h13 = h12 + h3; 0175 0176 return h13 / 12. 0177 * ((3. * x[0] * x[0] - 4. * x[0] * (x[1] + x[2]) + 6. * x[1] * x[2] + 2. * x[0] * x[3] - 2. * (x[1] + x[2]) * x[3] + x[3] * x[3]) / (h1 * h12) * y[0] 0178 + h13 * h13 * (h12 - h3) / (h1 * h2 * h23) * y[1] + h13 * h13 * (h23 - h1) / (h12 * h2 * h3) * y[2] 0179 + (x[0] * x[0] - 2. * x[0] * (x[1] + x[2]) + 6. * x[1] * x[2] + 2. * x[0] * x[3] - 4. * (x[1] + x[2]) * x[3] + 3. * x[3] * x[3]) / (h23 * h3) 0180 * y[3]); 0181 } 0182 0183 /* 1/2 sum_{i != j}^n (x_i x_j) for n=4 */ 0184 double sum_of_2product_combinations_4_2(double a, double b, double c, double d) { 0185 return a * (b + c + d) + b * (c + d) + c * d; 0186 } 0187 /* 1/6 sum_{i != j, j != k, i != k}^n (x_i x_j x_k) for n=4 */ 0188 double sum_of_3product_combinations_4_6(double a, double b, double c, double d) { 0189 return a * (b * (c + d) + c * d) + b * c * d; 0190 } 0191 0192 double nsl_sf_poly_interp_lagrange_4(double v, const double* x, const double* y) { 0193 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3]; 0194 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h13 = h12 + h3, h24 = h23 + h4, h14 = h12 + h34; 0195 0196 return y[0] * (v - x[1]) * (v - x[2]) * (v - x[3]) * (v - x[4]) / (h1 * h12 * h13 * h14) 0197 - y[1] * (v - x[0]) * (v - x[2]) * (v - x[3]) * (v - x[4]) / (h1 * h2 * h23 * h24) 0198 + y[2] * (v - x[0]) * (v - x[1]) * (v - x[3]) * (v - x[4]) / (h12 * h2 * h3 * h34) 0199 - y[3] * (v - x[0]) * (v - x[1]) * (v - x[2]) * (v - x[4]) / (h13 * h23 * h3 * h4) 0200 + y[4] * (v - x[0]) * (v - x[1]) * (v - x[2]) * (v - x[3]) / (h14 * h24 * h34 * h4); 0201 } 0202 double nsl_sf_poly_interp_lagrange_4_deriv(double v, const double* x, const double* y) { 0203 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], S = x[0] + x[1] + x[2] + x[3] + x[4]; 0204 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h13 = h12 + h3, h24 = h23 + h4, h14 = h12 + h34; 0205 0206 return y[0] 0207 * (4. * v * v * v - 3. * v * v * (S - x[0]) - sum_of_3product_combinations_4_6(x[1], x[2], x[3], x[4]) 0208 + 2. * v * sum_of_2product_combinations_4_2(x[1], x[2], x[3], x[4])) 0209 / (h1 * h12 * h13 * h14) 0210 - y[1] 0211 * (4. * v * v * v - 3. * v * v * (S - x[1]) - sum_of_3product_combinations_4_6(x[0], x[2], x[3], x[4]) 0212 + 2. * v * sum_of_2product_combinations_4_2(x[0], x[2], x[3], x[4])) 0213 / (h1 * h2 * h23 * h24) 0214 + y[2] 0215 * (4. * v * v * v - 3. * v * v * (S - x[2]) - sum_of_3product_combinations_4_6(x[0], x[1], x[3], x[4]) 0216 + 2. * v * sum_of_2product_combinations_4_2(x[0], x[1], x[3], x[4])) 0217 / (h12 * h2 * h3 * h34) 0218 - y[3] 0219 * (4. * v * v * v - 3. * v * v * (S - x[3]) - sum_of_3product_combinations_4_6(x[0], x[1], x[2], x[4]) 0220 + 2. * v * sum_of_2product_combinations_4_2(x[0], x[1], x[2], x[4])) 0221 / (h13 * h23 * h3 * h4) 0222 + y[4] 0223 * (4. * v * v * v - 3. * v * v * (S - x[4]) - sum_of_3product_combinations_4_6(x[0], x[1], x[2], x[3]) 0224 + 2. * v * sum_of_2product_combinations_4_2(x[0], x[1], x[2], x[3])) 0225 / (h14 * h24 * h34 * h4); 0226 } 0227 double nsl_sf_poly_interp_lagrange_4_deriv2(double v, const double* x, const double* y) { 0228 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], S = x[0] + x[1] + x[2] + x[3] + x[4]; 0229 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h13 = h12 + h3, h24 = h23 + h4, h14 = h12 + h34; 0230 0231 return 2. 0232 * (y[0] * (6. * v * v - 3. * v * (S - x[0]) + sum_of_2product_combinations_4_2(x[1], x[2], x[3], x[4])) / (h1 * h12 * h13 * h14) 0233 - y[1] * (6. * v * v - 3. * v * (S - x[1]) + sum_of_2product_combinations_4_2(x[0], x[2], x[3], x[4])) / (h1 * h2 * h23 * h24) 0234 + y[2] * (6. * v * v - 3. * v * (S - x[2]) + sum_of_2product_combinations_4_2(x[0], x[1], x[3], x[4])) / (h12 * h2 * h3 * h34) 0235 - y[3] * (6. * v * v - 3. * v * (S - x[3]) + sum_of_2product_combinations_4_2(x[0], x[1], x[2], x[4])) / (h13 * h23 * h3 * h4) 0236 + y[4] * (6. * v * v - 3. * v * (S - x[4]) + sum_of_2product_combinations_4_2(x[0], x[1], x[2], x[3])) / (h14 * h24 * h34 * h4)); 0237 } 0238 double nsl_sf_poly_interp_lagrange_4_deriv3(double v, const double* x, const double* y) { 0239 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], S = x[0] + x[1] + x[2] + x[3] + x[4]; 0240 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h13 = h12 + h3, h24 = h23 + h4, h14 = h12 + h34; 0241 0242 return 6. 0243 * (y[0] * (4. * v - S + x[0]) / (h1 * h12 * h13 * h14) + y[1] * (S - 4. * v - x[1]) / (h1 * h2 * h23 * h24) 0244 + y[2] * (4. * v - S + x[2]) / (h12 * h2 * h3 * h34) + y[3] * (S - 4. * v - x[3]) / (h13 * h23 * h3 * h4) 0245 + y[4] * (4. * v - S + x[4]) / (h14 * h24 * h34 * h4)); 0246 } 0247 double nsl_sf_poly_interp_lagrange_4_deriv4(const double* x, const double* y) { 0248 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3]; 0249 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h13 = h12 + h3, h24 = h23 + h4, h14 = h12 + h34; 0250 0251 return 24. 0252 * (y[0] / (h1 * h12 * h13 * h14) - y[1] / (h1 * h2 * h23 * h24) + y[2] / (h12 * h2 * h3 * h34) - y[3] / (h13 * h23 * h3 * h4) 0253 + y[4] / (h14 * h24 * h34 * h4)); 0254 } 0255 0256 /* 1/2 sum_{i != j}^n (x_i x_j) for n=6 */ 0257 double sum_of_product_combinations_6_2(double a, double b, double c, double d, double e, double f) { 0258 return a * (b + c + d + e + f) + b * (c + d + e + f) + c * (d + e + f) + d * (e + f) + e * f; 0259 } 0260 0261 double nsl_sf_poly_interp_lagrange_6_deriv4(double v, const double* x, const double* y) { 0262 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], h5 = x[5] - x[4], h6 = x[6] - x[5]; 0263 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h45 = h4 + h5, h56 = h5 + h6; 0264 double h13 = h12 + h3, h24 = h23 + h4, h35 = h34 + h5, h46 = h45 + h6, h14 = h13 + h4, h25 = h24 + h5, h36 = h35 + h6; 0265 double h15 = h14 + h5, h26 = h25 + h6, h16 = h15 + h6, S = x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6]; 0266 0267 return 24. 0268 * (y[0] * (15. * v * v - 5. * v * (S - x[0]) + sum_of_product_combinations_6_2(x[1], x[2], x[3], x[4], x[5], x[6])) / (h1 * h12 * h13 * h14 * h15 * h16) 0269 - y[1] * (15. * v * v - 5. * v * (S - x[1]) + sum_of_product_combinations_6_2(x[0], x[2], x[3], x[4], x[5], x[6])) 0270 / (h1 * h2 * h23 * h24 * h25 * h26) 0271 + y[2] * (15. * v * v - 5. * v * (S - x[2]) + sum_of_product_combinations_6_2(x[0], x[1], x[3], x[4], x[5], x[6])) 0272 / (h12 * h2 * h3 * h34 * h35 * h36) 0273 - y[3] * (15. * v * v - 5. * v * (S - x[3]) + sum_of_product_combinations_6_2(x[0], x[1], x[2], x[4], x[5], x[6])) 0274 / (h13 * h23 * h3 * h4 * h45 * h46) 0275 + y[4] * (15. * v * v - 5. * v * (S - x[4]) + sum_of_product_combinations_6_2(x[0], x[1], x[2], x[3], x[5], x[6])) 0276 / (h14 * h24 * h34 * h4 * h5 * h56) 0277 - y[5] * (15. * v * v - 5. * v * (S - x[5]) + sum_of_product_combinations_6_2(x[0], x[1], x[2], x[3], x[4], x[6])) 0278 / (h15 * h25 * h35 * h45 * h5 * h6) 0279 + y[6] * (15. * v * v - 5. * v * (S - x[6]) + sum_of_product_combinations_6_2(x[0], x[1], x[2], x[3], x[4], x[5])) 0280 / (h16 * h26 * h36 * h46 * h56 * h6)); 0281 } 0282 double nsl_sf_poly_interp_lagrange_6_deriv5(double v, const double* x, const double* y) { 0283 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], h5 = x[5] - x[4], h6 = x[6] - x[5]; 0284 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h45 = h4 + h5, h56 = h5 + h6; 0285 double h13 = h12 + h3, h24 = h23 + h4, h35 = h34 + h5, h46 = h45 + h6, h14 = h13 + h4, h25 = h24 + h5, h36 = h35 + h6; 0286 double h15 = h14 + h5, h26 = h25 + h6, h16 = h15 + h6, S = x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6]; 0287 0288 return 120. 0289 * (y[0] * (6. * v - S + x[0]) / (h1 * h12 * h13 * h14 * h15 * h16) - y[1] * (6. * v - S + x[1]) / (h1 * h2 * h23 * h24 * h25 * h26) 0290 + y[2] * (6. * v - S + x[2]) / (h12 * h2 * h3 * h34 * h35 * h36) - y[3] * (6. * v - S + x[3]) / (h13 * h23 * h3 * h4 * h45 * h46) 0291 + y[4] * (6. * v - S + x[4]) / (h14 * h24 * h34 * h4 * h5 * h56) - y[5] * (6. * v - S + x[5]) / (h15 * h25 * h35 * h45 * h5 * h6) 0292 + y[6] * (6. * v - S + x[6]) / (h16 * h26 * h36 * h46 * h56 * h6)); 0293 } 0294 double nsl_sf_poly_interp_lagrange_6_deriv6(const double* x, const double* y) { 0295 double h1 = x[1] - x[0], h2 = x[2] - x[1], h3 = x[3] - x[2], h4 = x[4] - x[3], h5 = x[5] - x[4], h6 = x[6] - x[5]; 0296 double h12 = h1 + h2, h23 = h2 + h3, h34 = h3 + h4, h45 = h4 + h5, h56 = h5 + h6; 0297 double h13 = h12 + h3, h24 = h23 + h4, h35 = h34 + h5, h46 = h45 + h6, h14 = h13 + h4, h25 = h24 + h5, h36 = h35 + h6; 0298 double h15 = h14 + h5, h26 = h25 + h6, h16 = h15 + h6; 0299 0300 return 720. 0301 * (y[0] / (h1 * h12 * h13 * h14 * h15 * h16) - y[1] / (h1 * h2 * h23 * h24 * h25 * h26) + y[2] / (h12 * h2 * h3 * h34 * h35 * h36) 0302 - y[3] / (h13 * h23 * h3 * h4 * h45 * h46) + y[4] / (h14 * h24 * h34 * h4 * h5 * h56) - y[5] / (h15 * h25 * h35 * h45 * h5 * h6) 0303 + y[6] / (h16 * h26 * h36 * h46 * h56 * h6)); 0304 }