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 }