File Coverage

levmar.pd
Criterion Covered Total %
statement 211 260 81.1
branch 106 152 69.7
condition 50 75 66.6
subroutine 15 17 88.2
pod 3 11 27.2
total 385 515 74.7


line stmt bran cond sub pod time code
1             # -*-Perl-*- # for emacs
2             use strict;
3             use warnings;
4             use Carp;
5              
6             our $VERSION = '0.0108';
7             pp_setversion( $VERSION );
8              
9              
10             our $HAVE_LAPACK;
11             require './have_lapack';
12             #print "HAVE_LAPACK = $HAVE_LAPACK\n";
13              
14             pp_addpm({At=>'Top'},<<'===EOD===top_pm===');
15             #use Data::Dumper;
16              
17             =head1 NAME
18              
19             PDL::Fit::Levmar - Levenberg-Marquardt fit/optimization routines
20              
21             =head1 DESCRIPTION
22              
23             Levenberg-Marquardt routines for least-squares fit to
24             functions non-linear in fit parameters.
25              
26             This module provides a L ( L ) interface to the non-linear fitting
27             library levmar 2.5 (written in C). Levmar is
28             L aware (in the L sense), provides support for analytic
29             or finite difference derivatives (in case no analytic
30             derivatives are supplied), L and/or L
31             and/or L
32             constraints (with L as a special
33             case) and pure single or double precision computation. The
34             routines are re-entrant, so they can be used in
35             multi-threaded applications (not tested!). Levmar is suited
36             both for data fitting and for optimization problems.
37              
38             The source code for the C levmar library is included in this
39             distribution. However, linearly-constrained fitting requires
40             that C be built with support for B
41             and B libraries. See the files F and
42             F, for more information. If
43             C is built without support for C,
44             the fitting options C, C, C, C, and C may
45             not be used. All other options, including C, do not
46             require C.
47              
48             User supplied fit functions can be written in perl code that
49             takes pdls as arguments, or, for efficiency, in in a simple
50             function description language (C), which is rapidly and
51             transparently translated to C, compiled, and dynamically
52             linked. Fit functions may also be written in pure C. If C
53             or C fit functions are used, the entire fitting
54             procedure is done in pure compiled C. The compilation and
55             linking is done only the first time the function is defined.
56              
57             There is a document distributed with this module
58             F<./doc/levmar.pdf> by the author of liblevmar describing
59             the fit algorithms. Additional information on liblevmar is available at
60             L
61              
62             Don't confuse this module with, but see also, L.
63              
64             =head1 SYNOPSIS
65              
66             use PDL::Fit::Levmar;
67             $result_hash = levmar($params,$x,$t, FUNC => '
68             function somename
69             x = p0 * exp(-t*t * p1);');
70             print levmar_report($result_hash);
71              
72              
73             =head1 EXAMPLES
74              
75              
76             A number of examples of invocations of C follow. The test
77             directory C<./t> in the module distribution contains many more examples.
78             The following seven examples are included as stand-alone scripts in the
79             ./examples/ directory. Some of the necessary lines are not repeated in
80             each example below.
81              
82             =over 3
83              
84             =item example--1
85              
86             In this example we fill co-ordinate $t and ordinate $x arrays
87             with 100 pairs of sample data. Then we call the fit routine
88             with initial guesses of the parameters.
89              
90             use PDL::LiteF;
91             use PDL::Fit::Levmar;
92             use PDL::NiceSlice;
93            
94             $n = 100;
95             $t = 10 * (sequence($n)/$n -1/2);
96             $x = 3 * exp(-$t*$t * .3 );
97             $p = pdl [ 1, 1 ]; # initial parameter guesses
98              
99             $h = levmar($p,$x,$t, FUNC =>
100             ' function
101             x = p0 * exp( -t*t * p1);
102             ');
103             print levmar_report($h);
104              
105             This example gives the output:
106              
107             Estimated parameters: [ 3 0.3]
108             Covariance:
109             [
110             [5.3772081e-25 7.1703376e-26]
111             [7.1703376e-26 2.8682471e-26]
112             ]
113              
114             ||e||_2 at initial parameters = 125.201
115             Errors at estimated parameters:
116             ||e||_2 = 8.03854e-22
117             ||J^T e||_inf = 2.69892e-05
118             ||Dp||_2 = 3.9274e-15
119             \mu/max[J^T J]_ii ] = 1.37223e-05
120             number of iterations = 15
121             reason for termination: = stopped by small ||e||_2
122             number of function evaluations = 20
123             number of jacobian evaluations = 2
124              
125             In the example above and all following examples, it is necessary
126             to include the three C statements at the top of the file.
127             The fit function in this example is in C code.
128             The parameter pdl $p is the input parameters (guesses)
129             levmar returns a hash with several elements including a
130             plain text report of the fit, which we chose to print.
131              
132             The interface is flexible-- we could have also called levmar like this
133              
134             $h = levmar($p,$x,$t, ' function
135             x = p0 * exp( -t*t * p1);
136             ');
137              
138             or like this
139              
140             $h = levmar(P =>$p, X => $x, T=> $t, FUNC => ' function
141             x = p0 * exp( -t*t * p1);
142             ');
143              
144             After the fit, the input parameters $p are left
145             unchanged. The output hash $h contains, among other things,
146             the optimized parameters in $h->{P}.
147              
148             =item example--2
149              
150             Next, we do the same fit, but with a perl/PDL fit function.
151              
152             $h = levmar($p,$x,$t, FUNC => sub {
153             my ($p,$x,$t) = @_;
154             my ($p0,$p1) = list $p;
155             $x .= $p0 * exp(-$t*$t * $p1);
156             });
157              
158             Using perl code (second example) results in slower execution
159             than using pure C (first example). How much slower depends
160             on the problem (see L below). See also the
161             section on L.
162              
163             =item example--3
164              
165             Next, we solve the same problem using a C fit routine.
166              
167             levmar($p,$x,$t, FUNC => '
168             #include
169             void gaussian(FLOAT *p, FLOAT *x, int m, int n, FLOAT *t)
170             {
171             int i;
172             for(i=0; i
173             x[i] = p[0] * exp( -t[i]*t[i] * p[1]);
174             }
175             ');
176              
177             The macro C is used rather than float or double because
178             the C code will be used for both single and double precision
179             routines. ( The code is automatically compiled twice; once
180             with C expanded to double and once expanded to float)
181             The correct version is used automatically depending on the
182             type of pdls you give levmar.
183              
184              
185             =item example--4
186              
187             We supply an analytic derivative ( analytic jacobian).
188              
189             $st = '
190             function
191             x = p0 * exp( -t*t * p1);
192              
193             jacobian
194             FLOAT ex, arg;
195             loop
196             arg = -t*t * p1;
197             ex = exp(arg);
198             d0 = ex;
199             d1 = -p0 * t*t * ex ;
200              
201             ';
202              
203             $h = levmar($p,$x,$t, FUNC => $st);
204              
205             If no jacobian function is supplied, levmar automatically
206             uses numeric difference derivatives. You can also explicitly
207             use numeric derivatives with the option C
208             C<< => 'numeric' >>.
209              
210             Note that the directives C and C begin
211             the function definitions. You can also supply a name if
212             you like, eg. C and C.
213              
214             In C, the co-ordinate data is always identified by 't', the
215             ordinate data by 'x' in the fit function and by 'dn', with n a
216             number, in the jacobian. The parameters are identified by
217             'p'. All other identifiers are pure C identifiers and
218             must be defined, as are C and C in the example.
219              
220             Referring to the example above, if the directive C appears
221             on a line by itself, code after it is wrapped in a loop over
222             the data; code before it is not. If C does not appear,
223             then all the code is wrapped in a loop. 'loop' must occur zero
224             or one times in each of the fit and jacobian definitions.
225             For some problems, you will not want a loop at all. In this
226             case the directive C is placed after the declarations.
227              
228             To see what C does, pass the option C C<< => 1 >> to levmar
229             and look at the C source file that is written.
230              
231             When defining the derivatives above (d0, d1) etc., you must
232             put the lines in the proper order ( eg, not d1,d0 ). (This
233             is for efficiency, see the generated C code.)
234              
235             One final note on this example-- we declared C and C to
236             be type C. Because they are temporary variables, we could
237             have hard coded them to double, in which case both the float
238             and double code versions would have used type double for them.
239             This is ok, because it doesn't cost any storage or cause
240             a memory fault because of incorrect pointer arithmetic.
241              
242              
243             =item example--5
244              
245             Here is an example from the liblevmar demo program that shows
246             one more bit of C syntax.
247              
248             $defst = "
249             function modros
250             noloop
251             x0 = 10 * (p1 -p0*p0);
252             x1 = 1.0 - p0;
253             x2 = 100;
254             jacobian jacmodros
255             noloop
256             d0[0] = -20 * p0;
257             d1[0] = 10;
258             d0[1] = -1;
259             d1[1] = 0;
260             d0[2] = 0;
261             d1[2] = 0;
262             ";
263             $p = pdl [-1.2, 1];
264             $x = pdl [0,0,0];
265             $h = levmar( $p,$x, FUNC => $defst );
266              
267             The directive C mentioned above has been used,
268             indicating that there are no implied loops in the
269             function. Note that this model function is designed only for
270             $x->nelem == 3. The additional syntax is in the
271             derivatives. Keeping in mind that there is no loop variable,
272             dq[r] means derivative w.r.t q evaluated at x[r]. (This is
273             translated by C to d[q+r*m], which is the index into a
274             1-d array.)
275              
276             =item example--6
277              
278             Here is an example that uses implicit threading. We create data
279             from a gaussian function with four different sets of parameters
280             and fit it all in one function call.
281              
282             $st = '
283             function
284             x = p0 * exp( -t*t * p1);
285             ';
286              
287             $n = 10;
288             $t = 10 * (sequence($n)/$n -1/2);
289             $x = zeroes($n,4);
290             map { $x(:,$_->[0]) .= $_->[1] * exp(-$t*$t * $_->[2] ) }
291             ( [0,3,.2], [1, 28, .1] , [2,2,.01], [3,3,.3] );
292             $p = [ 5, 1]; # initial guess
293             $h = levmar($p,$x,$t, FUNC => $st );
294             print $h->{P} . "\n";
295              
296             [
297             [ 3 0.2]
298             [ 28 0.1]
299             [ 2 0.01]
300             [ 3 0.3]
301             ]
302              
303              
304             =item example--7
305              
306             This example shows how to fit a bivariate Gaussian. Here
307             is the fit function.
308              
309             sub gauss2d {
310             my ($p,$xin,$t) = @_;
311             my ($p0,$p1,$p2) = list $p;
312             my $n = $t->nelem;
313             my $t1 = $t(:,*$n); # first coordinate
314             my $t2 = $t(*$n,:); # second coordinate
315             my $x = $xin->splitdim(0,$n);
316             $x .= $p0 * exp( -$p1*$t1*$t1 - $p2*$t2*$t2);
317             }
318              
319              
320             We would prefer a function that maps t(n,n) --> x(n,n) (with
321             p viewed as parameters.) But the levmar library expects one
322             dimensional x and t. So we design C to take
323             piddles with these dimensions: C, C,
324             C. For this example, we assume that both the co-ordinate
325             axes run over the same range, so we only need to pass n
326             values for t. The piddles t1 and t2 are (virtual) copies of
327             t with dummy dimensions inserted. Each represents
328             co-ordinate values along each of the two axes at each point
329             in the 2-d space, but independent of the position along the
330             other axis. For instance C and C
331             == t(j)>. We assume that the piddle xin is a flattened
332             version of the ordinate data, so we split the dimensions in
333             x. Then the entire bi-variate gaussian is calculated with
334             one line that operates on 2-d matrices. Now we create some
335             data,
336              
337             my $n = 101; # number of data points along each axis
338             my $scale = 3; # range of co-ordiate data
339             my $t = sequence($n); # co-ordinate data (used for both axes)
340             $t *= $scale/($n-1);
341             $t -= $scale/2; # rescale and shift.
342             my $x = zeroes($n,$n);
343             my $p = pdl [ .5,2,3]; # actual parameters
344             my $xlin = $x->clump(-1); # flatten the x data
345             gauss2d( $p, $xlin, $t->copy); # compute the bivariate gaussian data.
346              
347             Now x contains the ordinate data (so does xlin, but in a flattened shape.)
348             Finally, we fit the data with an incorrect set of initial parameters,
349              
350             my $p1 = pdl [ 1,1,1]; # not the parameters we used to make the data
351             my $h = levmar($p1,$xlin,$t,\&gauss2d);
352              
353             At this point C<$h->{P}> refers to the output parameter piddle C<[0.5, 2, 3]>.
354              
355             =back
356              
357             =head1 CONSTRAINTS
358              
359             Several of the options below are related to constraints. There are
360             three types: box, linear equation, and linear inequality. They may
361             be used in any combination. (But there is no testing if
362             there is a possible solution.) None or one or two of C and C may be
363             specified. None or both of C and C may be specified.
364             None or both of C and C may be specified.
365              
366             =head1 OPTIONS
367              
368             It is best to learn how to call levmar by looking at the
369             examples first, and looking at this section later.
370              
371             levmar() is called like this
372              
373             levmar($arg1, $arg2, ..., OPT1=>$val1, OPT2=>$val2, ...);
374             or this:
375             levmar($arg1, $arg2, ..., {OPT1=>$val1, OPT2=>$val2, ...});
376              
377             When calling levmar, the first 3 piddle arguments (or refs
378             to arrays), if present, are taken to be C<$p>,C<$x>, and C<$t>
379             (parameters, ordinate data, and co-ordinate data) in that
380             order. The first scalar value that can be interpreted as a
381             function will be. Everything else must be passed as an
382             option in a key-value pair. If you prefer, you can pass some
383             or all of C<$p,$x,$t> and the function as key-values in the
384             hash. Note that after the first key-value pair, you cannot
385             pass any more non-hash arguments. The following calls are equivalent
386             (where $func specifies the function as described in L ).
387              
388             levmar($p, $x, $t, $func);
389             levmar($func,$p, $x, $t);
390             levmar($p, $x, $t, FUNC=> $func);
391             levmar($p, $x, T=>$t, FUNC => $func);
392             levmar($p, X=>$x, T=>$t, FUNC => $func);
393             levmar(P=>$p, X=>$x, T=>$t, FUNC => $func);
394              
395             In the following, if the default value is not mentioned, it is undef.
396             C<$outh> refers to the output hash.
397              
398             Some of these options are actually options to Levmar::Func.
399             All options to Levmar::Func may by given in calls to levmar().
400              
401             =over 4
402              
403             =item FUNC
404              
405             This option is required (but it can be passed before the
406             options hash without the key C ) It can be
407             any of the following, which are auto-detected.
408              
409             a string containing lpp code
410             a string containing pure C code
411             the filename of a file containing lpp code (which must end in '.lpp' )
412             the filename of a file containing pure C code ( which must end in '.c' )
413             a reference to perl code
414             a reference to a previously created Levmar::Func object (which was
415             previously created via one of the preceeding methods.)
416              
417             If you are fitting a lot of data by doing many iterations over
418             a loop of perl code, it is by far most efficient to create a Func
419             object from C or lpp code and pass it to levmar. (Implicit threading
420             does not recompile code in any case.)
421              
422             You can also pass pure C code via the option CSRC.
423              
424             =item JFUNC
425              
426             This parameter is the jacobian as a ref to perl CODE. For
427             C and C code, the jacobian, if present, is always in the
428             same source file as the fit function; in this case, you
429             should leave C undefined. See L
430              
431             =item DERIVATIVE
432              
433             This takes the value 'numeric' or 'analytic'. If it is
434             set to 'analytic', but no analytic jacobian of the model
435             function is supplied, then the numeric algorithms will be used
436             anyway.
437              
438             =item NOCLEAN
439              
440             If defined (NOCLEAN => 1), files containing generated C
441             object and dynamic library code are not deleted. If not
442             defined, these files are deleted after they are no longer
443             needed. For the source and object (.c and .o) files, this
444             means immediately after the dynamic library (.so) is built.
445             The dynamic library file is deleted when the corresponding
446             Levmar::Func object is destroyed. (It could be deleted after
447             it is loaded, I suppose, and then be rebuilt if needed
448             again)
449              
450             =item FIX
451              
452             Example: Fix => [1,0,0,1,0].
453             This option takes a pdl (or array ref) of the same shape as
454             the parameters $p. Each element must have the value zero or
455             one. A zero corresponds to a free parameter and a one to a
456             fixed parameter. The best fit is found keeping the fixed
457             parameters at their input values and letting the free
458             parameters vary. This is implemented by using the linear
459             constraint option described below. Each element must be
460             either one or zero. This option currently cannot be
461             threaded. That is, if the array FIX has more than one
462             dimension you will not get correct results. Also, PDL will
463             not add dimension correctly if you pass additional
464             dimensions in other quantities. Threading will work if you
465             use linear constraints directly via C and C.
466              
467             =item FIXB
468              
469             This option is almost the same as FIX. It takes the same
470             values with the same meanings. It fixes parameters at the value
471             of the input parameters, but uses
472             box constraints, i.e., UB and LB rather than linear
473             constraints A and B. You can specify all three of UB,LB, and FIXB.
474             In this case, first box constraints determined by UB and LB are applied
475             Then, for those elements of FIXB with value one, the corresponding
476             values of UB and LB are overridden.
477              
478             =item A
479              
480             Example: A =>pdl [ [1,0], [0,1] ] , B => pdl [ 1,2 ]
481              
482             Minimize with linear constraints $A x $p = $b. That is,
483             parameters $p are optimized over the subset of parameters
484             that solve the equation. The dimensions of the quantities
485             are A(k,m), b(m), p(m), where k is the number of
486             constraints. ( k <= m ). Note that $b is a vector (it has one
487             fewer dimensions than A), but the option key is a capital 'B'.
488              
489             =item B
490              
491             See C.
492              
493             =item UB
494              
495             Example: UB => [10,10,10], LB => [-10,0,-5].
496             Box constraints. These have the same shape as the parameter
497             pdl $p. The fit is done with ub forming upper bounds and lb
498             lower bounds on the parameter values. Use, for instance
499             PDL::Fit::Levmar::get_dbl_max() for parameters that you
500             don't want bounded. You can use either linear constraints or
501             box constraints, or both. That is, you may specify A, B, UB, and LB.
502              
503             =item LB
504              
505             See C.
506              
507              
508             =item WGHTS
509              
510             Penalty weights can be given optionally when box and linear equality
511             constraints are both passed to levmar. See the levmar documenation for
512             how to use this. Note that if C and D are used then the WGHTS must
513             not passed.
514              
515             =item C
516              
517             Example: C => [ [ -1, -2, -1, -1], [ -3, -1, -2, 1] ], D => [ -5, -0.4]
518             Linear inequality constraints. Minimize with constraints $C x $p >= $d.
519             The dimensions are C(k2,m), D(m), p(m).
520              
521             =item D
522              
523             See C
524              
525             =item P
526              
527             Keys P, X, and T can be used to send to the parameters, ordinates and coordinates.
528             Alternatively, you can send them as non-option arguments to levmar before
529             the option arguments.
530              
531             =item X
532              
533             See C

534              
535             =item T
536              
537             See C

538              
539             =item DIR
540              
541             The directory containing files created when compiling C
542             and C fit functions. This defaults to being created by
543             L. The .c,
544             .o, and .so files will be written to this directory. This
545             option actually falls through to levmar_func. Such options
546             should be in separate section, or otherwise noted.
547              
548             =item GETOPTS
549              
550             If defined, return a ref to a hash containing the default
551             values of the parameters.
552              
553             =item COVAR
554              
555             Send a pdl reference for the output hash element COVAR. You may
556             want to test if this option is more efficient for
557             some problem. But unless the covariance matrix is very large,
558             it probably won't help much. On the other hand it almost certainly
559             won't make levmar() less efficient.
560              
561             Note that levmar returns a piddle representing the covariance in
562             the output hash. This will be the the same piddle that you give
563             as input via this option. So, if you do the following,
564              
565             my $covar = PDL->null
566             my $h =levmar(...., COVAR => $covar);
567              
568             then $covar and $h->{COVAR} are references to the same
569             pdl. The storage for the pdl will not be destroyed until
570             both $covar and $h->{COVAR} become undefined.
571              
572             =item NOCOVAR
573              
574             If defined, no covariance matrix is computed.
575              
576             =item POUT
577              
578             Send a pdl reference for the output hash element P. Don't
579             confuse this with the option P which can be used to send the
580             initial guess for the parameters (see C).
581              
582             =item INFO
583              
584             Send a pdl reference for the output hash element C.
585             (see C)
586              
587             =item RET
588              
589             Send a pdl reference for the output hash element C.
590             (see C)
591              
592              
593             =item MAXITS
594              
595             Maximum number of iterations to try before giving up. The default
596             is 100.
597              
598             =item MU
599              
600             The starting value of the parameter mu in the L-M algorithm.
601              
602             =item EPS1, EPS2, EPS3
603              
604             Stopping thresholds for C<||J^T e||_inf>, C<||Dp||_2> and
605             C<||e||_2>. (see the document levmar.pdf by the author of
606             liblevmar and distributed with this module) The algorithm
607             stops when the first threshold is reached (or C is reached). See
608             C for determining which threshold was reached.
609              
610             Here, C is a the vector of errors between the data and
611             the model function and C

is the vector of parameters.

612             S<||J^T e||_inf> is the gradient of C w.r.t C

613             at the current estimate of C

; C<||Dp||_2> is the amount

614             by which C

is currently being shifted at each iteration;

615             C<||e||_2> is a measure of the error between the model function
616             at the current estimate for C

and the data.

617              
618             =item DELTA
619              
620             This is a step size used in computing numeric derivatives. It is
621             not used if the analytic jacobian is used.
622              
623              
624             =item MKOBJ
625              
626             command to compile source into object code. This option is actually set in
627             the Levmar::Func object, but can be given in calls to levmar().
628             The default value is determined by the perl installation and can
629             be determined by examining the Levmar::Func object returned by
630             new or the output hash of a call to levmar. A typical value is
631             cc -c -O2 -fPIC -o %o %c
632              
633             =item MKSO
634              
635             command to convert object code to dynamic library code.
636             This option is actually set in the Levmar::Func object. A
637             typical default value is
638             cc -shared -L/usr/local/lib -fstack-protector %o -o %s
639              
640             =item CTOP
641              
642             The value of this string will be written at the top of the c code
643             written by Levmar::Func. This can be used to include headers and so forth.
644             This option is actually set in the Levmar::Func object. This code is also written
645             at the top of c code translated from lpp code.
646              
647              
648             =item FVERBOSE
649              
650             If true (eg 1) Print the compiling and linking commands to STDERR when compiling fit functions.
651             This option is actually passed to Levmar::Func. Default is 0.
652              
653             =item Default values
654              
655             Here are the default values
656             of some options
657              
658              
659             $Levmar_defaults = {
660             FUNC => undef, # Levmar::Func object, or function def, or ...
661             JFUNC => undef, # must be ref to perl sub
662             MAXITS => 100, # maximum iterations
663             MU => LM_INIT_MU, # These are described in levmar docs
664             EPS1 => LM_STOP_THRESH,
665             EPS2 => LM_STOP_THRESH,
666             EPS3 => LM_STOP_THRESH,
667             DELTA => LM_DIFF_DELTA,
668             DERIVATIVE => 'analytic',
669             FIX => undef,
670             A => undef,
671             B => undef,
672             C => undef,
673             D => undef,
674             UB = undef,
675             LB => undef,
676             X => undef,
677             P => undef,
678             T => undef,
679             WGHTS => undef,
680             # meant to be private
681             LFUNC => undef, # only Levmar::Func object, made from FUNC
682             };
683              
684             =back
685              
686              
687             =head1 OUTPUT
688              
689             This section describes the contents of the hash that
690             levmar takes as output. Do not confuse these hash keys with
691             the hash keys of the input options. It may be a good idea
692             to change the interface by prepending O to all of the output
693             keys that could be confused with options to levmar().
694              
695             =over 3
696              
697             =item P (output)
698              
699             pdl containing the optimized parameters. It has the same shape
700             as the input parameters.
701              
702             =item FUNC (output)
703              
704             ref to the Levmar::Func object. This object may have been created
705             during the call to levmar(). For instance, if you pass a string
706             contiaining an C definition, the compiled object (and associated
707             information) is contained in $outh->{FUNC}. Don't confuse this with
708             the input parameter of the same name.
709              
710             =item COVAR (output)
711              
712             a pdl representing covariance matrix.
713              
714             =item REASON
715              
716             an integer code representing the reason for terminating the
717             fit. (call levmar_report($outh) for an interpretation. The interpretations
718             are listed here as well (see the liblevmar documentation if you don't
719             find an explanation somewhere here.)
720              
721             1 stopped by small gradient J^T e
722             2 stopped by small Dp
723             3 stopped by itmax
724             4 singular matrix. Restart from current p with increased \mu
725             5 no further error reduction is possible. Restart with increased \mu
726             6 stopped by small ||e||_2
727              
728              
729             =item ERRI, ERR1, ERR2, ERR3, ERR4
730              
731             ERRI is C<||e||_2> at the initial paramters. ERR1 through
732             ERR3 are the actual values on termination of the quantities
733             corresponding to the thresholds EPS1 through EPS3 described
734             in the options section. ERR4 is C
735              
736             =item ITS
737              
738             Number of iterations performed
739              
740             =item NFUNC, NJAC, NLS
741              
742             Number of function evaluations, number of jacobian evaluations
743             and number of linear systems solved.
744              
745             =item INFO
746              
747             Array containing ERRI,ERR1, ..., ERR4, ITS, REASON, NFUNC, NJAC, NLS.
748              
749             =back
750              
751             =head1 FIT FUNCTIONS
752              
753             Fit functions, or model functions can be specified in the following
754             ways.
755              
756             =over 3
757              
758             =item lpp
759              
760             It is easier to learn to use C by reading the C section.
761              
762             C processes a function definition into C code. It writes
763             the opening and closing parts of the function, alters a
764             small number of identifiers if they appear, and wraps some
765             of the code in a loop. C recognizes four directives. They
766             must occur on a line with nothing else, not even comments.
767              
768             First, the directives are explained, then the substitutions.
769             The directive lines have a strict format. All other lines
770             can contain any C code including comments and B
771             macros. They will be written to a function in C after the
772             substitutions described below.
773              
774             =over 3
775              
776             =item C
777              
778             The first line of the fit function definition must be
779             C. The first line of the jacobian
780             definition, if the jacobian is to be defined, is C
781             funcname>. The function names can be any valid C function
782             name. The names may also be omitted as they are never needed
783             by the user. The names can be identical. (Note that a
784             numeric suffix will be automatically added to the function
785             name if the .so file already exists. This is because, if
786             another Func object has already loaded the shared library
787             from an .so file, dlopen will use this loaded library for
788             all C objects asking for that .so file, even if the
789             file has been overwritten, causing unexpected behavior)
790              
791             =item C
792              
793             The directive C says that all code before C is not
794             in the implicit loop, while all code following C is in
795             the implicit loop. If you omit the directive, then all the code
796             is wrapped in a loop.
797              
798             =item C
799              
800             The directive C says that there is no implicit loop anywhere
801             in the function.
802              
803             =item Out-of-loop substitutions
804              
805             These substitutions translate C to C in lines that occur
806             before the implied loop (or everywhere if there is no loop.)
807             In every case you can write the translated C code into your
808             function definition yourself and C will leave it
809             untouched.
810              
811             =over 3
812              
813             =item pq -> p[q]
814              
815             where q is a sequence of digits.
816              
817              
818             =item xq -> x[q]
819              
820             where q is a sequence of digits. This is applied only in the fit function,
821             not in the jacobian.
822              
823              
824             =item dq[r] -> d[q+m*r]
825              
826             (where m == $p->nelem), q and r are sequences of
827             digits. This applies only in the jacobian. You usually will
828             only use the fit functions with one value of m. It would
829             make faster code if you were to explicitly write, say C,
830             for each derivative at each point. Presumably there is a
831             small number of data points since this is outside a
832             loop. Some provisions should be added to C, say C to
833             hard code the value of C. But m is only explicitly used in
834             constructions involving this substitution.
835              
836              
837             =back
838              
839             =item In-loop substitutions
840              
841             These substitutions apply inside the implied loop. The loop variables are
842             i in the fit function and i and j in the jacobian.
843              
844             =over 3
845              
846             =item t -> t[i]
847              
848             (literal "i") You can also write t[i] or t[expression involving i] by hand.
849             Example: t*t -> t[i]*t[i].
850              
851              
852             =item pq -> p[q]
853              
854             where q is a sequence of digits. Example p3 -> p[3].
855              
856              
857             =item x -> x[i]
858              
859             only in fit function, not in jacobian.
860              
861              
862             =item (dr or dr[i]) -> d[j++]
863              
864             where r is a sequence of digits. Note that r and i are
865             ignored. So you are required to list the derivatives in
866             order. An example is
867              
868             d0 = t*t; // derivative w.r.t p[0] loop over all points
869             d1 = t;
870              
871             If you write C first and then C, lpp will incorrectly
872             assign the derivative functions.
873              
874             =back
875              
876              
877             =back
878              
879              
880              
881             =item C Code
882              
883             The jacobian name must start with 'jac' when a pure C function definition
884             is used. To see example of fit functions writen in C, call levmar
885             with lpp code and the option C. This will leave the C source
886             in the directory given by C. The C code you supply is mangled
887             slightly before passing it to the compiler: It is copied twice, with
888             FLOAT defined in one case as C and in the other as C.
889             The letter C is also appended to the function names in the latter
890             copy. The C code is parsed to find the fit function name and the
891             jacobian function name.
892              
893             We should make it possible to pass the function names as a separate option
894             rather than parsing the C code. This will allow auxiallary functions to
895             be defined in the C code; something that is currently not possible.
896              
897              
898             =item Perl_Subroutines
899              
900             This is how to use perl subroutines as fit functions... (see
901             the examples for now, e.g. L.) The
902             fit function takes piddles $p,$x, and $t, with dimensions
903             m,n, and tn. (often tn ==n ). These are references with
904             storage already allocated (by the user and liblevmar). So
905             you must use C<.=> when setting values. The jacobian takes
906             piddles $p,$d, and $t, where $d, the piddle of derivatives
907             has dimensions (m,n). For example
908              
909             $f = sub myexp {
910             my ($p,$x,$t) = @_;
911             my ($p0,$p1,$p2) = list($p);
912             $x .= exp($t/$p0);
913             $x *= $p1;
914             $x += $p2
915             }
916              
917             $jf = sub my expjac {
918             my ($p,$d,$t) = @_;
919             my ($p0,$p1,$p2) = list($p);
920             my $arg = $t/$p0;
921             my $ex = exp($arg);
922             $d((0)) .= -$p1*$ex*$arg/$p0;
923             $d((1)) .= $ex;
924             $d((2)) .= 1.0;
925             }
926              
927              
928              
929             =back
930              
931              
932             =head1 PDL::Fit::Levmar::Func Objects
933              
934             These objects are created every time you call levmar(). The hash
935             returned by levmar contains a ref to the Func object. For instance
936             if you do
937              
938             $outh = levmar( FUNC => ..., @opts);
939              
940             then $outh->{LFUNC} will contain a ref to the function object. The .so
941             file, if it exists, will not be deleted until the object is destroyed.
942             This will happen, for instance if you do C<$outh = undef>.
943              
944              
945             =head1 IMPLEMENTATION
946              
947             This section currently only refers to the interface and not the fit algorithms.
948              
949             =over 3
950              
951             =item C fit functions
952              
953             The module does not use perl interfaces to dlopen or the C
954             compiler. The C compiler options are taken from
955             %Config. This is mostly because I had already written those
956             parts before I found the modules. I imagine the
957             implementation here has less overhead, but is less portable.
958              
959              
960             =item perl subroutine fit functions
961              
962             Null pdls are created in C code before the fit starts. They
963             are passed in a struct to the C fit function and derivative
964             routines that wrap the user's perl code. At each call the
965             data pointers to the pdls are set to what liblevmar has sent
966             to the fit functions. The pdls are deleted after the fit.
967             Originally, all the information on the fit functions was
968             supposed to be handled by Levmar::Func. But when I added
969             perl subroutine support, it was less clumsy to move most of
970             the code for perl subs to the Levmar module. So the current
971             solution is not very clean.
972              
973             =item Efficiency
974              
975             Using C or C is faster than using perl subs, which is
976             faster than using L, at least in all the tests I have
977             done. For very large data sets, pure C was twice as fast as
978             perl subs and three times as fast as Fit::LM. Some
979             optimization problems have very small data sets and converge
980             very slowly. As the data sets become smaller and the number
981             of iterations increases the advantage of using pure C
982             increases as expected. Also, if I fit a small data set
983             (n=10) a large number of times (just looping over the same
984             problem), Pure C is ten times faster than Fit::LM, while
985             Levmar with perl subs is only about 1.15 times faster than
986             Fit::LM. All of this was observed on only two different
987             problems.
988              
989             =back
990              
991             =head1 FUNCTIONS
992              
993             =head2 levmar()
994              
995             =for ref
996              
997             Perform Levenberg-Marquardt non-linear least squares fit
998             to data given a model function.
999              
1000             =for usage
1001              
1002             use PDL::Fit::Levmar;
1003              
1004             $result_hash = levmar($p,$x,$t, FUNC => $func, %OPTIONS );
1005              
1006             $p is a pdl of input parameters
1007             $x is a pdl of ordinate data
1008             $t is an optional pdl of co-ordinate data
1009            
1010             levmar() is the main function in the Levmar package. See the
1011             PDL::Fit::Levmar for a complete description.
1012              
1013             =for signature
1014              
1015             p(m); x(n); t(nt); int itmax();
1016             [o] covar(m,m) ; int [o] returnval();
1017             [o] pout(m); [o] info(q=10);
1018              
1019             See the module documentation for information on passing
1020             these arguments to levmar. Threading is known to
1021             work with p(m) and x(n), but I have not tested the rest. In
1022             this case all of they output pdls get the correct number of
1023             dimensions (and correct values !). Notice that t(nt) has a
1024             different dimension than x(n). This is correct because in
1025             some problems there is no t at all, and in some it is
1026             pressed into the service of delivering other parameters to
1027             the fit routine. (Formally, even if you use t(n), they are
1028             parameters.)
1029              
1030              
1031             =head2 levmar_chkjac()
1032              
1033             =for ref
1034              
1035             Check the analytic jacobian of a function by computing
1036             the derivatives numerically.
1037              
1038             =for signature
1039            
1040             p(m); t(n); [o] err(n);
1041             This is the relevant part of the signature of the
1042             routine that does the work.
1043              
1044              
1045             =for usage
1046              
1047             use PDL::Fit::Levmar;
1048              
1049             $Gh = levmar_func(FUNC=>$Gf);
1050              
1051             $err = levmar_chkjac($Gh,$p,$t);
1052              
1053             $f is an object of type PDL::Fit::Levmar::Func
1054             $p is a pdl of input parameters
1055             $t is an pdl of co-ordinate data
1056             $err is a pdl of errors computed at the values $t.
1057              
1058             Note: No data $x is supplied to this function
1059              
1060             The Func object $Gh contains a function f, and a jacobian
1061             jf. The i_th element of $err measures the agreement between
1062             the numeric and analytic gradients of f with respect to $p
1063             at the i_th evaluation point f (normally determined by the
1064             i_th element of t). A value of 1 means that the analytic and
1065             numeric gradients agree well. A value of 0 mean they do not
1066             agree.
1067              
1068             Sometimes the number of evaluation points n is hardcoded
1069             into the function (as in almost all the examples taken from
1070             liblevmar and appearing in t/liblevmar.t. In this case the
1071             values that f returns depend only on $p and not on any other
1072             external data (nameley t). In this case, you must pass the
1073             number n as a perl scalar in place of t. For example
1074              
1075             $err = levmar_chkjac($Gh,$p,5);
1076              
1077              
1078             in the case that f is hardcoded to return five values.
1079 7     7   96  
  7         21  
  7         329  
1080 7     7   4423 Need to put the description from the C code in here.
  7         214  
  7         127  
1081 7     7   1310  
  7         15  
  7         535  
1082 7     7   5655 =head2 levmar_report()
  7         189808  
  7         60  
1083 7     7   4142992  
  7         36  
  7         109  
1084 7         25947 =for ref
1085 7     7   1390  
  7         12  
1086             Make a human readable report from the hash ref returned
1087             by levmar().
1088              
1089             =for usage
1090              
1091             use PDL::Fit::Levmar;
1092              
1093             $h = levmar($p,$x,$t, $func);
1094 0     0 0 0  
1095             print levmar_report($h);
1096              
1097              
1098             =head1 BUGS
1099              
1100             With the levmar-2.5 code: Passing workspace currently does not work with
1101             linear inequality constraint. Some of the PDL threading no long works
1102             correctly. These are noted in the tests in t/thread.t. It is not clear
1103             if it is a threading issue or the fitting has changed.
1104              
1105            
1106             =cut
1107              
1108             #--------------------------------------------------------------------
1109             # Begining of module code
1110              
1111             use strict;
1112             use PDL::Fit::Levmar::Func;
1113             use Carp;
1114             use PDL::NiceSlice;
1115             use PDL::Core ':Internal'; # For topdl()
1116             use vars ( '$Levmar_defaults', '$Levmar_defaults_order',
1117             '$Perl_func_wrapper', '$Perl_jac_wrapper', '$LPPEXT', '$DBLMAX' );
1118              
1119             # 'jac' refers to jacobian
1120             $Perl_func_wrapper = get_perl_func_wrapper();
1121             $Perl_jac_wrapper = get_perl_jac_wrapper();
1122             $DBLMAX = get_dbl_max();
1123              
1124             $LPPEXT = ".lpp";
1125              
1126              
1127             sub deb { print STDERR $_[0],"\n"}
1128              
1129             ===EOD===top_pm===
1130              
1131             pp_addpm({At=>'Top'},"\$PDL::Fit::Levmar::HAVE_LAPACK=$HAVE_LAPACK;\n");
1132              
1133             pp_addpm({At=>'Bot'},<<'===EOD===Authors===');
1134              
1135              
1136             =head1 AUTHORS
1137              
1138             PDL code for Levmar Copyright (C) 2006 John Lapeyre. C
1139             library code Copyright (C) 2006 Manolis Lourakis, licensed
1140             here under the Gnu Public License.
1141              
1142             All rights reserved. There is no warranty. You are allowed
1143             to redistribute this software / documentation under certain
1144             conditions. For details, see the file COPYING in the PDL
1145             distribution. If this file is separated from the PDL
1146             distribution, the copyright notice should be included in the
1147             file.
1148              
1149             =cut
1150              
1151             ===EOD===Authors===
1152              
1153             pp_addhdr('
1154             #include
1155             #include
1156             #include
1157             #include
1158             #include "pdlperlfunc.h"
1159             #include "levmar.h"
1160             ');
1161              
1162              
1163             pp_add_exported('', 'levmar', 'levmar_report', 'levmar_chkjac');
1164              
1165              
1166             pp_addpm(<<'===EOD===pm_code===one');
1167              
1168 1     1 0 10  
1169 1         18 # check if dims are equal in two pdls
1170 1         16 sub chk_eq_dims {
1171 1 50       19 my ($x,$y) = @_;
1172 1         3 my (@xd) = $x->dims();
1173 1         7 my (@yd) = $y->dims();
1174 1 50       11 return -2 if (scalar(@xd) != scalar(@yd) );
1175             my $ret = 1;
1176 1         10 foreach (@xd) {
1177             return -1 if ($_ != shift(@yd) );
1178             }
1179             return $ret;
1180             }
1181              
1182             @PDL::Fit::Levmar::reason_for_terminating = (
1183             '',
1184             'stopped by small gradient J^T e',
1185             'stopped by small Dp',
1186             'stopped by itmax',
1187             'singular matrix. Restart from current p with increased \mu',
1188             'no further error reduction is possible. Restart with increased \mu',
1189             'stopped by small ||e||_2'
1190 8     8 1 13372 );
1191 8         78
1192             sub levmar_report {
1193             my $h = shift;
1194             make_report($h->{P},$h->{COVAR}, $h->{INFO});
1195             }
1196 8     8 0 30  
1197 8         81 # make a small report out of the results of the optimization
1198             sub make_report {
1199             my ($p,$covar,$info) = @_;
1200             my @ninf = list($info);
1201 8         300 # for(my $i=0;$i<9; $i++) { # Tried to get threading to work, but no!
1202             # $ninf[$i] = $info(($i));
1203 8         22 # }
1204             $ninf[6] =
1205             $PDL::Fit::Levmar::reason_for_terminating[$ninf[6]]; # replace int with string
1206             my $form = <<"EOFORM";
1207             Estimated parameters: %s
1208             Covariance: %s
1209             ||e||_2 at initial parameters = %g
1210             Errors at estimated parameters:
1211             ||e||_2\t = %g
1212             ||J^T e||_inf\t= %g
1213             ||Dp||_2\t= %g
1214             \\mu/max[J^T J]_ii ]\t= %g
1215             number of iterations\t= %d
1216             reason for termination: = %s
1217             number of function evaluations\t= %d
1218             number of jacobian evaluations\t= %d
1219 8         219 number of linear systems solved\t= %d
1220             EOFORM
1221             my $st = sprintf($form, $p,$covar,@ninf);
1222            
1223             }
1224              
1225             $Levmar_defaults_order = qw [
1226             FUNC
1227            
1228              
1229             ];
1230              
1231              
1232             $Levmar_defaults = {
1233             MAXITS => 100, # maximum iterations
1234             MU => LM_INIT_MU(),
1235             EPS1 => LM_STOP_THRESH(),
1236             EPS2 => LM_STOP_THRESH(),
1237             EPS3 => LM_STOP_THRESH(),
1238             DELTA => LM_DIFF_DELTA(),
1239             DERIVATIVE => 'analytic',
1240             NOCOVAR => undef,
1241             FIX => undef,
1242             FIXB => undef,
1243             A => undef,
1244             B => undef,
1245             C => undef,
1246             D => undef,
1247             UB => undef,
1248             LB => undef,
1249             FUNC => undef, # Levmar::Func object, or function def, or ...
1250             JFUNC => undef, # must be ref to perl sub
1251             X => undef,
1252             P => undef,
1253             T => undef,
1254             WGHTS => undef,
1255             COVAR => undef, # The next 5 params can be set to PDL->null
1256             POUT => undef, # ref for preallocated output parameters
1257             INFO => undef,
1258             RET => undef,
1259             # meant to be private
1260             LFUNC => undef, # only Levmar::Func object, made from FUNC
1261             };
1262 0     0 0 0  
1263             # This isn't meant to replace help. But for now its doing nothing.
1264             sub get_help_str {
1265             return '
1266             This is the help string for levmar.
1267              
1268             ';
1269             }
1270 91     91 1 4628173  
1271 91         0 #################################################################
1272             sub levmar {
1273             my($p,$x,$t,$infunc);
1274             my $args;
1275 91         305 # get all args before the hash. p,x,t must come in that order
1276 178         328 # but (t), or (t and x), or (t,x,and p) can be in the hash
1277 178 100 66     1466 # the function can be anywhere before the hash
      66        
1278 86         171 while (1) {
  86         190  
1279             $args = 0;
1280 178 50       550 if ( (not defined $p ) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) {
1281 178 100 66     2222 $p = shift ; $args++;
      66        
1282 78         210 }
  78         161  
1283             last if ( @_ == 0 );
1284 178 50       573 if ( (not defined $x ) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) {
1285 178 100 66     3424 $x = shift ; $args++;
      66        
1286 41         92 }
  41         124  
1287             last if ( @_ == 0 );
1288 178 100       694 if ( (not defined $t) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) {
1289 171 100 100     1146 $t = shift ; $args++;
1290 21         52 }
  21         32  
1291             last if ( @_ == 0 );
1292 171 100       391 if ( not defined $infunc and ref($_[0]) =~ /Func|CODE/ ) {
1293 168 100 66     2141 $infunc = shift; $args++;
      66        
      66        
1294             }
1295 8         19 last if ( @_ == 0 );
  8         11  
1296             if ( (not defined $infunc) and
1297 168 100 100     1305 ( not ref($_[0]) ) and ( $_[0] =~ /(\.c|$LPPEXT)$/o or $_[0] =~ /\n/ ) ) {
1298             $infunc = shift; $args++;
1299 91         123 }
1300 91 100       489 last if ( @_ == 0 or $args == 0);
1301 91 100       247 }
1302 91 100       245 my $inh;
1303 80 50       759 $inh = shift if @_; # input parameter hash
1304             $inh = {} unless defined $inh;
1305 91 50       375 if(ref $inh ne 'HASH') { # turn list into anonymous hash
1306 0         0 $inh = defined $inh ? {$inh,@_} : {} ;
1307 0         0 }
1308             if( exists $inh->{HELP} ) {
1309 91 100       1384 my $s = get_help_str();
1310 1         90 return $s;
1311 1         14 }
1312             if( exists $inh->{GETOPTS} ) {
1313             my %h = %$Levmar_defaults;
1314 90 100       251 return \%h;
1315             }
1316 90 50 66     2511 # should already use a ref to string here
1317             $inh->{FUNC} = $infunc if defined $infunc;
1318             die "levmar: neither FUNC nor CSRC defined"
1319             unless defined $inh->{FUNC} or defined $inh->{CSRC};
1320              
1321             ===EOD===pm_code===one
1322              
1323             if (not $HAVE_LAPACK) {
1324 90         278 pp_addpm( q!
1325             foreach (qw( A B C D FIX WGHT )) {
1326 540 50       1438 barf "PDL::Fit::Levmar not built with lapack. Found parameter $_"
1327             if exists $inh->{$_};
1328             }
1329             !)
1330             }
1331              
1332             pp_addpm(<<'===EOD===pm_code===two');
1333              
1334 90         192
1335 90         161 ######## Handle parameters
1336 90         2058 my $h = {}; # parameter hash to be built from $inh and defaults
1337 2430         6949 my $funch = {}; # unrecognized parameter hash. This will be passed to Func.
1338             foreach ( keys %$Levmar_defaults ){ # copy defaults to final hash
1339 90         731 $h->{$_} = $Levmar_defaults->{$_};
1340 234 100       464 }
1341 221         443 foreach my $k (keys %$inh ) { # replace defaults with input params
1342             if ( exists $Levmar_defaults->{$k} ) {
1343             $h->{$k} = $inh->{$k};
1344 13         49 }
1345             else { # don't recognize, so pass to Func
1346             $funch->{$k} = $inh->{$k};
1347             }
1348             }
1349             ########## Set up input and output variables
1350 90 100 66     747  
1351 90 100 66     414 # These must come from parameters if not from the arg list
1352 90 100 66     427 $p = $h->{P} unless not defined $h->{P} and defined $p;
1353             $x = $h->{X} unless not defined $h->{X} and defined $p;
1354 90 50       207 $t = $h->{T} unless not defined $h->{T} and defined $p;
1355              
1356 0         0 if ( not defined $p ) { # This looks like some kind of error thing that was
1357 0         0 # not implemented consistently
1358 0         0 my $st = "No parameter (P) pdl";
1359             warn $st;
1360 90 50       193 return {RET => -1, ERRS => [$st] };
1361 0         0 }
1362 0         0 if ( not defined $x ) {
1363 0         0 my $st = "No data (X) pdl";
1364             warn $st;
1365             return {RET => -1, ERRS => [$st] };
1366             }
1367              
1368 90         638 #-------------------------------------------------
1369 90         771 # Treat input and output piddles for pp_defs
1370 90 100       533 $x = topdl($x); # in case they are refs to arrays
1371 90         1347 $p = topdl($p);
1372             $t = PDL->zeroes($p->type, 1) unless defined $t; # sometimes $t not needed
1373 90         586 $t = topdl($t);
1374             ### output variables
1375 90         0 my $pout;
1376 90         0 my $info;
1377 90         0 my $covar;
1378             my $ret;
1379             my $wghts;
1380 90 100       250  
1381 90 50       222 # should put this stuff in a loop
1382 90 50       197 $covar = $h->{COVAR} if defined $h->{COVAR};
1383 90 50       240 $pout = $h->{POUT} if defined $h->{POUT};
1384 90 50       295 $info = $h->{INFO} if defined $h->{INFO};
1385             $ret = $h->{RET} if defined $h->{RET};
1386             $wghts = $h->{WGHTS} if defined $h->{WGHTS};
1387 90 100       1600  
1388 90 50       1404 # If they are set here, then there will be no external ref.
1389 90 50       1126 $covar = PDL->null unless defined $covar;
1390 90 50       916 $pout = PDL->null unless defined $pout;
1391 90 50       879 $info = PDL->null unless defined $info;
1392             $ret = PDL->null unless defined $ret;
1393             $wghts = PDL->null unless defined $wghts;
1394              
1395             # Careful about $m, it is used in construcing $A below (with fix). But this is
1396 90         1007 # not correct when using implicit threading. Except threading may still be working.
1397             # Need to look into that.
1398             my $m = $p->nelem;
1399              
1400             #--------------------------------------------------------
1401 90 50       340 # Set up Func object
1402 90 100 100     987 #--------------------------------------------------------
1403             croak "No FUNC in options to levmar." unless exists $h->{FUNC};
1404 63         252 if ( ref($h->{FUNC}) =~ /CODE/ or
1405 63         368 not ref($h->{FUNC}) ) { # probably a string, convert to func object
1406 63 50       10716003 $funch->{FUNC} = $h->{FUNC};
1407 0         0 my @ret = PDL::Fit::Levmar::Func::levmar_func($funch);
1408             if ($ret[0] == -1 ) { # error in creating function
1409 0         0 shift(@ret);
1410             # deb "Error: " . join("\n",@ret); # can turn this off and on
1411 63         642 return {RET => -1, ERRS => [@ret] } ; # just return all the other messages.
1412             }
1413             $h->{LFUNC} = $ret[0];
1414 27         96 }
1415 27         81 else { # already a Func object
1416             $h->{LFUNC} = $h->{FUNC} ; # copy ref
1417             my @k = keys %$funch;
1418             # It would be good to check for valid options. But if a user switches from a
1419             # string to a Func oject in the call to levmar(), he may not delete the
1420 27 50       84 # other keys. Halting on an error would bit frustrating or puzzling.
1421 0 0       0 # Even a warning is perhaps too much
  0         0  
1422 0         0 if ( @k ) {
1423 0         0 my $s = ''; $s = 's' if @k>1;
1424 0         0 my $str = "Unrecognized or useless option$s to levmar: \n";
1425             foreach ( @k ) {
1426 0         0 $str .= " '$_' => '" . $funch->{$_} . "'\n" ;
1427             }
1428             warn $str ."";
1429             }
1430             }
1431 90         649 # C pointers to fit functions
1432 90         1463 my ($funcn,$sfuncn,$jacn,$sjacn) = # single and double
1433             $h->{LFUNC}->get_fit_pointers();
1434             my $deriv = $h->{DERIVATIVE};
1435              
1436 90         292 # The DFP stuff is to wrap perl functions in C routines to pass to liblevmar.
1437             # It's probably cleaner to move most of this stuff into Levmar::Func
1438 90 100       687 my $DFP = 0; # routines check for $DFP == 0 to bypass perl wrapper
1439 8         15  
1440 8         75 if ( ref($h->{FUNC}) =~ /CODE/) { # setup perl wrapper stuff
1441 8 100 66     95 my $jfunc = 0;
1442 6         16 $DFP = DFP_create();
1443             if (defined $h->{JFUNC} and ref($h->{JFUNC}) =~ /CODE/) {
1444 8 100 100     50 $jfunc = $h->{JFUNC};
1445             }
1446 2         4 if ( $deriv eq 'analytic' and $jfunc == 0 ) {
1447 2         2 # warn "No jacobian function supplied, using numeric derivatives";
1448             $deriv = 'numeric';
1449 8         45 $h->{DERIVATIVE} = 'numeric';
1450 8         13 }
1451 8         12 DFP_set_perl_funcs($DFP, $h->{FUNC}, $h->{JFUNC});
1452 8         10 $funcn = $Perl_func_wrapper;
1453 8         14 $jacn = $Perl_jac_wrapper;
1454             $sfuncn = $Perl_func_wrapper; # Single and double can use same wrapper
1455             $sjacn = $Perl_jac_wrapper;
1456             }
1457              
1458 90 100       587 ############ Do a few sanity checks
    50          
1459 71 100 66     898  
1460             if ( $deriv eq 'analytic' ) {
1461 1         15 if (not defined $jacn or $jacn == 0 ) {
1462 1         35 # warn "No jacobian function supplied, using numeric derivatives";
1463             $deriv = 'numeric';
1464             $h->{DERIVATIVE} = 'numeric';
1465             }
1466 0         0 }
1467             elsif ( $deriv ne 'numeric' ) {
1468             croak "DERIVATIVE must be 'analytic' or 'numeric'";
1469             }
1470              
1471             # liblevmar uses 5 option for analytic and 6 for numeric.
1472 90 100       1610 my $opts = pdl($p->type, @$h{qw(MU EPS1 EPS2 EPS3)},
1473             $h->{DERIVATIVE} eq 'analytic' ? () : $h->{DELTA}
1474 90         13306 );
1475             # We make an integer option array as well, for passing stuff , like maxits.
1476             my $iopts = pdl(long, $h->{MAXITS});
1477              
1478             ########### FIX holds some parameters constant using linear constraints.
1479             # It is a special case of more general constraints using A and b.
1480             # Notice that this fails if FIX has more than one dimension (ie, you are
1481 90 50       6979 # threading. FIXB does the same but using box constraints.
    100          
1482 0         0  
1483 0 0       0 if (defined $h->{FIX} ) {
1484 0         0 my $ip = topdl( $h->{FIX}); # take array ref or pdl
1485             if ( chk_eq_dims($ip,$p) < 0 ) {
1486 0         0 croak "p and FIX must have the same dimensions";
1487 0 0       0 }
1488 0         0 my $nc = $ip->sum; # number of fixed vars
1489 0         0 if ($nc > 0) {
1490 0         0 my $A = zeroes($p->type, $m,$nc);
1491 0         0 my $b = zeroes($p->type, $nc);
1492 0 0       0 my $j=0;
1493 0         0 for(my $i=0; $i<$m; $i++) {
1494 0         0 if ($ip->at($i) == 1) {
1495 0         0 $A($i,$j) .= 1;
1496             $b($j) .= $p->at($i);
1497             $j++;
1498 0         0 }
1499 0         0 }
1500             $h->{A} = $A;
1501             $h->{B} = $b;
1502             }
1503 1         30 }
1504 1 50       162 elsif ( defined $h->{FIXB} ) {
1505 0         0 my $f = topdl( $h->{FIXB}); # take array ref or pdl
1506             if ( chk_eq_dims($f,$p) < 0 ) {
1507 1 50       12 croak "p and FIX must have the same dimensions";
1508 1 50       4 }
1509 1         14 $h->{UB} = ones($p) * $DBLMAX if not defined $h->{UB};
1510 1         120 $h->{LB} = ones($p) * -$DBLMAX if not defined $h->{LB};
1511 1         454 $_ = topdl($_) for @$h{qw(UB LB)};
1512 1         391 my $fi = PDL::Primitive::which($f == 1); # indices in p that we want to fix.
1513             $h->{UB}->flat->index($fi) .= $p->flat->index($fi);
1514             $h->{LB}->flat->index($fi) .= $p->flat->index($fi);
1515             # so ub and lb are now at maximum bounds where not fixed and at value of
1516 90         394 # p where fixed
1517 90 50       1539 }
1518 0         0 my $want_covar = 1;
1519             if ( defined $h->{NOCOVAR} ) {
1520             $want_covar = 0;
1521 90         2583 }
1522 90 50       272  
1523             my $errs = check_levmar_args($h);
1524 0         0 if ( @$errs > 0 ) {
1525             # print @$errs;
1526 90         326 return {RET => -1, ERRS => $errs };
1527             }
1528 90 50       254 my ($func_key, $arg_list) = build_constraint_arg_combination($h);
1529 0         0 # print "func key '$func_key'\n";
1530             if ( not defined $func_key ) {
1531 90 50       382 croak "Could not find function key";
1532 0         0 }
1533             if ( not exists $PDL::Fit::Levmar::PDL_Levmar_funcs{$func_key} ) {
1534 90         345 croak "Could not find function for key";
1535             }
1536             my $pdl_levmar_func = $PDL::Fit::Levmar::PDL_Levmar_funcs{$func_key};
1537             # print "func $pdl_levmar_func\n";
1538             # my $nargs = @$arg_list;
1539             # print "Got $nargs args\n";
1540 90 100       468727 &$pdl_levmar_func($p,$x,$t,@$arg_list,$iopts,$opts,
1541             $covar, $ret, $pout, $info, $funcn, $sfuncn,
1542             ($h->{DERIVATIVE} eq 'analytic' ? ( $jacn, $sjacn ) : ()),
1543 90 100       26674330 $DFP, $want_covar);
1544              
1545             DFP_free($DFP) if $DFP;
1546              
1547             my $hout = {
1548             RET => $ret,
1549             COVAR => $covar,
1550             P => $pout,
1551             ERRI => $info((0)),
1552             ERR1 => $info((1)),
1553             ERR2 => $info((2)),
1554             ERR3 => $info((3)),
1555             ERR4 => $info((4)),
1556             ITS => $info((5)),
1557             REASON => $info((6)),
1558             NFUNC => $info((7)),
1559             NJAC => $info((8)),
1560             NLS => $info((9)),
1561 90         1986 INFO => $info,
1562 90         44076 FUNC => $h->{LFUNC},
1563             };
1564             return $hout;
1565            
1566             } # end levmar()
1567 90     90 0 283  
1568 90         1380  
1569 90         217 sub PDL::Fit::Levmar::check_levmar_args {
1570 90         418 my ($h) = @_;
1571 540 100 66     2385 my @refargs = qw( LB UB A B C D );
1572 30         89 my @errs = ();
1573 30 50       145 foreach my $argname ( @refargs ) {
1574 0         0 if ( exists $h->{$argname} and defined $h->{$argname} ) {
1575             my $arg = $h->{$argname};
1576             if ( not ref($arg) ) {
1577             push @errs, "$argname must be a pdl or ref to array.";
1578 90         736 }
1579 90         199 }
1580 180         463 }
1581 180         274 my @combs = ( [ 'A', 'B' ], [ 'C', 'D' ] );
1582 180         323 foreach my $comb (@combs ) {
1583 360 50 33     1606 my $n = @$comb;
1584             my $nf = 0;
1585 180 50 33     546 foreach my $arg ( @$comb ) {
1586 0         0 $nf++ if exists $h->{$arg} and defined $h->{$arg};
1587             }
1588             if ( $nf != 0 and $n != $nf ) {
1589 90         464 push @errs, 'none or all of ' . join(' and ',@$comb) . ' must be defined.';
1590             }
1591             }
1592             return \@errs;
1593             }
1594              
1595            
1596             # make a list of strings of names of constraint args that
1597 90     90 0 225 # have been passed.
1598 90         229 # hash is arg hash to top level call
1599 90         247 sub PDL::Fit::Levmar::build_constraint_arg_combination {
1600             my ($h) = @_;
1601 90         1117 my @arg_comb = ();
1602 90         328 my @arg_list = ();
1603 540         1302 # order is important in following
1604             my @possible_args = qw( LB UB A B C D );
1605 540 100 66     2065 foreach ( @possible_args ) {
1606 30         78 my $ucarg = $_;
1607 30         233 # $ucarg =~ tr/a-z/A-Z/; # should rewrite so that tr not needed
1608             if ( exists $h->{$ucarg} and defined $h->{$ucarg} ) {
1609             push @arg_comb, $_;
1610 90         180 push @arg_list, topdl($h->{$ucarg});
1611 90 100       315 }
1612 70         226 }
1613             my $deriv_type;
1614             if ($h->{DERIVATIVE} eq 'analytic' ) {
1615 20         115 $deriv_type = 'DER';
1616             }
1617 90 50 33     727 else {
1618 90         478 $deriv_type = 'DIFF';
1619 90         535 }
1620             push @arg_list, topdl($h->{WGHTS}) if exists $h->{WGHTS} and defined $h->{WGHTS};
1621             my $fk = make_pdl_levmar_func_key(make_hash_key_from_arg_comb(\@arg_comb), $deriv_type);
1622             return ($fk,\@arg_list);
1623 90     90 0 227 }
1624 90         746  
1625             sub PDL::Fit::Levmar::make_hash_key_from_arg_comb {
1626             my ( $arg_comb ) = @_;
1627             return join( '_', @$arg_comb);
1628 90     90 0 293 }
1629 90         438  
1630              
1631             sub PDL::Fit::Levmar::make_pdl_levmar_func_key {
1632             my ($arg_str, $deriv_type) = @_;
1633             return $deriv_type . '_' . $arg_str;
1634             }
1635              
1636              
1637             %PDL::Fit::Levmar::PDL_Levmar_funcs = (
1638             DER_ => \&PDL::levmar_der_,
1639             DIFF_ => \&PDL::levmar_diff_,
1640             DER_LB_C_D => \&PDL::levmar_der_lb_C_d,
1641             DIFF_LB_C_D => \&PDL::levmar_diff_lb_C_d,
1642             DER_A_B => \&PDL::levmar_der_A_b,
1643             DIFF_A_B => \&PDL::levmar_diff_A_b,
1644             DER_UB_A_B => \&PDL::levmar_der_ub_A_b,
1645             DIFF_UB_A_B => \&PDL::levmar_diff_ub_A_b,
1646             DER_UB => \&PDL::levmar_der_ub,
1647             DIFF_UB => \&PDL::levmar_diff_ub,
1648             DER_A_B_C_D => \&PDL::levmar_der_A_b_C_d,
1649             DIFF_A_B_C_D => \&PDL::levmar_diff_A_b_C_d,
1650             DER_LB_UB_A_B_C_D => \&PDL::levmar_der_lb_ub_A_b_C_d,
1651             DIFF_LB_UB_A_B_C_D => \&PDL::levmar_diff_lb_ub_A_b_C_d,
1652             DER_LB => \&PDL::levmar_der_lb,
1653             DIFF_LB => \&PDL::levmar_diff_lb,
1654             DER_LB_A_B_C_D => \&PDL::levmar_der_lb_A_b_C_d,
1655             DIFF_LB_A_B_C_D => \&PDL::levmar_diff_lb_A_b_C_d,
1656             DER_UB_A_B_C_D => \&PDL::levmar_der_ub_A_b_C_d,
1657             DIFF_UB_A_B_C_D => \&PDL::levmar_diff_ub_A_b_C_d,
1658             DER_LB_UB => \&PDL::levmar_der_lb_ub,
1659             DIFF_LB_UB => \&PDL::levmar_diff_lb_ub,
1660             DER_LB_A_B => \&PDL::levmar_der_lb_A_b,
1661             DIFF_LB_A_B => \&PDL::levmar_diff_lb_A_b,
1662             DER_UB_C_D => \&PDL::levmar_der_ub_C_d,
1663             DIFF_UB_C_D => \&PDL::levmar_diff_ub_C_d,
1664             DER_LB_UB_A_B => \&PDL::levmar_der_lb_ub_A_b,
1665             DIFF_LB_UB_A_B => \&PDL::levmar_diff_lb_ub_A_b,
1666             DER_LB_UB_C_D => \&PDL::levmar_der_lb_ub_C_d,
1667             DIFF_LB_UB_C_D => \&PDL::levmar_diff_lb_ub_C_d,
1668 4     4 1 565702 DER_C_D => \&PDL::levmar_der_C_d,
1669 4         20 DIFF_C_D => \&PDL::levmar_diff_C_d,
1670 4 50       30 );
1671 0         0  
1672 0         0  
1673              
1674 4         14  
1675 4 50       58 sub levmar_chkjac {
1676 0         0 my ($f,$p,$t) = @_;
1677 0         0 my $r = ref $f;
  0         0  
1678             if ( not $r =~ /Levmar::Func/ ) {
1679 4         13 warn "levmar_chkjac: not a Levmar::Func object ";
1680 4         14 return;
1681 4 100       17 }
1682 2         3 my $N;
1683 2         13 if ( not ref($t) =~ /PDL/ ) {
1684 2 50 33     21 $N = $t; # in case there is no t for this func
1685 0         0 $t = zeroes( $p->type, 1); just some pdl
1686 0         0 }
1687             my $DFP = 0;
1688 2         7 my ($funcn,$sfuncn,$jacn,$sjacn);
1689 2         3 if ( ref($f->{FUNC}) =~ /CODE/) { # setup perl wrapper stuff
1690 2         6 my $jfunc = 0;
1691 2         2 $DFP = DFP_create();
1692 2         3 if (not (defined $f->{JFUNC} and ref($f->{FUNC}) =~ /CODE/ ) ) {
1693             warn "levmar_chkjac: no perl code jacobian supplied in JFUNC.";
1694             return undef;
1695 2         27 }
1696             DFP_set_perl_funcs($DFP, $f->{FUNC}, $f->{JFUNC});
1697             $funcn = $Perl_func_wrapper;
1698 4         21 $jacn = $Perl_jac_wrapper;
1699 4 50       14 $sfuncn = $Perl_func_wrapper;
1700 0         0 $sjacn = $Perl_jac_wrapper;
1701             }
1702             else { # pointers to native c functions.
1703 4         196 ($funcn,$sfuncn,$jacn,$sjacn) =
1704             $f->get_fit_pointers();
1705 4         1125 }
1706 4         10 my $err;
1707             if ( defined $N ) {
1708             $err = _levmar_chkjac_no_t($p,$funcn,$sfuncn,$jacn,$sjacn,$N,$DFP);
1709             }
1710             else {
1711             $err = _levmar_chkjac($p,$t,$funcn,$sfuncn,$jacn,$sjacn,$DFP);
1712             }
1713             DFP_free($DFP);
1714             return $err;
1715             }
1716              
1717             ===EOD===pm_code===two
1718              
1719             =pod
1720              
1721             =begin comment
1722              
1723             The following comments are not intended to appear in documentation.
1724             But short of removing them, I find it impossible to keep them from
1725             appearing in the documentation.
1726              
1727             The following provides an interface to 12 functions in
1728             liblevmar. 2 (float or double) * 2 (numeric or analytic)
1729             * 3 (bc, lec, no constraint). There are 6 pp_defs. pp
1730             takes care of the float , double code itself (with some
1731             macros) You can't nest pp macros, so I use DUMI below.
1732             Note that I put a conditional in the thread loop. Not a
1733             big deal, I think, because the threadloop is calling a big
1734             routine with lots of conditionals and lots of calls to
1735             other similar routines.
1736              
1737             I pass pdl of type long iopts for some
1738             parameters. Currently only maxits is there. I suppose I
1739             could also put want_covar in there, but now its an other
1740             parameter. Whatever is in iopts can be threaded. I suppose
1741             someone might want to thread whether to compute
1742             covariance.
1743              
1744             =end comment
1745              
1746             =cut
1747              
1748             # Note very carefully the placement of trailing commas and semi-colons here.
1749              
1750             sub find_levmar_func_name_from_args {
1751             my ($arglist, $arg_descr) = @_;
1752             my %seen = ();
1753             my $nargs = @$arglist;
1754             my $max_seen = 0;
1755             foreach my $arg ( @$arglist ) {
1756             foreach my $routine ( @{ $arg_descr->{$arg}->{ALLOWEDIN} } ) {
1757             $seen{$routine}++;
1758             $max_seen = $seen{$routine} if $max_seen < $seen{$routine};
1759             }
1760             }
1761             my @routine_priority = qw( bc lec blec bleic );
1762             my $routine = 'none';
1763             foreach my $try_routine ( @routine_priority ) {
1764             if ( exists $seen{$try_routine} and $seen{$try_routine} == $max_seen ) {
1765             $routine = $try_routine;
1766             last;
1767             }
1768             }
1769             # print join(':',@$arglist)," => ";
1770             # print $routine, "\n";
1771             return $routine;
1772             }
1773              
1774             sub make_hash_key_from_arg_comb {
1775             my ( $arg_comb ) = @_;
1776             return join( '_', @$arg_comb);
1777             }
1778              
1779             # Make the string for Pars =>
1780             sub make_constraint_signature {
1781             my ( $arg_comb, $arg_descr ) = @_;
1782             my $sig_str = '';
1783             foreach my $arg ( @$arg_comb ) {
1784             $sig_str .= $arg_descr->{$arg}->{SIGNATURE} . '; ';
1785             }
1786             $sig_str =~ s/;\s$//;
1787             return $sig_str;
1788             }
1789              
1790             sub array_to_hash {
1791             my ($a) = @_;
1792             my $h = {};
1793             foreach ( @$a) {
1794             $h->{$_} = 1;
1795             }
1796             return $h;
1797             }
1798              
1799             # not working now,
1800             # need to use $levmar_routine_description
1801             # below to build correct call arguments
1802             # test if arg is present in arg_comb and write NULL , if not
1803             sub make_constraint_call_args {
1804             my ( $arg_comb, $arg_descr, $levmar_routine_description, $levmar_funtion_name ) = @_;
1805             my $route_descr = $levmar_routine_description->{$levmar_funtion_name};
1806             my $args = $route_descr->{ARGS};
1807             my $reqr = {};
1808             my $arg_comb_hash = array_to_hash($arg_comb);
1809             $reqr = $route_descr->{REQR} if exists $route_descr->{REQR};
1810             my $call_str = '';
1811             foreach my $arg ( @$args ) {
1812             if ( exists $reqr->{$arg}) {
1813             if ( exists $arg_comb_hash->{$reqr->{$arg}} ) {
1814             $call_str .= "$arg,";
1815             }
1816             else {
1817             $call_str .= '0,';
1818             }
1819             next;
1820             }
1821             if ( not exists $arg_comb_hash->{$arg} ) {
1822             $call_str .= 'NULL,';
1823             next;
1824             }
1825             $call_str .= $arg_descr->{$arg}->{CALLARG} . ', ';
1826             }
1827             # $call_str =~ s/,\s$//;
1828             return $call_str;
1829             }
1830              
1831             # We will write 64 (perhaps) pdl function definitions.
1832             # For each constraint option (A,b,C... etc) we have the following:
1833             # SIGNATURE is the string that is part of the ppdef pdl signature
1834             # CALLARG is the pp_def argument in the call to the C routine
1835             # ALLOWEDIN is the list of levmar C routines that take this constraint as an argument
1836             sub make_argument_combinations {
1837             my $arg_descr = {
1838             A => {
1839             SIGNATURE => 'A(m,k)',
1840             CALLARG => '$P(A)',
1841             ALLOWEDIN => [qw( lec blec bleic )],
1842             },
1843             b => {
1844             SIGNATURE => 'b(k)',
1845             CALLARG => '$P(b)',
1846             ALLOWEDIN => [qw( lec blec bleic )],
1847             },
1848             ub => {
1849             SIGNATURE => 'ub(m)',
1850             CALLARG => '$P(ub)',
1851             ALLOWEDIN => [qw( bc blec bleic )],
1852             },
1853             lb => {
1854             SIGNATURE => 'lb(m)',
1855             CALLARG => '$P(lb)',
1856             ALLOWEDIN => [qw( bc blec bleic )],
1857             },
1858             C => {
1859             SIGNATURE => 'C(m,k2)',
1860             CALLARG => '$P(C)',
1861             ALLOWEDIN => [qw( bleic )],
1862             },
1863             d => {
1864             SIGNATURE => 'd(k2)',
1865             CALLARG => '$P(d)',
1866             ALLOWEDIN => [qw( bleic )],
1867             },
1868             # WGHTS => {
1869             # SIGNATURE => 'wghts(m)',
1870             # CALLARG => '$P(wghts)',
1871             # ALLOWEDIN => [qw( blec )],
1872             # },
1873             };
1874              
1875             my $levmar_routine_description = {
1876             none => { ARGS => [] },
1877             bc => { ARGS => [qw( lb ub )] },
1878             lec => { ARGS => [ 'A', 'b', '$SIZE(k)' ],
1879             REQR => { '$SIZE(k)' => 'A' },
1880             },
1881             blec => { ARGS => [ 'lb', 'ub', 'A', 'b' , '$SIZE(k)' ],
1882             REQR => { '$SIZE(k)' => 'A' },
1883             },
1884             bleic => { ARGS => [ 'lb', 'ub', 'A', 'b', '$SIZE(k)', 'C', 'd', '$SIZE(k2)' ],
1885             REQR => { '$SIZE(k)' => 'A', '$SIZE(k2)' => 'C' },
1886             }
1887             };
1888              
1889              
1890             my %arg_combs_analysis =();
1891             # These are intended to be legal constraint combinations
1892             # result should also be used to check if a call is legal
1893             # This should make all leval combinations
1894             my $arg_combs = [];
1895             foreach my $linear ( [ ] , $HAVE_LAPACK ? [ 'A', 'b' ] : () ) {
1896             foreach my $box ( [ ] , [ 'lb', 'ub' ] , [ 'lb' ], [ 'ub' ] ) {
1897             foreach my $ineq ( [ ] , $HAVE_LAPACK ? [ 'C', 'd' ] : () ) {
1898             push @$arg_combs, [ @$box, @$linear, @$ineq ];
1899             }
1900             }
1901             }
1902             foreach my $arg_comb ( @$arg_combs ) {
1903             my $levmar_funtion_name = find_levmar_func_name_from_args( $arg_comb, $arg_descr );
1904             my $comb_key = make_hash_key_from_arg_comb( $arg_comb );
1905             my $constraint_signature = make_constraint_signature( $arg_comb, $arg_descr );
1906             my $call_args = make_constraint_call_args( $arg_comb, $arg_descr,
1907             $levmar_routine_description, $levmar_funtion_name );
1908             $arg_combs_analysis{$comb_key} = {
1909             LEVMAR_FUNCTION_NAME => $levmar_funtion_name,
1910             ARG_COMB => [ @$arg_comb ],
1911             SIGNATURE => $constraint_signature,
1912             CALLARGS => $call_args,
1913             PDL_FUNC_NAME_DER => make_pdl_levmar_func_name_from_strings($comb_key, 'der'),
1914             PDL_FUNC_NAME_DIFF => make_pdl_levmar_func_name_from_strings($comb_key, 'diff'),
1915             };
1916             }
1917             # print Dumper(%arg_combs_analysis);
1918             return \%arg_combs_analysis;
1919             }
1920              
1921             # for testing. This replaces the pdl pp_def sub
1922              
1923             sub disable_ppdef {
1924             my $name = shift;
1925             my %ppdef = @_;
1926             $ppdef{NAME} = $name;
1927             print Dumper(\%ppdef);
1928             }
1929              
1930             sub write_pp_defs {
1931             my ($arg_combs_analysis) = @_;
1932             foreach my $der ( 'analytic', 'numeric' ) {
1933             # foreach my $con ( 'none', 'bc', 'lec', 'blec', 'bleic','blic','leic','lic' ) {
1934             foreach my $argcomb ( keys %$arg_combs_analysis ) {
1935             # passing workspace is broken for some routines, so...
1936             my $arg_anal = $arg_combs_analysis->{$argcomb};
1937             my $h = {NOWORK => 0}; # default
1938             if ($der eq 'analytic') { # analytic derivative
1939             $h->{OPAR} = ' IV jacn; IV sjacn; ';
1940             $h->{CALL} = 'der';
1941             $h->{ARG} = 't$TFD(s,)jacn,';
1942             $h->{DUMI}= 'void * tjacn = (void *) $COMP(jacn);
1943             void * tsjacn = (void *) $COMP(sjacn);';
1944             $h->{WORKFAC} = 2; # needs less workspace than numeric
1945             }
1946             else { # numeric derivative
1947             $h->{OPAR} = '';
1948             $h->{CALL} = 'dif';
1949             $h->{ARG} = '';
1950             $h->{DUMI}= '';
1951             $h->{WORKFAC} = 4;
1952             }
1953             $h->{SIG} = $arg_anal->{SIGNATURE} . '; ' ;
1954             $h->{ARG2} = $arg_anal->{CALLARGS};
1955             if ($arg_anal->{LEVMAR_FUNCTION_NAME} eq 'bleic' ) {
1956             $h->{NOWORK} = 1;
1957             }
1958             my $funcname = '';
1959             $funcname = $arg_anal->{LEVMAR_FUNCTION_NAME} unless $arg_anal->{LEVMAR_FUNCTION_NAME} eq 'none';
1960             $h->{CALL} = $funcname . '_' . $h->{CALL} unless $arg_anal->{LEVMAR_FUNCTION_NAME} eq 'none';
1961             if ($arg_anal->{LEVMAR_FUNCTION_NAME} eq 'blec') {
1962             $h->{SIG} .= 'wghts(m); ';
1963             $h->{ARG2} .= '$P(wghts), ';
1964             }
1965             $h->{ARG2} .= 'NULL, ' if $arg_anal->{LEVMAR_FUNCTION_NAME} eq 'bc' and @{$arg_anal->{ARG_COMB}}; # as of levmar-2.6, a dscl arg
1966             my $pdl_func_name;
1967             $pdl_func_name = $arg_anal->{PDL_FUNC_NAME_DER} if $der eq 'analytic';
1968             $pdl_func_name = $arg_anal->{PDL_FUNC_NAME_DIFF} if $der eq 'numeric';
1969             pp_def( $pdl_func_name,
1970             Pars => " p(m); x(n); t(nt); $h->{SIG} int iopts(in); opts(nopt); [t] work(wn);
1971             [o] covar(m,m) ; int [o] returnval();
1972             [o] pout(m); [o] info(q=10); ",
1973             OtherPars => " IV funcn; IV sfuncn; $h->{OPAR} IV indat; "
1974             . " int want_covar; ",
1975             RedoDimsCode => "
1976             int im = \$PDL(p)->dims[0];
1977             int in = \$PDL(x)->dims[0];
1978             int min = $h->{WORKFAC}*in + 4*im + in*im + im*im;
1979             int inw = \$PDL(work)->dims[0];
1980             \$SIZE(wn) = inw >= min ? inw : min;
1981             ",
1982             GenericTypes => ['F','D'], Doc => undef,
1983             Code => "
1984             int * iopts;
1985             int maxits;
1986             void * tfuncn = (void *) \$COMP(funcn);
1987             void * tsfuncn = (void *) \$COMP(sfuncn);
1988             \$GENERIC(covar) * pcovar;
1989             \$GENERIC(work) * pwork;
1990             $h->{DUMI};
1991             DFP *dat = (void *) \$COMP(indat);
1992             DFP_check( &dat, PDL_\$TFD(F,D), \$SIZE(m), \$SIZE(n),
1993             \$SIZE(nt), \$P(t) );
1994             threadloop %{
1995             loop(m) %{
1996             \$pout() = \$p();
1997             %}
1998             iopts = \$P(iopts);
1999             pcovar = \$COMP(want_covar) == 1 ? \$P(covar) : NULL;
2000             pwork = $h->{NOWORK} == 1 ? NULL : \$P(work);
2001             maxits = iopts[0]; /* for clarity. we hope optimized away */
2002             \$returnval() = \$TFD(s,d)levmar_$h->{CALL} (
2003             t\$TFD(s,)funcn , $h->{ARG}
2004             \$P(pout), \$P(x), \$SIZE(m), \$SIZE(n), $h->{ARG2}
2005             maxits, \$P(opts), \$P(info), pwork, pcovar, dat);
2006             %}
2007             "
2008             );
2009             }
2010             }
2011             }
2012              
2013             # same routine defined above, but in Levmar.pm code
2014             sub make_pdl_levmar_func_key {
2015             my ($arg_str, $deriv_type) = @_;
2016             return $deriv_type . '_' . $arg_str;
2017             }
2018              
2019              
2020              
2021             sub make_pdl_levmar_func_name_from_strings {
2022             my ($arg_str, $deriv_type) = @_;
2023             return 'levmar_' . make_pdl_levmar_func_key($arg_str, $deriv_type);
2024             }
2025              
2026              
2027             my $a = make_argument_combinations();
2028             write_pp_defs($a);
2029              
2030              
2031              
2032             =pod
2033              
2034             =begin comment
2035              
2036             /*
2037             * Check the jacobian of a n-valued nonlinear function in m variables
2038             * evaluated at a point p, for consistency with the function itself.
2039             *
2040             * Based on fortran77 subroutine CHKDER by
2041             * Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More
2042             * Argonne National Laboratory. MINPACK project. March 1980.
2043             *
2044             *
2045             * func points to a function from R^m --> R^n: Given a p in R^m it yields hx in R^n
2046             * jacf points to a function implementing the jacobian of func, whose correctness
2047             * is to be tested. Given a p in R^m, jacf computes into the nxm matrix j the
2048             * jacobian of func at p. Note that row i of j corresponds to the gradient of
2049             * the i-th component of func, evaluated at p.
2050             * p is an input array of length m containing the point of evaluation.
2051             * m is the number of variables
2052             * n is the number of functions
2053             * adata points to possible additional data and is passed uninterpreted
2054             * to func, jacf.
2055             * err is an array of length n. On output, err contains measures
2056             * of correctness of the respective gradients. if there is
2057             * no severe loss of significance, then if err[i] is 1.0 the
2058             * i-th gradient is correct, while if err[i] is 0.0 the i-th
2059             * gradient is incorrect. For values of err between 0.0 and 1.0,
2060             * the categorization is less certain. In general, a value of
2061             * err[i] greater than 0.5 indicates that the i-th gradient is
2062             * probably correct, while a value of err[i] less than 0.5
2063             * indicates that the i-th gradient is probably incorrect.
2064             *
2065             *
2066             * The function does not perform reliably if cancellation or
2067             * rounding errors cause a severe loss of significance in the
2068             * evaluation of a function. therefore, none of the components
2069             * of p should be unusually small (in particular, zero) or any
2070             * other value which may cause loss of significance.
2071             */
2072              
2073             =end comment
2074              
2075             =cut
2076              
2077             pp_def('_levmar_chkjac', Pars => ' p(m); t(n); [o] err(n); ',
2078             OtherPars => ' IV func; IV sfunc; IV jac; IV sjac; IV indat; ',
2079             GenericTypes => ['F','D'], Doc => undef,
2080             Code => '
2081             void * f = (void *) $COMP(func);
2082             void * sf = (void *) $COMP(sfunc);
2083             void * j = (void *) $COMP(jac);
2084             void * sj = (void *) $COMP(sjac);
2085             DFP *dat = (void *) $COMP(indat);
2086             DFP_check( &dat, PDL_$TFD(F,D), $SIZE(m), $SIZE(n), $SIZE(n), $P(t) );
2087             $TFD(s,d)levmar_chkjac (
2088             $TFD(s,)f, $TFD(s,)j,$P(p),$SIZE(m),$SIZE(n),dat,$P(err)
2089             );
2090             '
2091             );
2092              
2093             # From perl5 internals, chapter 4 ...
2094             #Perl's integer type is not necessarily a C int; it's called
2095             #an IV, or Integer Value. The difference is that an IV is
2096             #guaranteed to hold a pointer.
2097              
2098              
2099             pp_def('_levmar_chkjac_no_t', Pars => ' p(m); [o] err(n); ',
2100             OtherPars => 'IV func; IV sfunc; IV jac; IV sjac; int N; IV indat; ',
2101             GenericTypes => ['F','D'], Doc => undef,
2102             RedoDimsCode => "
2103             int N = \$COMP(N);
2104             int nin = \$PDL(err)->dims[0];
2105             \$SIZE(n) = nin >= N ? nin : N;
2106             ",
2107             Code => '
2108             void * f = (void *) $COMP(func);
2109             void * sf = (void *) $COMP(sfunc);
2110             void * j = (void *) $COMP(jac);
2111             void * sj =(void *) $COMP(sjac);
2112             DFP *dat = (void *) $COMP(indat);
2113             DFP_check( &dat, PDL_$TFD(F,D), $SIZE(m), $SIZE(n), $SIZE(n), NULL );
2114             $TFD(s,d)levmar_chkjac (
2115             $TFD(s,)f, $TFD(s,)j,$P(p),$SIZE(m),$SIZE(n),dat,$P(err)
2116             );
2117             '
2118             );
2119              
2120              
2121             =pod
2122              
2123             =begin comment
2124              
2125             No end of trouble cause by confusion over passing ints and chars
2126             and so forth. I am sticking with using ints for pointers for the
2127             time being.
2128              
2129             =end comment
2130              
2131             =cut
2132              
2133              
2134             pp_addxs( '', '
2135              
2136              
2137             void *
2138             DFP_create()
2139              
2140             CODE:
2141             DFP * dat;
2142             dat = (DFP *)malloc(sizeof( DFP ));
2143             if ( NULL == dat ) {
2144             fprintf(stderr, "Can\'t allocate storage for dat in DFP_create\n");
2145             exit(1);
2146             }
2147             RETVAL = dat;
2148             OUTPUT:
2149             RETVAL
2150              
2151             void
2152             DFP_free( dat )
2153             IV dat
2154            
2155             CODE:
2156             if ( (DFP *) dat) free( (DFP *) dat);
2157              
2158              
2159             void
2160             DFP_set_perl_funcs ( data, perl_fit_func, perl_jac_func )
2161             IV data
2162             SV* perl_fit_func
2163             SV* perl_jac_func
2164              
2165             CODE:
2166             DFP *dat = (DFP *) data;
2167             if ( dat == NULL ) {
2168             fprintf(stderr, "DFP_set_perl_funcs got null struct\n");
2169             exit(1);
2170             }
2171             dat->perl_fit_func = perl_fit_func;
2172             dat->perl_jac_func = perl_jac_func;
2173              
2174              
2175             double
2176             get_dbl_max( )
2177             CODE:
2178             RETVAL = DBL_MAX;
2179             OUTPUT:
2180             RETVAL
2181              
2182             double
2183             LM_INIT_MU( )
2184             CODE:
2185             RETVAL = LM_INIT_MU;
2186             OUTPUT:
2187             RETVAL
2188              
2189             double
2190             LM_STOP_THRESH( )
2191             CODE:
2192             RETVAL = LM_STOP_THRESH;
2193             OUTPUT:
2194             RETVAL
2195              
2196             double
2197             LM_DIFF_DELTA( )
2198             CODE:
2199             RETVAL = LM_DIFF_DELTA;
2200             OUTPUT:
2201             RETVAL
2202              
2203              
2204             =pod
2205              
2206              
2207             =begin comment
2208              
2209             The next two routines just get pointers to functions from
2210             the C code and return them as SVs to perl. The functions
2211             are the C wrappers to the users _perl_ fit and jacobian
2212             functions. LEVFUNC and JLEVFUNC should be re-entrant so
2213             the following two routines can called once when the
2214             Levmar::Func module is loaded and can be shared by all
2215             object instances.
2216              
2217             =end comment
2218              
2219             =cut
2220              
2221             void *
2222             get_perl_func_wrapper( )
2223              
2224             CODE:
2225             RETVAL = &LEVFUNC;
2226             OUTPUT:
2227             RETVAL
2228              
2229             void *
2230             get_perl_jac_wrapper( )
2231              
2232             CODE:
2233             RETVAL = &JLEVFUNC;
2234             OUTPUT:
2235             RETVAL
2236              
2237              
2238              
2239             ');
2240              
2241              
2242             pp_done();
2243              
2244