1 module des.math.method.calculus.diff; 2 3 import des.math.linear; 4 import std.traits; 5 6 import des.ts; 7 8 /// 9 auto df(size_t N, size_t M, T, E=T) 10 ( Vector!(M,T) delegate( in Vector!(N,T) ) f, in Vector!(N,T) p, E step=E.epsilon*10 ) 11 if( isFloatingPoint!T && isFloatingPoint!E ) 12 in { assert( f !is null ); } body 13 { 14 Matrix!(M,N,T) ret; 15 Vector!(N,T) p1, p2; 16 T dstep = 2.0 * step; 17 18 foreach( i; 0 .. N ) 19 { 20 p1 = p2 = p; 21 p1[i] -= step; 22 p2[i] += step; 23 ret.setCol( i, ( f(p2) - f(p1) ) / dstep ); 24 } 25 26 return ret; 27 } 28 29 /// 30 unittest 31 { 32 import std.math : sqrt; 33 auto func( in dvec2 p ) { return dvec3( p.x^^2, sqrt(p.y) * p.x, 3 ); } 34 35 auto res = df( &func, dvec2(18,9), 1e-5 ); 36 auto must = Matrix!(3,2,double)( 36, 0, 3, 3, 0, 0 ); 37 38 assertEqApprox( res.asArray, must.asArray, 1e-5 ); 39 } 40 41 /// 42 auto df(T,K,E=T)( T delegate(T) f, K p, E step=E.epsilon*2 ) 43 if( isFloatingPoint!T && isFloatingPoint!E && is( K : T ) ) 44 { 45 alias V1 = Vector!(1,T); 46 V1 f_vec( in V1 p_vec ) { return V1( f( p_vec[0] ) ); } 47 return df( &f_vec, V1(p), step )[0][0]; 48 } 49 50 /// 51 unittest 52 { 53 auto pow2( double x ){ return x^^2; } 54 assertEqApprox( df( &pow2, 1 ), 2.0, 2e-6 ); 55 assertEqApprox( df( &pow2, 3 ), 6.0, 2e-6 ); 56 assertEqApprox( df( &pow2, -2 ), -4.0, 2e-6 ); 57 }