@@ -93,8 +93,8 @@ void test_sde_infrastructure() {
9393 double expected_std = std::sqrt (0.01 );
9494 assert (std::abs (dW[0 ]) < 5 * expected_std); // 5-sigma test
9595
96- std::cout << " ✠?SDE problem and Wiener process creation\n " ;
97- std::cout << " ✠?Noise generation (dW[0] = " << dW[0 ] << " )\n " ;
96+ std::cout << " � ?SDE problem and Wiener process creation\n " ;
97+ std::cout << " � ?Noise generation (dW[0] = " << dW[0 ] << " )\n " ;
9898}
9999
100100void test_euler_maruyama () {
@@ -105,7 +105,7 @@ void test_euler_maruyama() {
105105 test_problems::gbm_drift, test_problems::gbm_diffusion);
106106 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 42 );
107107
108- EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
108+ diffeq:: EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
109109
110110 // Test integration
111111 std::vector<double > state = {100.0 }; // Initial stock price
@@ -120,9 +120,9 @@ void test_euler_maruyama() {
120120 // Result should be reasonable (not too far from initial value for small T)
121121 assert (state[0 ] > 50.0 && state[0 ] < 200.0 );
122122
123- std::cout << " ✠?GBM integration: S(0) = 100.0 ↠?S(" << T << " ) = "
123+ std::cout << " � ?GBM integration: S(0) = 100.0 � ?S(" << T << " ) = "
124124 << std::fixed << std::setprecision (2 ) << state[0 ] << " \n " ;
125- std::cout << " ✠?Method: " << integrator.name () << " \n " ;
125+ std::cout << " � ?Method: " << integrator.name () << " \n " ;
126126}
127127
128128void test_milstein_method () {
@@ -132,7 +132,13 @@ void test_milstein_method() {
132132 test_problems::gbm_drift, test_problems::gbm_diffusion);
133133 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 123 );
134134
135- MilsteinIntegrator<std::vector<double >, double > integrator (problem, wiener);
135+ // For GBM g(t, S) = σ * S, so g'(t, S) = σ
136+ auto diffusion_derivative = [](double t, const std::vector<double >& x, std::vector<double >& dgx) {
137+ double sigma = 0.2 ; // Same as in gbm_diffusion
138+ dgx[0 ] = sigma;
139+ };
140+
141+ diffeq::MilsteinIntegrator<std::vector<double >> integrator (problem, diffusion_derivative, wiener);
136142
137143 std::vector<double > state = {100.0 };
138144 double dt = 0.001 ;
@@ -143,9 +149,9 @@ void test_milstein_method() {
143149 assert (state[0 ] > 0 );
144150 assert (state[0 ] > 50.0 && state[0 ] < 200.0 );
145151
146- std::cout << " ✠?GBM integration: S(0) = 100.0 ↠?S(" << T << " ) = "
152+ std::cout << " � ?GBM integration: S(0) = 100.0 � ?S(" << T << " ) = "
147153 << std::fixed << std::setprecision (2 ) << state[0 ] << " \n " ;
148- std::cout << " ✠?Method: " << integrator.name () << " \n " ;
154+ std::cout << " � ?Method: " << integrator.name () << " \n " ;
149155}
150156
151157void test_sri1_method () {
@@ -155,7 +161,7 @@ void test_sri1_method() {
155161 test_problems::ou_drift, test_problems::ou_diffusion);
156162 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 456 );
157163
158- SRI1Integrator<std::vector<double >, double > integrator (problem, wiener);
164+ diffeq:: SRI1Integrator<std::vector<double >> integrator (problem, wiener);
159165
160166 std::vector<double > state = {1.0 }; // Initial value
161167 double dt = 0.001 ;
@@ -166,9 +172,9 @@ void test_sri1_method() {
166172 // OU process should be bounded and tend toward mean
167173 assert (std::abs (state[0 ]) < 5.0 ); // Reasonable bounds
168174
169- std::cout << " ✠?OU process integration: X(0) = 1.0 ↠?X(" << T << " ) = "
175+ std::cout << " � ?OU process integration: X(0) = 1.0 � ?X(" << T << " ) = "
170176 << std::fixed << std::setprecision (3 ) << state[0 ] << " \n " ;
171- std::cout << " ✠?Method: " << integrator.name () << " \n " ;
177+ std::cout << " � ?Method: " << integrator.name () << " \n " ;
172178}
173179
174180void test_implicit_euler_maruyama () {
@@ -178,7 +184,7 @@ void test_implicit_euler_maruyama() {
178184 test_problems::ou_drift, test_problems::ou_diffusion);
179185 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 789 );
180186
181- ImplicitEulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
187+ diffeq:: ImplicitEulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
182188
183189 std::vector<double > state = {2.0 };
184190 double dt = 0.01 ; // Larger time step to test stability
@@ -188,9 +194,9 @@ void test_implicit_euler_maruyama() {
188194
189195 assert (std::abs (state[0 ]) < 5.0 );
190196
191- std::cout << " ✠?OU process integration: X(0) = 2.0 ↠?X(" << T << " ) = "
197+ std::cout << " � ?OU process integration: X(0) = 2.0 � ?X(" << T << " ) = "
192198 << std::fixed << std::setprecision (3 ) << state[0 ] << " \n " ;
193- std::cout << " ✠?Method: " << integrator.name () << " \n " ;
199+ std::cout << " � ?Method: " << integrator.name () << " \n " ;
194200}
195201
196202void test_multidimensional_sde () {
@@ -200,7 +206,7 @@ void test_multidimensional_sde() {
200206 test_problems::multi_drift, test_problems::multi_diffusion);
201207 auto wiener = factory::make_wiener_process<std::vector<double >>(2 , 999 );
202208
203- EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
209+ diffeq:: EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
204210
205211 std::vector<double > state = {1.0 , 1.0 }; // Initial values
206212 double dt = 0.001 ;
@@ -212,7 +218,7 @@ void test_multidimensional_sde() {
212218 assert (state[0 ] > 0 && state[0 ] < 10.0 );
213219 assert (state[1 ] > 0 && state[1 ] < 10.0 );
214220
215- std::cout << " ✠?2D system: [1.0, 1.0] ↠?["
221+ std::cout << " � ?2D system: [1.0, 1.0] � ?["
216222 << std::fixed << std::setprecision (3 ) << state[0 ] << " , " << state[1 ] << " ]\n " ;
217223}
218224
@@ -225,12 +231,12 @@ void test_noise_types() {
225231 test_problems::multi_drift, test_problems::multi_diffusion, NoiseType::SCALAR_NOISE);
226232 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 111 );
227233
228- EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
234+ diffeq:: EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
229235
230236 std::vector<double > state = {1.0 , 1.0 };
231237 integrator.integrate (state, 0.001 , 0.05 );
232238
233- std::cout << " ✠?Scalar noise: [1.0, 1.0] ↠?["
239+ std::cout << " � ?Scalar noise: [1.0, 1.0] � ?["
234240 << std::fixed << std::setprecision (3 ) << state[0 ] << " , " << state[1 ] << " ]\n " ;
235241 }
236242
@@ -240,12 +246,18 @@ void test_noise_types() {
240246 test_problems::multi_drift, test_problems::multi_diffusion, NoiseType::DIAGONAL_NOISE);
241247 auto wiener = factory::make_wiener_process<std::vector<double >>(2 , 222 );
242248
243- MilsteinIntegrator<std::vector<double >, double > integrator (problem, wiener);
249+ // For multi_diffusion g(t, x) = [0.2*x[0], 0.15*x[1]], so g'(t, x) = [0.2, 0.15]
250+ auto diffusion_derivative = [](double t, const std::vector<double >& x, std::vector<double >& dgx) {
251+ dgx[0 ] = 0.2 ; // Derivative of 0.2*x[0] w.r.t. x[0]
252+ dgx[1 ] = 0.15 ; // Derivative of 0.15*x[1] w.r.t. x[1]
253+ };
254+
255+ diffeq::MilsteinIntegrator<std::vector<double >> integrator (problem, diffusion_derivative, wiener);
244256
245257 std::vector<double > state = {1.0 , 1.0 };
246258 integrator.integrate (state, 0.001 , 0.05 );
247259
248- std::cout << " ✠?Diagonal noise: [1.0, 1.0] ↠?["
260+ std::cout << " � ?Diagonal noise: [1.0, 1.0] � ?["
249261 << std::fixed << std::setprecision (3 ) << state[0 ] << " , " << state[1 ] << " ]\n " ;
250262 }
251263}
@@ -267,8 +279,15 @@ void test_convergence_properties() {
267279 auto wiener_em = factory::make_wiener_process<std::vector<double >>(1 , 42 );
268280 auto wiener_mil = factory::make_wiener_process<std::vector<double >>(1 , 42 );
269281
270- EulerMaruyamaIntegrator<std::vector<double >> em_integrator (problem, wiener_em);
271- MilsteinIntegrator<std::vector<double >, double > mil_integrator (problem, wiener_mil);
282+ diffeq::EulerMaruyamaIntegrator<std::vector<double >> em_integrator (problem, wiener_em);
283+
284+ // For GBM g(t, S) = σ * S, so g'(t, S) = σ
285+ auto diffusion_derivative = [](double t, const std::vector<double >& x, std::vector<double >& dgx) {
286+ double sigma = 0.2 ; // Same as in gbm_diffusion
287+ dgx[0 ] = sigma;
288+ };
289+
290+ diffeq::MilsteinIntegrator<std::vector<double >> mil_integrator (problem, diffusion_derivative, wiener_mil);
272291
273292 std::vector<double > state_em = {100.0 };
274293 std::vector<double > state_mil = {100.0 };
@@ -282,8 +301,8 @@ void test_convergence_properties() {
282301 errors_milstein.push_back (std::abs (state_mil[0 ] - 100.0 ));
283302 }
284303
285- std::cout << " ✠?Convergence test completed for dt values: 0.01, 0.005, 0.0025\n " ;
286- std::cout << " ✠?Both methods show expected convergence behavior\n " ;
304+ std::cout << " � ?Convergence test completed for dt values: 0.01, 0.005, 0.0025\n " ;
305+ std::cout << " � ?Both methods show expected convergence behavior\n " ;
287306}
288307
289308void test_step_by_step_integration () {
@@ -293,7 +312,7 @@ void test_step_by_step_integration() {
293312 test_problems::gbm_drift, test_problems::gbm_diffusion);
294313 auto wiener = factory::make_wiener_process<std::vector<double >>(1 , 314 );
295314
296- EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
315+ diffeq:: EulerMaruyamaIntegrator<std::vector<double >> integrator (problem, wiener);
297316
298317 std::vector<double > state = {100.0 };
299318 double dt = 0.01 ;
@@ -308,7 +327,7 @@ void test_step_by_step_integration() {
308327 }
309328
310329 assert (state[0 ] > 0 );
311- std::cout << " ✠?Step-by-step integration maintains positivity\n " ;
330+ std::cout << " � ?Step-by-step integration maintains positivity\n " ;
312331}
313332
314333int main () {
0 commit comments