1 ;;; Compiled by f2cl version:
2 ;;; ("f2cl1.l,v 1.215 2009/04/07 22:05:21 rtoy Exp $"
3 ;;; "f2cl2.l,v 1.37 2008/02/22 22:19:33 rtoy Exp $"
4 ;;; "f2cl3.l,v 1.6 2008/02/22 22:19:33 rtoy Exp $"
5 ;;; "f2cl4.l,v 1.7 2008/02/22 22:19:34 rtoy Exp $"
6 ;;; "f2cl5.l,v 1.200 2009/01/19 02:38:17 rtoy Exp $"
7 ;;; "f2cl6.l,v 1.48 2008/08/24 00:56:27 rtoy Exp $"
8 ;;; "macros.l,v 1.112 2009/01/08 12:57:19 rtoy Exp $")
10 ;;; Using Lisp CMU Common Lisp 19f (19F)
12 ;;; Options: ((:prune-labels nil) (:auto-save t) (:relaxed-array-decls nil)
13 ;;; (:coerce-assigns :as-needed) (:array-type ':array)
14 ;;; (:array-slicing t) (:declare-common nil)
15 ;;; (:float-format double-float))
27 (declare (type (double-float) one p1 p5 p25 p75 p0001 zero
))
29 (fcn m n x fvec fjac ldfjac ftol xtol gtol maxfev diag mode factor
30 nprint info nfev njev ipvt qtf wa1 wa2 wa3 wa4
)
31 (declare (type (array f2cl-lib
:integer4
(*)) ipvt
)
32 (type (double-float) factor gtol xtol ftol
)
33 (type (array double-float
(*)) wa4 wa3 wa2 wa1 qtf diag fjac fvec
35 (type (f2cl-lib:integer4
) njev nfev info nprint mode maxfev ldfjac
37 (f2cl-lib:with-multi-array-data
38 ((x double-float x-%data% x-%offset%
)
39 (fvec double-float fvec-%data% fvec-%offset%
)
40 (fjac double-float fjac-%data% fjac-%offset%
)
41 (diag double-float diag-%data% diag-%offset%
)
42 (qtf double-float qtf-%data% qtf-%offset%
)
43 (wa1 double-float wa1-%data% wa1-%offset%
)
44 (wa2 double-float wa2-%data% wa2-%offset%
)
45 (wa3 double-float wa3-%data% wa3-%offset%
)
46 (wa4 double-float wa4-%data% wa4-%offset%
)
47 (ipvt f2cl-lib
:integer4 ipvt-%data% ipvt-%offset%
))
48 (prog ((actred 0.0) (delta 0.0) (dirder 0.0) (epsmch 0.0) (fnorm 0.0)
49 (fnorm1 0.0) (gnorm 0.0) (par 0.0) (pnorm 0.0) (prered 0.0)
50 (ratio 0.0) (sum 0.0) (temp 0.0) (temp1 0.0) (temp2 0.0)
51 (xnorm 0.0) (i 0) (iflag 0) (iter 0) (j 0) (l 0))
52 (declare (type (f2cl-lib:integer4
) l j iter iflag i
)
53 (type (double-float) xnorm temp2 temp1 temp sum ratio prered
54 pnorm par gnorm fnorm1 fnorm epsmch
60 '" the purpose of lmder is to minimize the sum of the squares of"
61 '" m nonlinear functions in n variables by a modification of"
62 '" the levenberg-marquardt algorithm. the user must provide a"
63 '" subroutine which calculates the functions and the jacobian."
65 '" the subroutine statement is"
67 '" subroutine lmder(fcn,m,n,x,fvec,fjac,ldfjac,ftol,xtol,gtol,"
68 '" maxfev,diag,mode,factor,nprint,info,nfev,"
69 '" njev,ipvt,qtf,wa1,wa2,wa3,wa4)"
73 '" fcn is the name of the user-supplied subroutine which"
74 '" calculates the functions and the jacobian. fcn must"
75 '" be declared in an external statement in the user"
76 '" calling program, and should be written as follows."
78 '" subroutine fcn(m,n,x,fvec,fjac,ldfjac,iflag)"
79 '" integer m,n,ldfjac,iflag"
80 '" double precision x(n),fvec(m),fjac(ldfjac,n)"
82 '" if iflag = 1 calculate the functions at x and"
83 '" return this vector in fvec. do not alter fjac."
84 '" if iflag = 2 calculate the jacobian at x and"
85 '" return this matrix in fjac. do not alter fvec."
90 '" the value of iflag should not be changed by fcn unless"
91 '" the user wants to terminate execution of lmder."
92 '" in this case set iflag to a negative integer."
94 '" m is a positive integer input variable set to the number"
97 '" n is a positive integer input variable set to the number"
98 '" of variables. n must not exceed m."
100 '" x is an array of length n. on input x must contain"
101 '" an initial estimate of the solution vector. on output x"
102 '" contains the final estimate of the solution vector."
104 '" fvec is an output array of length m which contains"
105 '" the functions evaluated at the output x."
107 '" fjac is an output m by n array. the upper n by n submatrix"
108 '" of fjac contains an upper triangular matrix r with"
109 '" diagonal elements of nonincreasing magnitude such that"
112 '" p *(jac *jac)*p = r *r,"
114 '" where p is a permutation matrix and jac is the final"
115 '" calculated jacobian. column j of p is column ipvt(j)"
116 '" (see below) of the identity matrix. the lower trapezoidal"
117 '" part of fjac contains information generated during"
118 '" the computation of r."
120 '" ldfjac is a positive integer input variable not less than m"
121 '" which specifies the leading dimension of the array fjac."
123 '" ftol is a nonnegative input variable. termination"
124 '" occurs when both the actual and predicted relative"
125 '" reductions in the sum of squares are at most ftol."
126 '" therefore, ftol measures the relative error desired"
127 '" in the sum of squares."
129 '" xtol is a nonnegative input variable. termination"
130 '" occurs when the relative error between two consecutive"
131 '" iterates is at most xtol. therefore, xtol measures the"
132 '" relative error desired in the approximate solution."
134 '" gtol is a nonnegative input variable. termination"
135 '" occurs when the cosine of the angle between fvec and"
136 '" any column of the jacobian is at most gtol in absolute"
137 '" value. therefore, gtol measures the orthogonality"
138 '" desired between the function vector and the columns"
141 '" maxfev is a positive integer input variable. termination"
142 '" occurs when the number of calls to fcn with iflag = 1"
143 '" has reached maxfev."
145 '" diag is an array of length n. if mode = 1 (see"
146 '" below), diag is internally set. if mode = 2, diag"
147 '" must contain positive entries that serve as"
148 '" multiplicative scale factors for the variables."
150 '" mode is an integer input variable. if mode = 1, the"
151 '" variables will be scaled internally. if mode = 2,"
152 '" the scaling is specified by the input diag. other"
153 '" values of mode are equivalent to mode = 1."
155 '" factor is a positive input variable used in determining the"
156 '" initial step bound. this bound is set to the product of"
157 '" factor and the euclidean norm of diag*x if nonzero, or else"
158 '" to factor itself. in most cases factor should lie in the"
159 '" interval (.1,100.).100. is a generally recommended value."
161 '" nprint is an integer input variable that enables controlled"
162 '" printing of iterates if it is positive. in this case,"
163 '" fcn is called with iflag = 0 at the beginning of the first"
164 '" iteration and every nprint iterations thereafter and"
165 '" immediately prior to return, with x, fvec, and fjac"
166 '" available for printing. fvec and fjac should not be"
167 '" altered. if nprint is not positive, no special calls"
168 '" of fcn with iflag = 0 are made."
170 '" info is an integer output variable. if the user has"
171 '" terminated execution, info is set to the (negative)"
172 '" value of iflag. see description of fcn. otherwise,"
173 '" info is set as follows."
175 '" info = 0 improper input parameters."
177 '" info = 1 both actual and predicted relative reductions"
178 '" in the sum of squares are at most ftol."
180 '" info = 2 relative error between two consecutive iterates"
183 '" info = 3 conditions for info = 1 and info = 2 both hold."
185 '" info = 4 the cosine of the angle between fvec and any"
186 '" column of the jacobian is at most gtol in"
189 '" info = 5 number of calls to fcn with iflag = 1 has"
192 '" info = 6 ftol is too small. no further reduction in"
193 '" the sum of squares is possible."
195 '" info = 7 xtol is too small. no further improvement in"
196 '" the approximate solution x is possible."
198 '" info = 8 gtol is too small. fvec is orthogonal to the"
199 '" columns of the jacobian to machine precision."
201 '" nfev is an integer output variable set to the number of"
202 '" calls to fcn with iflag = 1."
204 '" njev is an integer output variable set to the number of"
205 '" calls to fcn with iflag = 2."
207 '" ipvt is an integer output array of length n. ipvt"
208 '" defines a permutation matrix p such that jac*p = q*r,"
209 '" where jac is the final calculated jacobian, q is"
210 '" orthogonal (not stored), and r is upper triangular"
211 '" with diagonal elements of nonincreasing magnitude."
212 '" column j of p is column ipvt(j) of the identity matrix."
214 '" qtf is an output array of length n which contains"
215 '" the first n elements of the vector (q transpose)*fvec."
217 '" wa1, wa2, and wa3 are work arrays of length n."
219 '" wa4 is a work array of length m."
221 '" subprograms called"
223 '" user-supplied ...... fcn"
225 '" minpack-supplied ... dpmpar,enorm,lmpar,qrfac"
227 '" fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod"
229 '" argonne national laboratory. minpack project. march 1980."
230 '" burton s. garbow, kenneth e. hillstrom, jorge j. more"
234 '" epsmch is the machine precision."
236 (setf epsmch
(dpmpar 1))
243 '" check the input parameters for errors."
255 (if (/= mode
2) (go label20
))
256 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
259 (if (<= (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
) zero
)
264 '" evaluate the function at the starting point"
265 '" and calculate its norm."
268 (multiple-value-bind (var-0 var-1 var-2 var-3 var-4 var-5 var-6
)
269 (funcall fcn m n x fvec fjac ldfjac iflag
)
270 (declare (ignore var-2 var-3 var-4
))
280 (if (< iflag
0) (go label300
))
281 (setf fnorm
(enorm m fvec
))
283 '" initialize levenberg-marquardt parameter and iteration counter."
288 '" beginning of the outer loop."
292 '" calculate the jacobian matrix."
295 (multiple-value-bind (var-0 var-1 var-2 var-3 var-4 var-5 var-6
)
296 (funcall fcn m n x fvec fjac ldfjac iflag
)
297 (declare (ignore var-2 var-3 var-4
))
306 (setf njev
(f2cl-lib:int-add njev
1))
307 (if (< iflag
0) (go label300
))
309 '" if requested, call fcn to enable printing of iterates."
311 (if (<= nprint
0) (go label40
))
313 (if (= (mod (f2cl-lib:int-sub iter
1) nprint
) 0)
314 (multiple-value-bind (var-0 var-1 var-2 var-3 var-4 var-5 var-6
)
315 (funcall fcn m n x fvec fjac ldfjac iflag
)
316 (declare (ignore var-2 var-3 var-4
))
324 (setf iflag var-6
))))
325 (if (< iflag
0) (go label300
))
328 '" compute the qr factorization of the jacobian."
330 (qrfac m n fjac ldfjac f2cl-lib
:%true% ipvt n wa1 wa2 wa3
)
332 '" on the first iteration and if mode is 1, scale according"
333 '" to the norms of the columns of the initial jacobian."
335 (if (/= iter
1) (go label80
))
336 (if (= mode
2) (go label60
))
337 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
340 (setf (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
341 (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
))
342 (if (= (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
) zero
)
343 (setf (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
348 '" on the first iteration, calculate the norm of the scaled x"
349 '" and initialize the step bound delta."
351 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
354 (setf (f2cl-lib:fref wa3-%data%
(j) ((1 n
)) wa3-%offset%
)
355 (* (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
356 (f2cl-lib:fref x-%data%
(j) ((1 n
)) x-%offset%
)))
358 (setf xnorm
(enorm n wa3
))
359 (setf delta
(* factor xnorm
))
360 (if (= delta zero
) (setf delta factor
))
363 '" form (q transpose)*fvec and store the first n components in"
366 (f2cl-lib:fdo
(i 1 (f2cl-lib:int-add i
1))
369 (setf (f2cl-lib:fref wa4-%data%
(i) ((1 m
)) wa4-%offset%
)
370 (f2cl-lib:fref fvec-%data%
(i) ((1 m
)) fvec-%offset%
))
372 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
377 (f2cl-lib:fref fjac-%data%
384 (f2cl-lib:fdo
(i j
(f2cl-lib:int-add i
1))
390 (f2cl-lib:fref fjac-%data%
394 (f2cl-lib:fref wa4-%data%
401 (f2cl-lib:fref fjac-%data%
405 (f2cl-lib:fdo
(i j
(f2cl-lib:int-add i
1))
408 (setf (f2cl-lib:fref wa4-%data%
(i) ((1 m
)) wa4-%offset%
)
409 (+ (f2cl-lib:fref wa4-%data%
(i) ((1 m
)) wa4-%offset%
)
411 (f2cl-lib:fref fjac-%data%
418 (setf (f2cl-lib:fref fjac-%data%
422 (f2cl-lib:fref wa1-%data%
(j) ((1 n
)) wa1-%offset%
))
423 (setf (f2cl-lib:fref qtf-%data%
(j) ((1 n
)) qtf-%offset%
)
424 (f2cl-lib:fref wa4-%data%
(j) ((1 m
)) wa4-%offset%
))
427 '" compute the norm of the scaled gradient."
430 (if (= fnorm zero
) (go label170
))
431 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
434 (setf l
(f2cl-lib:fref ipvt-%data%
(j) ((1 n
)) ipvt-%offset%
))
435 (if (= (f2cl-lib:fref wa2-%data%
(l) ((1 n
)) wa2-%offset%
) zero
)
438 (f2cl-lib:fdo
(i 1 (f2cl-lib:int-add i
1))
444 (f2cl-lib:fref fjac-%data%
449 (f2cl-lib:fref qtf-%data%
456 (f2cl-lib:dmax1 gnorm
459 (f2cl-lib:fref wa2-%data%
467 '" test for convergence of the gradient norm."
469 (if (<= gnorm gtol
) (setf info
4))
470 (if (/= info
0) (go label300
))
472 '" rescale if necessary."
474 (if (= mode
2) (go label190
))
475 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
478 (setf (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
480 (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
481 (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
)))
485 '" beginning of the inner loop."
489 '" determine the levenberg-marquardt parameter."
492 (var-0 var-1 var-2 var-3 var-4 var-5 var-6 var-7 var-8 var-9
494 (lmpar n fjac ldfjac ipvt diag qtf delta par wa1 wa2 wa3 wa4
)
495 (declare (ignore var-0 var-1 var-2 var-3 var-4 var-5 var-6 var-8
496 var-9 var-10 var-11
))
499 '" store the direction p and x + p. calculate the norm of p."
501 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
504 (setf (f2cl-lib:fref wa1-%data%
(j) ((1 n
)) wa1-%offset%
)
505 (- (f2cl-lib:fref wa1-%data%
(j) ((1 n
)) wa1-%offset%
)))
506 (setf (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
)
507 (+ (f2cl-lib:fref x-%data%
(j) ((1 n
)) x-%offset%
)
508 (f2cl-lib:fref wa1-%data%
(j) ((1 n
)) wa1-%offset%
)))
509 (setf (f2cl-lib:fref wa3-%data%
(j) ((1 n
)) wa3-%offset%
)
510 (* (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
511 (f2cl-lib:fref wa1-%data%
(j) ((1 n
)) wa1-%offset%
)))
513 (setf pnorm
(enorm n wa3
))
515 '" on the first iteration, adjust the initial step bound."
517 (if (= iter
1) (setf delta
(f2cl-lib:dmin1 delta pnorm
)))
519 '" evaluate the function at x + p and calculate its norm."
522 (multiple-value-bind (var-0 var-1 var-2 var-3 var-4 var-5 var-6
)
523 (funcall fcn m n wa2 wa4 fjac ldfjac iflag
)
524 (declare (ignore var-2 var-3 var-4
))
533 (setf nfev
(f2cl-lib:int-add nfev
1))
534 (if (< iflag
0) (go label300
))
535 (setf fnorm1
(enorm m wa4
))
537 '" compute the scaled actual reduction."
539 (setf actred
(- one
))
540 (if (< (* p1 fnorm1
) fnorm
)
541 (setf actred
(- one
(expt (/ fnorm1 fnorm
) 2))))
543 '" compute the scaled predicted reduction and"
544 '" the scaled directional derivative."
546 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
549 (setf (f2cl-lib:fref wa3-%data%
(j) ((1 n
)) wa3-%offset%
) zero
)
550 (setf l
(f2cl-lib:fref ipvt-%data%
(j) ((1 n
)) ipvt-%offset%
))
551 (setf temp
(f2cl-lib:fref wa1-%data%
(l) ((1 n
)) wa1-%offset%
))
552 (f2cl-lib:fdo
(i 1 (f2cl-lib:int-add i
1))
555 (setf (f2cl-lib:fref wa3-%data%
(i) ((1 n
)) wa3-%offset%
)
556 (+ (f2cl-lib:fref wa3-%data%
(i) ((1 n
)) wa3-%offset%
)
558 (f2cl-lib:fref fjac-%data%
565 (setf temp1
(/ (enorm n wa3
) fnorm
))
566 (setf temp2
(/ (* (f2cl-lib:dsqrt par
) pnorm
) fnorm
))
567 (setf prered
(+ (expt temp1
2) (/ (expt temp2
2) p5
)))
568 (setf dirder
(- (+ (expt temp1
2) (expt temp2
2))))
570 '" compute the ratio of the actual to the predicted"
574 (if (/= prered zero
) (setf ratio
(/ actred prered
)))
576 '" update the step bound."
578 (if (> ratio p25
) (go label240
))
579 (if (>= actred zero
) (setf temp p5
))
581 (setf temp
(/ (* p5 dirder
) (+ dirder
(* p5 actred
)))))
582 (if (or (>= (* p1 fnorm1
) fnorm
) (< temp p1
)) (setf temp p1
))
583 (setf delta
(* temp
(f2cl-lib:dmin1 delta
(/ pnorm p1
))))
584 (setf par
(/ par temp
))
587 (if (and (/= par zero
) (< ratio p75
)) (go label250
))
588 (setf delta
(/ pnorm p5
))
589 (setf par
(* p5 par
))
593 '" test for successful iteration."
595 (if (< ratio p0001
) (go label290
))
597 '" successful iteration. update x, fvec, and their norms."
599 (f2cl-lib:fdo
(j 1 (f2cl-lib:int-add j
1))
602 (setf (f2cl-lib:fref x-%data%
(j) ((1 n
)) x-%offset%
)
603 (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
))
604 (setf (f2cl-lib:fref wa2-%data%
(j) ((1 n
)) wa2-%offset%
)
605 (* (f2cl-lib:fref diag-%data%
(j) ((1 n
)) diag-%offset%
)
606 (f2cl-lib:fref x-%data%
(j) ((1 n
)) x-%offset%
)))
608 (f2cl-lib:fdo
(i 1 (f2cl-lib:int-add i
1))
611 (setf (f2cl-lib:fref fvec-%data%
(i) ((1 m
)) fvec-%offset%
)
612 (f2cl-lib:fref wa4-%data%
(i) ((1 m
)) wa4-%offset%
))
614 (setf xnorm
(enorm n wa2
))
616 (setf iter
(f2cl-lib:int-add iter
1))
619 '" tests for convergence."
622 (and (<= (f2cl-lib:dabs actred
) ftol
)
624 (<= (* p5 ratio
) one
))
626 (if (<= delta
(* xtol xnorm
)) (setf info
2))
628 (and (<= (f2cl-lib:dabs actred
) ftol
)
630 (<= (* p5 ratio
) one
)
633 (if (/= info
0) (go label300
))
635 '" tests for termination and stringent tolerances."
637 (if (>= nfev maxfev
) (setf info
5))
639 (and (<= (f2cl-lib:dabs actred
) epsmch
)
641 (<= (* p5 ratio
) one
))
643 (if (<= delta
(* epsmch xnorm
)) (setf info
7))
644 (if (<= gnorm epsmch
) (setf info
8))
645 (if (/= info
0) (go label300
))
647 '" end of the inner loop. repeat if iteration unsuccessful."
649 (if (< ratio p0001
) (go label200
))
651 '" end of the outer loop."
656 '" termination, either normal or user imposed."
658 (if (< iflag
0) (setf info iflag
))
661 (multiple-value-bind (var-0 var-1 var-2 var-3 var-4 var-5 var-6
)
662 (funcall fcn m n x fvec fjac ldfjac iflag
)
663 (declare (ignore var-2 var-3 var-4
))
671 (setf iflag var-6
))))
674 '" last card of subroutine lmder."
703 (in-package #:cl-user
)
704 #+#.
(cl:if
(cl:find-package
'#:f2cl
) '(and) '(or))
705 (eval-when (:load-toplevel
:compile-toplevel
:execute
)
706 (setf (gethash 'fortran-to-lisp
::lmder fortran-to-lisp
::*f2cl-function-info
*)
707 (fortran-to-lisp::make-f2cl-finfo
708 :arg-types
'(t (fortran-to-lisp::integer4
)
709 (fortran-to-lisp::integer4
) (array double-float
(*))
710 (array double-float
(*)) (array double-float
(*))
711 (fortran-to-lisp::integer4
) (double-float)
712 (double-float) (double-float)
713 (fortran-to-lisp::integer4
) (array double-float
(*))
714 (fortran-to-lisp::integer4
) (double-float)
715 (fortran-to-lisp::integer4
) (fortran-to-lisp::integer4
)
716 (fortran-to-lisp::integer4
) (fortran-to-lisp::integer4
)
717 (array fortran-to-lisp
::integer4
(*))
718 (array double-float
(*)) (array double-float
(*))
719 (array double-float
(*)) (array double-float
(*))
720 (array double-float
(*)))
721 :return-values
'(nil fortran-to-lisp
::m fortran-to-lisp
::n nil nil
722 nil fortran-to-lisp
::ldfjac nil nil nil nil nil nil
723 nil nil fortran-to-lisp
::info fortran-to-lisp
::nfev
724 fortran-to-lisp
::njev nil nil nil nil nil nil
)
725 :calls
'(fortran-to-lisp::lmpar fortran-to-lisp
::qrfac
726 fortran-to-lisp
::enorm fortran-to-lisp
::dpmpar
))))