NB. The Lorentzian profile Ltz(x) for variable x NB. x Ltz y, where y= parameters x0, w & h. Ltz=: {{ 'x0 w h'=. y a=. 2%w L=. h % 1 + *: a*(x-x0) }} NB. This provides the vector of differences between NB. the Lorentzian model and the data points "d" NB. It requires data defined by global variable "lhs" NB. lhs is a 2D array (t;d), where t=(x_i) and d=(d_i) F=: {{ 't d'=. x L=. t Ltz y L - d }} NB. DF provides the partial derivatives of L wrt x0,w & h. DF=: {{ 'x0 w h'=. y a2=. *: a=. 2%w 't d'=. x L2=. *: L=. t Ltz y dLdp=. (2*a2%h)*(t-x0)*L2 dLdw=. (a*a2%h)*L2*(t-x0)^2 dLdh=. L%h |: > dLdp;dLdw;dLdh }} NB. Solve takes one Gauss-Newton step: Solve=: {{ Fx=. x F y NB. evaluate error for each point DFx=. x DF y NB. get derivatives of L DFsq=. (|: DFx) mm DFx NB. approximate the Hessian Top=. Fx mm DFx vv=: -Top %. DFsq NB. solve the linear system NB. "v" is a reserved symbol (like x & y), so we use "vv" y + vv }} NB. update profile parameters SLV=: {{lhs Solve^:_ y}} NB. iterate steps to convergence NB. lhs RMS (p,w,h) --> root mean square of lhs RMS=: {{ %: +/ *: x F y }} NB. mm=: +/ .* (the J expression for matrix multiplication)