@@ -41,27 +41,7 @@ struct Polynomial(F)
41
41
+/
42
42
@optmath typeof (F.init * X.init * 1f + F.init) opCall (X)(in X x) const
43
43
{
44
- import mir.internal.utility: Iota;
45
- auto ret = cast (typeof (return ))0 ;
46
- if (coefficients)
47
- {
48
- ptrdiff_t i = coefficients.length - 1 ;
49
- assert (i >= 0 );
50
- auto c = cast ()coefficients[i];
51
- static foreach (d; Iota! derivative)
52
- c *= i - d;
53
- ret = cast (typeof (return )) c;
54
- while (-- i >= cast (ptrdiff_t )derivative)
55
- {
56
- assert (i < coefficients.length);
57
- c = cast ()coefficients[i];
58
- static foreach (d; Iota! derivative)
59
- c *= i - d;
60
- ret *= x;
61
- ret += c;
62
- }
63
- }
64
- return ret;
44
+ return x.poly! derivative(this .coefficients[]);
65
45
}
66
46
}
67
47
}
@@ -81,9 +61,9 @@ version (mir_test) @safe pure nothrow @nogc unittest
81
61
auto a = rcarray! (const double )(3.0 , 4.5 , 1.9 , 2 );
82
62
auto p = a.polynomial;
83
63
84
- alias f = (x) => 3.0 + 4.5 * x^^ 1 + 1.9 * x^^ 2 + 2 * x^^ 3 ;
85
- alias df = (x) => 4.5 + 2 * 1.9 * x^^ 1 + 3 * 2 * x^^ 2 ;
86
- alias d2f = (x) => 2 * 1.9 + 6 * 2 * x^^ 1 ;
64
+ alias f = (x) => 3.0 + 4.5 * x^^ 1 + 1.9 * x^^ 2 + 2 * x^^ 3 ;
65
+ alias df = (x) => 4.5 + 2 * 1.9 * x^^ 1 + 3 * 2 * x^^ 2 ;
66
+ alias d2f = (x) => 2 * 1.9 + 6 * 2 * x^^ 1 ;
87
67
88
68
assert (p(3.3 ).approxEqual(f(3.3 )));
89
69
assert (p(7.2 ).approxEqual(f(7.2 )));
@@ -94,3 +74,153 @@ version (mir_test) @safe pure nothrow @nogc unittest
94
74
assert (p.opCall ! 2 (3.3 ).approxEqual(d2f(3.3 )));
95
75
assert (p.opCall ! 2 (7.2 ).approxEqual(d2f(7.2 )));
96
76
}
77
+
78
+ /+ +
79
+ Evaluate polynomial.
80
+
81
+ Coefficients assumed to be in the order a0 + a1 * x ^^ 1 + ... + aN * x ^^ N
82
+
83
+ Params:
84
+ F = controls type of output
85
+ derivative = order of derivatives (default = 0)
86
+
87
+ Returns:
88
+ Value of the polynomial, evaluated at `x`
89
+
90
+ See_also:
91
+ $(WEB en.wikipedia.org/wiki/Polynomial, Polynomial).
92
+ +/
93
+ template poly (uint derivative = 0 )
94
+ {
95
+ import std.traits : ForeachType;
96
+ /+ +
97
+ Params:
98
+ x = value to evaluate
99
+ coefficients = coefficients of polynomial
100
+ +/
101
+ @optmath typeof (F.init * X.init * 1f + F.init) poly(X, F)(in X x, scope const F[] coefficients... )
102
+ {
103
+ import mir.internal.utility: Iota;
104
+ auto ret = cast (typeof (return ))0 ;
105
+ if (coefficients.length > 0 )
106
+ {
107
+ ptrdiff_t i = coefficients.length - 1 ;
108
+ assert (i >= 0 );
109
+ auto c = cast ()coefficients[i];
110
+ static foreach (d; Iota! derivative)
111
+ c *= i - d;
112
+ ret = cast (typeof (return )) c;
113
+ while (-- i >= cast (ptrdiff_t )derivative)
114
+ {
115
+ assert (i < coefficients.length);
116
+ c = cast ()coefficients[i];
117
+ static foreach (d; Iota! derivative)
118
+ c *= i - d;
119
+ ret *= x;
120
+ ret += c;
121
+ }
122
+ }
123
+ return ret;
124
+ }
125
+ }
126
+
127
+ // /
128
+ version (mir_test) @safe pure nothrow unittest
129
+ {
130
+ import mir.math.common: approxEqual;
131
+
132
+ double [] x = [3.0 , 4.5 , 1.9 , 2 ];
133
+
134
+ alias f = (x) => 3.0 + 4.5 * x^^ 1 + 1.9 * x^^ 2 + 2 * x^^ 3 ;
135
+ alias df = (x) => 4.5 + 2 * 1.9 * x^^ 1 + 3 * 2 * x^^ 2 ;
136
+ alias d2f = (x) => 2 * 1.9 + 6 * 2 * x^^ 1 ;
137
+
138
+ assert (poly(3.3 , x).approxEqual(f(3.3 )));
139
+ assert (poly(7.2 , x).approxEqual(f(7.2 )));
140
+
141
+ assert (poly! 1 (3.3 , x).approxEqual(df(3.3 )));
142
+ assert (poly! 1 (7.2 , x).approxEqual(df(7.2 )));
143
+
144
+ assert (poly! 2 (3.3 , x).approxEqual(d2f(3.3 )));
145
+ assert (poly! 2 (7.2 , x).approxEqual(d2f(7.2 )));
146
+ }
147
+
148
+ // static array test
149
+ version (mir_test) @safe pure @nogc nothrow unittest
150
+ {
151
+ import mir.math.common: approxEqual;
152
+
153
+ double [4 ] x = [3.0 , 4.5 , 1.9 , 2 ];
154
+
155
+ alias f = (x) => 3.0 + 4.5 * x^^ 1 + 1.9 * x^^ 2 + 2 * x^^ 3 ;
156
+ alias df = (x) => 4.5 + 2 * 1.9 * x^^ 1 + 3 * 2 * x^^ 2 ;
157
+ alias d2f = (x) => 2 * 1.9 + 6 * 2 * x^^ 1 ;
158
+
159
+ assert (poly(3.3 , x).approxEqual(f(3.3 )));
160
+ assert (poly(7.2 , x).approxEqual(f(7.2 )));
161
+
162
+ assert (poly! 1 (3.3 , x).approxEqual(df(3.3 )));
163
+ assert (poly! 1 (7.2 , x).approxEqual(df(7.2 )));
164
+
165
+ assert (poly! 2 (3.3 , x).approxEqual(d2f(3.3 )));
166
+ assert (poly! 2 (7.2 , x).approxEqual(d2f(7.2 )));
167
+ }
168
+
169
+ // Check coefficient.length = 3
170
+ version (mir_test) @safe pure nothrow unittest
171
+ {
172
+ import mir.math.common: approxEqual;
173
+
174
+ double [] x = [3.0 , 4.5 , 1.9 ];
175
+
176
+ alias f = (x) => 3.0 + 4.5 * x^^ 1 + 1.9 * x^^ 2 ;
177
+ alias df = (x) => 4.5 + 2 * 1.9 * x^^ 1 ;
178
+ alias d2f = (x) => 2 * 1.9 ;
179
+
180
+ assert (poly(3.3 , x).approxEqual(f(3.3 )));
181
+ assert (poly(7.2 , x).approxEqual(f(7.2 )));
182
+
183
+ assert (poly! 1 (3.3 , x).approxEqual(df(3.3 )));
184
+ assert (poly! 1 (7.2 , x).approxEqual(df(7.2 )));
185
+
186
+ assert (poly! 2 (3.3 , x).approxEqual(d2f(3.3 )));
187
+ assert (poly! 2 (7.2 , x).approxEqual(d2f(7.2 )));
188
+ }
189
+
190
+ // Check coefficient.length = 2
191
+ version (mir_test) @safe pure nothrow unittest
192
+ {
193
+ import mir.math.common: approxEqual;
194
+
195
+ double [] x = [3.0 , 4.5 ];
196
+
197
+ alias f = (x) => 3.0 + 4.5 * x^^ 1 ;
198
+ alias df = (x) => 4.5 ;
199
+ alias d2f = (x) => 0.0 ;
200
+
201
+ assert (poly(3.3 , x).approxEqual(f(3.3 )));
202
+ assert (poly(7.2 , x).approxEqual(f(7.2 )));
203
+
204
+ assert (poly! 1 (3.3 , x).approxEqual(df(3.3 )));
205
+ assert (poly! 1 (7.2 , x).approxEqual(df(7.2 )));
206
+
207
+ assert (poly! 2 (3.3 , x).approxEqual(d2f(3.3 )));
208
+ assert (poly! 2 (7.2 , x).approxEqual(d2f(7.2 )));
209
+ }
210
+
211
+ // Check coefficient.length = 1
212
+ version (mir_test) @safe pure nothrow unittest
213
+ {
214
+ import mir.math.common: approxEqual;
215
+
216
+ double [] x = [3.0 ];
217
+
218
+ alias f = (x) => 3.0 ;
219
+ alias df = (x) => 0.0 ;
220
+
221
+ assert (poly(3.3 , x).approxEqual(f(3.3 )));
222
+ assert (poly(7.2 , x).approxEqual(f(7.2 )));
223
+
224
+ assert (poly! 1 (3.3 , x).approxEqual(df(3.3 )));
225
+ assert (poly! 1 (7.2 , x).approxEqual(df(7.2 )));
226
+ }
0 commit comments