1 /++ 2 Hermite Polynomial Coefficients 3 4 License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0) 5 Authors: John Hall 6 7 +/ 8 9 module mir.math.func.hermite; 10 11 /++ 12 Normalized (probabilist's) Hermite polynomial coefficients 13 14 Params: 15 N = Degree of polynomial 16 17 See_also: 18 $(LINK2 https://en.wikipedia.org/wiki/Hermite_polynomials, Hermite polynomials) 19 +/ 20 @safe pure nothrow 21 long[] hermiteCoefficientsNorm(size_t N) 22 { 23 if (N == 0) { 24 return [1]; 25 } else { 26 typeof(return) output = [0, 1]; 27 if (N > 1) { 28 output.length = N + 1; 29 int K; 30 typeof(return) h_N_minus_1 = hermiteCoefficientsNorm(0); // to be copied to h_N_minus_2 in loop 31 h_N_minus_1.length = N; 32 typeof(return) h_N_minus_2; //value replaced later 33 h_N_minus_2.length = N - 1; 34 35 foreach (size_t j; 2..(N + 1)) { 36 h_N_minus_2[0..(j - 1)] = h_N_minus_1[0..(j - 1)]; 37 h_N_minus_1[0..j] = output[0..j]; 38 K = -(cast(int) j - 1); 39 output[0] = K * h_N_minus_2[0]; 40 foreach (size_t i; 1..(j - 1)) { 41 output[i] = h_N_minus_1[i - 1] + K * h_N_minus_2[i]; 42 } 43 foreach (size_t i; (j - 1)..(j + 1)) { 44 output[i] = h_N_minus_1[i - 1]; 45 } 46 } 47 } 48 return output; 49 } 50 } 51 52 /// 53 version(mir_test) 54 @safe pure nothrow 55 unittest 56 { 57 import mir.polynomial: polynomial; 58 import mir.rc.array: rcarray; 59 import mir.test: should; 60 61 auto h0 = hermiteCoefficientsNorm(0).rcarray!(const double).polynomial; 62 auto h1 = hermiteCoefficientsNorm(1).rcarray!(const double).polynomial; 63 auto h2 = hermiteCoefficientsNorm(2).rcarray!(const double).polynomial; 64 auto h3 = hermiteCoefficientsNorm(3).rcarray!(const double).polynomial; 65 auto h4 = hermiteCoefficientsNorm(4).rcarray!(const double).polynomial; 66 auto h5 = hermiteCoefficientsNorm(5).rcarray!(const double).polynomial; 67 auto h6 = hermiteCoefficientsNorm(6).rcarray!(const double).polynomial; 68 auto h7 = hermiteCoefficientsNorm(7).rcarray!(const double).polynomial; 69 auto h8 = hermiteCoefficientsNorm(8).rcarray!(const double).polynomial; 70 auto h9 = hermiteCoefficientsNorm(9).rcarray!(const double).polynomial; 71 auto h10 = hermiteCoefficientsNorm(10).rcarray!(const double).polynomial; 72 73 h0(3).should == 1; 74 h1(3).should == 3; 75 h2(3).should == 8; 76 h3(3).should == 18; 77 h4(3).should == 30; 78 h5(3).should == 18; 79 h6(3).should == -96; 80 h7(3).should == -396; 81 h8(3).should == -516; 82 h9(3).should == 1_620; 83 h10(3).should == 9_504; 84 } 85 86 /// Also works with @nogc CTFE 87 version(mir_test) 88 @safe pure nothrow @nogc 89 unittest 90 { 91 import mir.ndslice.slice: sliced; 92 import mir.test: should; 93 94 static immutable result = [-1, 0, 1]; 95 96 static immutable hc2 = hermiteCoefficientsNorm(2); 97 hc2.sliced.should == result; 98 } 99 100 /++ 101 Physicist's Hermite polynomial coefficients 102 103 Params: 104 N = Degree of polynomial 105 106 See_also: 107 $(LINK2 https://en.wikipedia.org/wiki/Hermite_polynomials, Hermite polynomials) 108 +/ 109 @safe pure nothrow 110 long[] hermiteCoefficients(size_t N) 111 { 112 if (N == 0) { 113 return [1]; 114 } else { 115 typeof(return) output = [0, 2]; 116 if (N > 1) { 117 output.length = N + 1; 118 typeof(return) h_N_minus_1 = hermiteCoefficients(0); 119 h_N_minus_1.length = N; 120 121 foreach (size_t j; 2..(N + 1)) { 122 h_N_minus_1[0..j] = output[0..j]; 123 output[0] = -h_N_minus_1[1]; 124 foreach (size_t i; 1..(j - 1)) { 125 output[i] = 2 * h_N_minus_1[i - 1] - (cast(int) i + 1) * h_N_minus_1[i + 1]; 126 } 127 foreach (size_t i; (j - 1)..(j + 1)) { 128 output[i] = 2 * h_N_minus_1[i - 1]; 129 } 130 } 131 } 132 return output; 133 } 134 } 135 136 /// 137 version(mir_test) 138 @safe pure nothrow 139 unittest 140 { 141 import mir.polynomial: polynomial; 142 import mir.rc.array: rcarray; 143 import mir.test: should; 144 145 auto h0 = hermiteCoefficients(0).rcarray!(const double).polynomial; 146 auto h1 = hermiteCoefficients(1).rcarray!(const double).polynomial; 147 auto h2 = hermiteCoefficients(2).rcarray!(const double).polynomial; 148 auto h3 = hermiteCoefficients(3).rcarray!(const double).polynomial; 149 auto h4 = hermiteCoefficients(4).rcarray!(const double).polynomial; 150 auto h5 = hermiteCoefficients(5).rcarray!(const double).polynomial; 151 auto h6 = hermiteCoefficients(6).rcarray!(const double).polynomial; 152 auto h7 = hermiteCoefficients(7).rcarray!(const double).polynomial; 153 auto h8 = hermiteCoefficients(8).rcarray!(const double).polynomial; 154 auto h9 = hermiteCoefficients(9).rcarray!(const double).polynomial; 155 auto h10 = hermiteCoefficients(10).rcarray!(const double).polynomial; 156 157 h0(3).should == 1; 158 h1(3).should == 6; 159 h2(3).should == 34; 160 h3(3).should == 180; 161 h4(3).should == 876; 162 h5(3).should == 3_816; 163 h6(3).should == 14_136; 164 h7(3).should == 39_024; 165 h8(3).should == 36_240; 166 h9(3).should == -406_944; 167 h10(3).should == -3_093_984; 168 } 169 170 /// Also works with @nogc CTFE 171 version(mir_test) 172 @safe pure nothrow @nogc 173 unittest 174 { 175 import mir.ndslice.slice: sliced; 176 import mir.test: should; 177 178 static immutable result = [-2, 0, 4]; 179 180 static immutable hc2 = hermiteCoefficients(2); 181 hc2.sliced.should == result; 182 }