1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495# 1 "src/base/optimise/owl_numdiff_generic.ml"(*
* OWL - an OCaml numerical library for scientific computing
* Copyright (c) 2016-2018 Liang Wang <liang.wang@cl.cam.ac.uk>
*)openOwl_types(* Functor of making numerical differentiation module of different precisions *)moduleMake(A:Ndarray_Numdiff)=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|](xi+._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.copyxinA.setx'[|i|]((A.getx[|i|])+._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 *)