12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182# 1 "src/base/optimise/owl_numdiff_generic.ml"(*
* OWL - OCaml Scientific and Engineering Computing
* Copyright (c) 2016-2020 Liang Wang <liang.wang@cl.cam.ac.uk>
*)openOwl_types(* Functor of making numerical differentiation module of different precisions *)moduleMake(A:Ndarray_Numdiffwithtypeelt=float)=structtypearr=A.arrtypeelt=A.elt(* global epsilon value used in numerical differentiation *)let_eps=0.00001let_ep1=1.0/._epslet_ep2=0.5/._eps(* derivative of f : scalar -> scalar *)letdifffx=(f(x+._eps)-.f(x-._eps))*._ep2(* derivative of f : scalar -> scalar, return both function value and derivative *)letdiff'fx=fx,difffx(* second order derivative of f : scalar -> scalar *)letdiff2fx=(f(x+._eps)+.f(x-._eps)-.(2.*.fx))/.(_eps*._eps)(* second order derivative of f : float -> float, return both function value and derivative *)letdiff2'fx=fx,diff2fx(* gradient of f : vector -> scalar, return both function value and gradient *)letgrad'fx=letn=A.numelxinletg=A.create[|n|](fx)inletgg=A.mapi(funixi->letx'=A.copyxinA.setx'[|i|](A.elt_to_floatxi+._eps);fx')xing,A.((gg-g)*$_ep1)(* gradient of f : vector -> scalar *)letgradfx=grad'fx|>snd(* transposed jacobian of f : vector -> vector, return both function value and jacobian *)letjacobianT'fx=lety=fxinletm,n=A.numelx,A.numelyinletj=A.tiley[|m;1|]inletjj=A.copyjinfori=0tom-1doletx'=A.copyxinleta=A.elt_to_float(A.getx[|i|])inA.setx'[|i|](a+._eps);lety'=A.reshape(fx')[|1;n|]inA.set_slice[[i];[]]jjy'done;y,A.((jj-j)*$_ep1)(* transposed jacobian of f : vector -> vector *)letjacobianTfx=jacobianT'fx|>snd(* jacobian of f : vector -> vector, return both function value and jacobian *)letjacobian'fx=lety,j=jacobianT'fxiny,A.transpose~axis:[|1;0|]j(* jacobian of f : vector -> vector *)letjacobianfx=jacobian'fx|>sndend(* ends here *)