File Coverage

/root/.cpan/build/PDL-Fit-Levmar-0.0100-0/blib/lib/PDL/Fit/Levmar/Func.pm
Criterion Covered Total %
statement 351 446 78.7
branch 139 222 62.6
condition 23 36 63.8
subroutine 31 37 83.7
pod 3 26 11.5
total 547 767 71.3


line stmt bran cond sub pod time code
1              
2             #
3             # GENERATED WITH PDL::PP! Don't modify!
4             #
5             package PDL::Fit::Levmar::Func;
6              
7             @EXPORT_OK = qw( levmar_func PDL::PP _callf PDL::PP _callj PDL::PP _callj1 );
8             %EXPORT_TAGS = (Func=>[@EXPORT_OK]);
9              
10 7     7   35 use PDL::Core;
  7         8  
  7         37  
11 7     7   1450 use PDL::Exporter;
  7         13  
  7         53  
12 7     7   165 use DynaLoader;
  7         28  
  7         485  
13              
14              
15              
16             $PDL::Fit::Levmar::Func::VERSION = '0.0100';
17             @ISA = ( 'PDL::Exporter','DynaLoader' );
18             push @PDL::Core::PP, __PACKAGE__;
19             bootstrap PDL::Fit::Levmar::Func $VERSION;
20              
21              
22              
23              
24             =head1 NAME
25              
26             PDL::Fit::Levmar::Func - Create model functions for Levenberg-Marquardt fit routines
27              
28             =head1 DESCRIPTION
29              
30             This module creates and manages functions for use with the
31             Levmar fitting module. The functions are created with a
32             very simple description language (that is mostly C), or are
33             pure C, or are perl code. For many applications, the present
34             document is not necessary because levmar uses the
35             Levmar::Func module transparantly. Therefore, before
36             reading the following, refer to L.
37              
38             =head1 SYNOPSIS
39              
40             use PDL::Fit::Levmar::Func;
41              
42             $func = levmar_func( FUNC => # define and link function
43              
44             '
45             function gaussian
46             loop
47             x[i] = p[0] * exp(-(t[i] - p[1])*(t[i] - p[1])*p[2]);
48             end function
49              
50             jacobian jacgaussian
51             double arg, expf;
52             loop
53             arg = t[i] - p[1];
54             expf = exp(-arg*arg*p[2]);
55             d0 = expf;
56             d1 = p[0]*2*arg*p[2]*expf;
57             d2 = p[0]*(-arg*arg)*expf;
58             end jacobian
59             '
60             );
61              
62             $hout = PDL::Fit::Levmar::levmar($p,$x,$t, # fit the data
63             FUNCTION => $func,
64             );
65              
66             =head1 FUNCTIONS
67              
68             =head2 levmar_func()
69              
70             =for usage
71              
72             levmar_func( OPTIONS )
73              
74             =for ref
75              
76             This function creates and links a function, ie, takes a function definition
77             and returns a function (object instance) ready for use by levmar.
78             see PDL::Fit::Levmar::Func for more information.
79              
80             OPTIONS:
81              
82             =for options
83              
84             Some of the options are described in the PDL::Fit::Levmar documentation.
85              
86             MKOBJ -- command to compile source into object code. This can be set.
87             The default value is determined by the perl installation and can
88             be determined by examining the Levmar::Func object returned by
89             new or the output hash of a call to levmar. A typical value is
90             cc -c -O2 -fPIC -o %o %c
91              
92             MKSO -- command to convert object code to dynamic library code. A typical
93             default value is
94             cc -shared -L/usr/local/lib -fstack-protector %o -o %s
95            
96              
97             CTOP -- The value of this string will be written at the top of the c code
98             written by Levmar::Func. This can be used to include headers and so forth.
99             This option is actually set in the Levmar::Func object.
100              
101              
102             =head2 call()
103              
104             =for ref
105              
106             Call (evaluate) the fit function in a Levmar::Func object.
107              
108             =for usage
109              
110             use PDL::Fit::Levmar::Func;
111              
112             $Gh = levmar_func(FUNC=>$fcode);
113              
114             $x = $Gh->call($p,$t);
115              
116             Here $fcode is a function definition (say lpp code). (This does
117             not currently work with perl subroutines, I think. Of course,
118             you can call the subroutine directly. But it would be good
119             to support it for consistency.)
120            
121             $p is a pdl or ref to array of parameters.
122             $t is a pdl of co-ordinate values.
123             $x is the fit function evaluated at $p and $t. $x has the
124             same shape as $t.
125              
126             =for example
127              
128             $Gf = levmar_func( FUNC => '
129             function
130             x = p0 * t * t;
131             ');
132              
133             print $Gf->call([2],sequence(10)) , "\n";
134             [0 2 8 18 32 50 72 98 128 162]
135              
136             =cut
137              
138              
139 7     7   35 use strict;
  7         9  
  7         140  
140 7     7   29 use Carp;
  7         11  
  7         294  
141 7     7   44 use Config;
  7         18  
  7         212  
142 7     7   31 use File::Path;
  7         21  
  7         375  
143 7     7   2548 use File::Spec::Functions;
  7         4785  
  7         490  
144              
145             sub munlink;
146              
147             #use PDL::NiceSlice;
148 7     7   39 use PDL::Core ':Internal'; # For topdl()
  7         9  
  7         33  
149              
150 7         32708 use vars ('$MKOBJ', '$MKSO', '$OBJ_EXT' , '$SO',
151 7     7   587 '$LEVFUNC', '$JLEVFUNC', '$LPPEXT' );
  7         20  
152              
153             # These are pointers to the C functions that wrap the user's
154             # perl fit functions.
155             #$LEVFUNC = get_perl_func_wrap();
156             #$JLEVFUNC = get_perl_jac_wrap();
157              
158             $OBJ_EXT = $Config{obj_ext};
159             $SO = $Config{so};
160             $LPPEXT = '.lpp';
161             # string to compile .c to .o
162             $MKOBJ = $Config{cc} . " -c " . $Config{optimize} . " " .
163             $Config{cccdlflags} . " -o %o %c ";
164              
165             # string to compile .o to .so
166             $MKSO = $Config{ld} . " " . $Config{lddlflags} ." %o -o %s ";
167              
168              
169              
170              
171              
172              
173              
174              
175              
176             =head2 new
177              
178             =for usage
179              
180             my $fitfunc = new PDL::Fit::Levmar::Func(...);
181             or
182             my $fitfunc = levmar_func(...);
183              
184             =for ref
185              
186             Generic constructor. Use levmar_func rather than new.
187              
188             =cut
189              
190             $PDL::Fit::Levmar::Func::SRC_EXT = ".c";
191             #$PDL::Fit::Levmar::Func::SO_EXT = ".so";
192             #$PDL::Fit::Levmar::Func::OBJ_EXT = ".o";
193              
194       568 0   sub deb {
195             # print STDERR $_[0], "\n";
196             }
197              
198 0     0 0 0 sub prwarn { print STDERR $_[0], "\n";}
199              
200             ##########################################
201             # Methods follow
202              
203             # some kind of stack corruption is related to this function, maybe. no probably not.
204             # So, only shift opts if they are there
205             #use Data::Dumper;
206              
207             sub new {
208 70     70 1 329 my($class) = shift;
209 70         251 my($opts) = shift;
210             # print STDERR "In new class: $class, opts $opts\n";
211 70 100       337 if(ref $opts ne 'HASH') { # change opts to hash of opts
212 8 50       52 $opts = defined $opts ? {$opts,@_} : {} ;
213             }
214             # print Dumper($opts),"\n";
215 70         1310 my $self = { # following are defaults
216             MKOBJ => $MKOBJ,
217             MKSO => $MKSO,
218             NOCLEAN => undef,
219             FUNC => undef,
220             JFUNC => undef,
221             # TYPE => 'double',
222             NOSO => undef,
223             CSRC => undef,
224             CTOP => undef,
225             DIR => "./tempcode" , # where the .so is built
226             TESTSYNTAX => undef,
227             LIBHANDLE => undef,
228             FVERBOSE => 0,
229             };
230 70         313 foreach ( keys %$opts ) { # replace defaults
231 86 50       272 if ( exists $self->{$_} ) {
232 86         260 $self->{$_} = $opts->{$_};
233             }
234 0         0 else { die "Levmar::Func::new: Unrecognized option to Levmar::Func '$_'";}
235             }
236 70         281 return bless $self,$class;
237             }
238              
239             # all these attempts at dying and croaking fail.
240             # program does not quit and error messages are not printed
241             # dont know why. It must be some bad bug in the xs code.
242             # If I just print the error message, its fine.
243             # I think it has to do with DESTROY. return does not work either
244             sub DESTROY {
245 64     64   7076 my $self = shift;
246 64         116 my $cnt = 0;
247 64 100       643 return if defined $self->{NOSO};
248 54 50       270 if ( defined $self->{LIBHANDLE}) {
249 54         217 my ($ret, $err) = close_shared_object_file($self->{LIBHANDLE});
250 54 50 33     471 if ( $err ne '' or $ret != 0) {
251 0         0 warn "Levmar::Func::DESTROY: Error closing function library:$ret '$err'";
252             }
253 54 50       232 warn "Error closing function library:$ret '$err'" if $ret != 0;
254 54 100       198 if ( defined $self->{JPOINTER} ) { # call close twice because we got two symbols
255 52         148 ($ret, $err) = close_shared_object_file($self->{LIBHANDLE});
256 52 50       159 warn "Error closing function library:$ret '$err'" if $ret !=0 ;
257 52 50 33     392 if ( $err ne '' or $ret != 0 ) {
258 0         0 warn "Levmar::Func::DESTROY: Error closing function library:$ret '$err'";
259             }
260             }
261 54 100       176 if ( defined $self->{SJPOINTER} ) { # call close twice because we got two symbols
262 52         143 ($ret, $err) = close_shared_object_file($self->{LIBHANDLE});
263 52 50       138 warn "Error closing function library:$ret '$err'" if $ret !=0 ;
264 52 50 33     326 if ( $err ne '' or $ret != 0 ) {
265 0         0 warn "Levmar::Func::DESTROY: Error closing function library:$ret '$err'";
266             }
267             }
268 54 50       159 if ( defined $self->{SFPOINTER} ) { # call close twice because we got two symbols
269 54         169 ($ret, $err) = close_shared_object_file($self->{LIBHANDLE});
270 54 50       167 warn "Error closing function library:$ret '$err'" if $ret !=0 ;
271 54 50 33     427 if ( $err ne '' or $ret != 0 ) {
272 0         0 warn "Levmar::Func::DESTROY: Error closing function library:$ret '$err'";
273             }
274             }
275             }
276 54 100 66     511 if (not defined $self->{NOCLEAN} and defined $self->{SONAME} ) {
277 53         197 foreach my $k ( qw ( SONAME )) { # clean so file
278 53         138 my $fn = $self->{$k};
279 53 50       814 if (-e $fn) {
280 53 50       561 if ( not -f $fn ) {
281 0         0 warn "Levmar::Func::DESTROY: Refusing to remove non-file '$fn'";
282             }
283             else {
284 53         197 $cnt = munlink $fn;
285 53 50       3949 if ( $cnt < 1 ) {
286 0         0 warn "Levmar::Func::DESTROY: failed removing '$fn' (lib probably open)";
287             }
288             else {
289             # warn "Levmar::Func::DESTROY: SUCCESS removing '$fn'";
290             }
291             }
292             }
293             }
294             }
295             }
296              
297 70     70 1 400137 sub levmar_func { my $self = new PDL::Fit::Levmar::Func(@_);
298 70         155 my @err;
299 70 100 100     952 if ( defined $self->{FUNC} and $self->{FUNC} =~ /CODE/ ) {
300 10         26 $self->{NOSO} = 1; # bad way to handle this
301 10         23 $self->{FPOINTER} = 0; # test for this in levmar
302             }
303             else {
304 60 50 66     276 if ( not defined $self->{FUNC} and not defined $self->{CSRC} ) {
305 0         0 die "Levmar::Func::lemar_func: neither FUNC nor CSRC defined";
306             }
307 60         429 @err = $self->make_ccode();
308 60 50       172 return @err if $err[0] == -1;
309 60         250 $self->make_build_names();
310 60         211 $self->write_ccode();
311 60 50       430 if ( not $self->make_shared_object_file() ) {
312 0         0 die "Levmar::Func::levmar_func: Compilation failed.";
313             }
314 60 50       942 if ( not $self->load_fit_library() ) {
315 0         0 die "Levmar::Func::levmar_func: Loading dynamic library failed.";
316             }
317 60 100       580 $self->clean_files() unless defined $self->{NOCLEAN};
318             }
319 70 100       340 if ( defined $self->{JFUNC} ) { # probably won't get called
320 2 50       13 if ( $self->{JFUNC} =~ /CODE/ ) {
321 2         3 $self->{NOSO} = 1;
322             }
323             else {
324 0         0 die "Levmar::Func::levmar_func option JFUNC must be a ref to a perl sub";
325             }
326             }
327 70         1322 return $self;
328             }
329              
330              
331             sub make_build_names {
332 94     94 0 168 my $self = shift;
333             die "Levmar::Func::levmar_func: no name for function"
334 94 50       245 unless defined $self->{NAME};
335 94         184 my $q = $self->{DIR};
336 94 100       1475 if ( not -d $q ) {
337 1 50       147 die "Levmar::Func::levmar_func: Can't make directory (folder) '$q'"
338             unless File::Path::mkpath( $q );
339             }
340 94 100       540 $self->{FNAME} = $self->{NAME} unless exists $self->{FNAME}; # base file name
341 94         212 my $n = $self->{FNAME};
342 94         652 my $srcn = catfile( $q , $n . $PDL::Fit::Levmar::Func::SRC_EXT);
343 94         432 my $son = catfile($q ,$n . "." . $SO);
344 94         380 my $objn = catfile($q , $n . $OBJ_EXT);
345 94         360 $self->{SRCNAME} = $srcn;
346 94         206 $self->{SONAME} = $son;
347 94         195 $self->{OBJNAME} = $objn;
348             }
349              
350              
351              
352             # change this to identity, can remove sometime
353             sub mfqp {
354 240     240 0 1143 my ($self,$key) = @_;
355 240         768 return $self->{$key};
356             }
357              
358             # substitue string $new for $old when it
359             # occurs after 'void'.
360             sub subst_func_name {
361 28     28 0 64 my ($sref,$old,$new) = @_;
362 28         649 $$sref =~ s/(\W)void\s+$old/$1void $new/;
363             }
364              
365             # Write c source file from function definition.
366             # Entire definition is given as a string, or the
367             # filename , ending in $LPPEXT is given
368             # Copying the source strings around, inefficient. should use
369             # refs
370             sub make_ccode {
371 60     60 0 138 my $self = shift;
372 60         96 my @err;
373              
374 60 100       257 if ( not defined $self->{CSRC} ) { # is FUNC really c code?
375 48 100 100     939 if (not $self->{FUNC} =~ /$LPPEXT$/o # is not a $LPPEXT file
      100        
376             and ( $self->{FUNC} =~ /\.c$/ or # is a .c file
377             # doesnt have function def
378             not $self->{FUNC} =~ /(^|\n)\s*function(\s+\w+|\s*)\n/) ) {
379 2         13 $self->{CSRC} = $self->{FUNC};
380             }
381             }
382 60 100       276 if ( defined $self->{CSRC} ) {
    50          
383 14 100       122 if ( $self->{CSRC} =~ /\.c$/ ) {
384 4         17 my $cf = $self->{CSRC};
385 4         16 local (*CHAND);
386 4         36 local $/;
387 4 50       142 open CHAND, "<$cf" or die "Levmar::Func::make_code : Can't open C src file '$cf'";
388 4         117 $self->{CCODE} = ;
389 4         50 close(CHAND);
390             }
391             else { # inefficient, but it works
392 10         59 $self->{CCODE} = $self->{CSRC};
393             }
394 14         60 my ($funcname, $jacname) = $self->get_funcs_from_c();
395 14 50       38 $jacname = '' unless defined $jacname;
396 14         23 my ($sfuncname, $sjacname);
397 14         27 $sfuncname = 's' . $funcname;
398 14 50       38 $sjacname = 's' . $jacname if $jacname;
399 14         35 my $doublecode = $self->{CCODE};
400 14         19 my $floatcode = $doublecode;
401 14         61 subst_func_name(\$floatcode, $funcname, $sfuncname);
402 14 50       90 subst_func_name(\$floatcode, $jacname, $sjacname) if $jacname;
403 14 50       127 if ($^O =~ /MSWin32/i) {
404 0         0 my $export = ' __declspec (dllexport) ';
405 0         0 subst_func_name(\$doublecode, $funcname, $export . $funcname);
406 0         0 subst_func_name(\$floatcode, $sfuncname, $export . $sfuncname);
407 0 0       0 subst_func_name(\$doublecode, $jacname, $export . $jacname) if $jacname;
408 0 0       0 subst_func_name(\$floatcode, $sjacname, $export . $sjacname) if $jacname;
409             }
410             # if ( /^\s*void\s+([\w]+)/ )
411             $self->{CCODE} =
412 14         102 "
413             #define FLOAT double
414             " . $doublecode .
415             "
416             #undef FLOAT
417             #define FLOAT float
418             " . $floatcode;
419 14 50       71 $self->{NAME} = $funcname unless exists $self->{NAME};
420 14 50       52 $self->{JACNAME} = $jacname unless exists $self->{JACNAME};
421 14         66 return (1); # don't use FUNC even if its there.
422             }
423             elsif ( defined $self->{FUNC} ) {
424 46         102 my $st = $self->{FUNC};
425 46 100       198 if ($st =~ /$LPPEXT$/o) { # file, not string
426 15         49 local (*FUNCHAND);
427 15         116 local $/;
428 15 50       570 open FUNCHAND, "<$st" or die "Levmar::Func::make_ccode : Can't open def file '$st'";
429 15         309 $st = ;
430 15         186 close(FUNCHAND);
431             }
432 46         105 my ($funcname,$jacname,$ccode);
433 46         294 my @ret = generate_C_source($self, $st);
434 46 50       209 if ( $ret[0] eq '-1' ) { # stop warnings with ==
435 0         0 my $r;
436             # ($r, $funcname, $jacname, $code, @err) = @ret;
437 0         0 return @ret;
438             }
439             else {
440 46         172 ($funcname,$jacname,$ccode) = @ret;
441             }
442 46         159 $self->{CCODE} = $ccode;
443 46 50       234 $self->{NAME} = $funcname unless exists $self->{NAME};
444 46 50       156 $self->{JACNAME} = $jacname unless exists $self->{JACNAME};
445 46         165 return (1);
446             }
447 0         0 return (-1, "Can't make C code with no defintion or source file");
448             }
449              
450             # jacobian function name **must** start with 'jac' if using pure c code
451             sub get_funcs_from_c {
452 14     14 0 26 my $self = shift;
453 14         131 my @lines = split ("\n",$self->{CCODE});
454 14         89 my ($fname, $jacname) = (undef, undef);
455 14         39 foreach (@lines ) {
456 382 100       683 if ( /^\s*void\s+([\w]+)/ ) { # prototype begins with 'void' return type
457 28         155 my $fn = $1;
458 28 100       142 if ($fn =~ /^jac/ ) {
459 14         60 $jacname = $fn;
460             }
461             else {
462 14         31 $fname = $fn;
463             }
464             }
465             }
466 14 50 33     130 if ( not defined $fname or $fname eq '' ) { # ok if jacname == undef
467 0         0 die "Levmar::Func::get_funcs_from_c : Can't find function name from c code";
468             }
469 14         84 return ($fname, $jacname);
470             }
471              
472             sub write_ccode {
473 60     60 0 111 my $self = shift;
474 60         201 local (*CCODEH);
475 60 50       173 return unless exists $self->{CCODE};
476 60 50       157 if ( not defined $self->{NAME} ) {
477 0         0 die "Levmar::Func::write_ccode : Can't write C code for function with no name";
478             }
479 60         128 my $srcn = $self->{SRCNAME};
480 60 50       3573 open CCODEH, ">$srcn" or die "Levmar::Func::write_ccode : Can't open C source file '$srcn' for writing";
481 60 50       314 print CCODEH $self->{CTOP}, "\n" if defined $self->{CTOP};
482 60         553 print CCODEH $self->{CCODE};
483 60         2123 close CCODEH;
484             }
485              
486             sub make_shared_object_file {
487 60     60 0 154 my $self = shift;
488 60         110 my $ret;
489 60         182 my $srcn1 = $self->{SRCNAME};
490 60         506 my $fname1 = $self->{FNAME};
491 60         99 my $i = 0;
492 60         95 my $max = 20; # allow $max renamed files
493 60         896 while ( -f $self->{SONAME} ) { # this is important to avoid user side bugs
494 34         92 $i++;
495 34         94 my $so = $self->{SONAME};
496 34         87 $self->{FNAME} = $fname1 . $i;
497 34         97 $self->make_build_names();
498             # warn "Levmar::Func::make_shared_object_file: $so exists. Trying " . $self->{SONAME};
499 34 50       435 last if $i > $max;
500             }
501 60         171 my $srcn = $self->{SRCNAME};
502 60         111 my $objn = $self->{OBJNAME};
503 60         102 my $sobjn = $self->{SONAME};
504 60         125 my $fname = $self->{FNAME};
505 60 50       227 if ( $i > $max ){
    100          
506 0         0 die 'Levmar::Func::make_shared_object_file: Too many renamed files in '. $self->{DIR} . ' try cleaning.';
507             }
508             elsif ($i > 0) {
509 21 50       700 if ( rename($srcn1,$srcn) == 0 ) {
510 0         0 die "Levmar::Func::make_shared_object_file: Faile to rename $srcn1 to $srcn";
511             }
512             }
513             # my $mkobjstr = $self->{MKOBJ} ." -o $objn $srcn";
514 60         135 my $mkobjstr = $self->{MKOBJ};
515 60         329 $mkobjstr =~ s/\%c/$srcn/g;
516 60         223 $mkobjstr =~ s/\%o/$objn/g;
517 60         195 $ret = do_system($mkobjstr, $self); # compile c to o
518 60         2387 deb "Levmar::Func::make_shared_object_file: compile returned '$ret'";
519 60 50       433 if ( $ret != 0) { # zero is success
520 0         0 warn "Levmar::Func::make_shared_object_file: Compiling '$srcn' failed.";
521 0         0 return 0;
522             }
523 60         861 $self->{MKOBJSTR} = $mkobjstr;
524 60         614 my $sostr = $self->{MKSO};
525 60         1659 $sostr =~ s/\%s/$sobjn/g;
526 60         804 $sostr =~ s/\%o/$objn/g;
527 60         548 $ret = do_system($sostr, $self); # make so from o
528 60         2297 deb "Levmar::Func::make_shared_object_file: '$sostr' make so from o returned '$ret'";
529 60 50       415 if ( 0 != $ret ) {
530 0         0 warn "Levmar::Func::make_shared_object_file: Making shared library '$sobjn' failed.";
531 0         0 return 0;
532             }
533 60         1988 $self->{SOSTR} = $sostr;
534             }
535              
536             #### Some methods to return information
537             # get compiler strings
538             sub get_cc_str {
539 1     1 0 23 my $self = shift;
540 1         43 return ($self->{MKOBJSTR}, $self->{SOSTR});
541             }
542              
543             sub get_fpoint {
544 0     0 0 0 my $self = shift;
545 0         0 $self->{FPOINTER};
546             }
547              
548             sub get_jacpoint {
549 0     0 0 0 my $self = shift;
550 0         0 $self->{JPOINTER};
551             }
552              
553             sub get_fit_pointers {
554 91     91 0 205 my $self = shift;
555             ($self->{FPOINTER},
556             $self->{SFPOINTER},
557             $self->{JPOINTER},
558 91         548 $self->{SJPOINTER});
559             }
560              
561             sub get_file_names {
562 2     2 0 60 my $self = shift;
563 2         15 return ($self->mfqp('SRCNAME'),
564             $self->mfqp('OBJNAME'),
565             $self->mfqp('SONAME'));
566             }
567              
568             # remove generated o, and C files
569             # Well, don't remove so file.
570             sub clean_files {
571 58     58 0 163 my $self = shift;
572 58         124 my $cnt = 0;
573 58         173 my $srcn = $self->mfqp('SRCNAME'); # fully qualified names
574 58         196 my $objn = $self->mfqp('OBJNAME');
575 58         213 foreach my $k ( qw ( OBJNAME )) { # soname needs to be there
576 58         180 my $fn = $self->mfqp($k);
577 58 50       852 if (-e $fn) {
578 58 50       651 if ( not -f $fn ) {
579 0         0 warn "Levmar::Func::clean_files : Object file '$fn' not a file. Not deleting";
580             }
581             else {
582 58         493 $cnt = munlink $fn;
583 58 50       385 if ( $cnt < 1) {
584 0         0 warn "Levmar::Func::clean_files : cnt $cnt: Failed to delete object file '$fn'";
585             }
586             }
587             }
588             }
589 58 50       767 if ( -e $srcn ) {
590 58 50       636 if ( not -f $srcn ) {
591 0         0 warn "Levmar::Func::clean_files: Source file '$srcn' not a file. Not deleting";
592             }
593 58 50       4037 open my $srch , '<' ,
594             $srcn or die "Levmar::Func::clean_files : Can't open C source file '$srcn' for reading";
595 58         199 my $closed = 0;
596             # weird stack bug present when using implicit $_ rather than $line.
597             # A function that calls levmar_func sometimes has an item in arg stack
598             # replaced by the first line read here.
599 58         1688 while (my $line = <$srch>) {
600 72 100       1108 next if $line =~ /^\s*$/;
601 58 100       338 if ($line =~ /\/\* This file automatically/) {
602 44         647 close($srch);
603 44         135 $closed = 1;
604 44         93 $cnt = 0;
605 44         135 $cnt = munlink $srcn;
606 44 50       227 warn "Levmar::Func::clean_files: cnt $cnt: Failed to delete source file '$srcn'"
607             if $cnt < 1;
608 44         122 last;
609             }
610 14         57 last; # only check up to first non-blank line
611             }
612 58 100       623 close($srch) unless $closed == 1;
613             }
614             }
615              
616             # Improve effiency after this is well tested by getting all four
617             # symbols at once.
618              
619             sub load_fit_library {
620 60     60 0 455 my $self = shift;
621 60         548 my $so = $self->mfqp('SONAME');
622 60         328 my $fn = $self->{NAME};
623 60         448 my $jn = $self->{JACNAME};
624 60 50       1464 die "Levmar::Func::load_fit_library : Can't find dynamic library file '$so'" unless -e $so;
625 60         248 my ($func_pointer, $jac_pointer, $lib_handle, $error_message)=
626             (0,0,0,0);
627 60         673 my ($sfunc_pointer, $sjac_pointer) = # single precision
628             (0,0);
629 60         790 ($func_pointer, $lib_handle, $error_message) =
630             open_and_find($so,$fn);
631 60         453 ($sfunc_pointer, $lib_handle, $error_message) = # single precision
632             open_and_find($so,'s'.$fn);
633 60 50       291 if ( $error_message ne '' ) {
634 0         0 warn "Levmar::Func::load_fit_library: Failed to load dynamic library '$so'\n".
635             " and find fit func '$fn'.\n dlopen:'$error_message'";
636 0         0 return 0;
637             }
638 60 100 66     976 if ( defined $jn and $jn ne '') {
639 58         219 ($jac_pointer, $lib_handle, $error_message) =
640             open_and_find($so,$jn);
641 58 50       342 if ( $error_message ne '' ) {
642 0         0 warn "Levmar::Func::load_fit_library: Failed to load dynamic library '$so' and find jacobian '$jn'.\n".
643             " dlopen:'$error_message' ";
644             }
645             else {
646 58         495 $self->{JPOINTER} = $jac_pointer;
647             }
648 58         365 ($sjac_pointer, $lib_handle, $error_message) =
649             open_and_find($so, 's' . $jn);
650 58 50       213 if ( $error_message ne '' ) {
651 0         0 warn "Levmar::Func::load_fit_library: Failed to load dynamic library '$so' and find jacobian '$jn'.\n".
652             " dlopen:'$error_message' ";
653             }
654             else {
655 58         311 $self->{SJPOINTER} = $sjac_pointer;
656             }
657              
658             }
659 60         453 $self->{FPOINTER} = $func_pointer;
660 60         302 $self->{SFPOINTER} = $sfunc_pointer;
661 60         418 $self->{LIBHANDLE} = $lib_handle;
662             }
663              
664              
665             # End of methods
666             # (Actually there are some more methods near the bottom
667             # that are close to the corresponding pp_defs)
668             ########################################
669             # Non-methods below here
670              
671             # should return 0 on success
672             sub do_system {
673 120     120 0 454 my ($c,$f) = @_;
674 120 50       392 print STDERR $c,"\n" if $f->{FVERBOSE};
675 120         6795852 system $c;
676             }
677              
678             sub munlink {
679 155     155 0 399 my $f = shift;
680 155         224 my $cnt;
681 155         468 my $sf = "'$f'";
682 155 50       1700 if ( not -e $f ) {
683 0         0 prwarn "munlink: $sf does not exist";
684 0         0 return 0;
685             }
686 155 50       1594 if ( not -f $f ) {
687 0         0 prwarn "munlink: $sf is not a file. Not removing.";
688 0         0 return 0;
689             }
690 155         6816 $cnt = unlink $f;
691 155 50       718 if (not $cnt > 0) {
692 0         0 prwarn "munlink: Can't unlink exisiting file $sf";
693             }
694 155         438 return $cnt;
695             }
696              
697             # Turn a function description into C source
698             # !care! I disabled NiceSlice, because it erroneously saw
699             # slicing in this piddle-less routine. But I was not using it
700             # anyway. (parser is rewritten, maybe not a problem anymore.)
701             sub generate_C_source {
702 46     46 0 189 my ($self, $fdef) = @_;
703 46         210 my $funcname = ''; # this one is returned
704 46         145 my $jacname = ''; # this one is returned
705             # Do this first now send t -> t[i], x -> x[i], p3 -> p[3]
706             # Probably a better way than doing this in a loop
707             # but overlapping matchin patterns do not work with global flag
708             # t --> t[i]
709              
710             # I tried to substitutions on $fdef vs on each line. Not much difference.
711 46         135 my $defs = {};
712 46         134 my ($lines,$def, $loopf, $noloopf, $name);
713 46         279 my (@flines) = split(/\n/, $fdef);
714 46         118 $lines = [];
715 46         79 my $prefunc = $lines;# lines before any func def
716 46         198 foreach my $oneline (@flines) { #break code into functions
717 649 100       1252 next if $oneline =~ /^\s*end\s+(function|jacobian)\s*/;
718 641 100       1641 if ( $oneline =~ /^\s*(function|jacobian)\s*(\w*)\s*$/ ) { # func declaration
719 90         548 $name = $2;
720 90 100       234 $name = "func" unless $name ne '';
721 90         260 my $type = $1;
722 90 100 100     604 $name = "jac" . $name if $type eq 'jacobian' and not $name =~ /^jac/ ;
723 90         345 $def = $defs->{$name} = {};
724 90         350 $def->{type} = $type;
725 90         172 $lines = [];
726 90         171 $def->{loop} = $lines;
727 90         132 $noloopf = 0;
728 90         119 $loopf = 0;
729 90         200 next;
730             }
731 551 100       1452 if ( $oneline =~ /^\s*noloop/ ) { # don't want any implicit loop
    100          
732 22         48 $def->{preloop} = $lines;
733 22         32 $def->{loop} = undef;
734 22         32 $noloopf = 1;
735 22         32 next;
736             }
737             elsif ( $oneline =~ /^\s*loop/ ) { # start implicit loop
738 40         118 $def->{preloop} = $lines;
739 40         79 $lines = [];
740 40         92 $def->{loop} = $lines;
741 40         55 $loopf = 1;
742 40         71 next;
743             }
744             else {
745 489         1176 push @$lines, "" .$oneline ."\n";
746             }
747             }
748              
749            
750 46 50       140 if ( defined $self->{TESTSYNTAX} ) {
751 0         0 my $st = '';
752 0 0       0 if ( @$prefunc > 0) {
753 0         0 $st .= ":PREFUNC: lines:" . scalar(@{$prefunc}). "\n";
  0         0  
754 0         0 $st .= join("\n",@{$prefunc}). "\n";
  0         0  
755             }
756 0         0 foreach my $name ( keys %$defs ) {
757 0         0 my $d = $defs->{$name};
758 0         0 $st .= "NAME: $name, TYPE: " . $d->{type};
759 0 0       0 if (defined $d->{preloop}) {
760 0         0 $st .= ":PRELOOP: lines:" . scalar(@{$d->{preloop}}). "\n";
  0         0  
761 0         0 $st .= join("\n",@{$d->{preloop}}). "\n";
  0         0  
762             }
763 0 0       0 if (defined $d->{loop}) {
764 0         0 $st .= ":LOOP: lines:" . scalar(@{$d->{loop}}). "\n";
  0         0  
765 0         0 $st .= join("\n",@{$d->{loop}}). "\n";
  0         0  
766             }
767             }
768 0         0 $self->{SYNTAXRESULTS} = $st;
769             }
770              
771 46         92 my $end_function = "\}\n\n";
772 46         168 my $end_loop = " \}\n";
773 46         406 my $start_loop = { 'jacobian' => " for(i=j=0; i
774             'function' => " for(i=0; i
775              
776             # my $dtype = $self->{TYPE};
777 46         117 my $dtype = 'FLOAT';
778 46         599 my $start_function = {
779             'jacobian' => "void JACFUNNAME($dtype *p, $dtype *d, int m, int n, $dtype *t)\n\{\n".
780             " int i,j;\n",
781             # " $dtype *t = ($dtype *) data;\n",
782             'function' => "void FITFUNNAME($dtype *p, $dtype *x, int m, int n, $dtype *t)\n\{\n".
783             " int i;\n" };
784             # " $dtype *t = ($dtype *) data;\n" };
785 46         237 my $kode =
786             "/* This file automatically created and deleted. Do not edit. */\n" .
787             "#include\n#include \n\n" .
788             join('',@$prefunc);
789              
790              
791 46         99 my $kode1 = '';
792              
793 46         209 foreach my $name ( keys %$defs ) {
794 90         190 my $d = $defs->{$name};
795 90         142 my ($loop, $preloop, $loopcode);
796 90         168 my $type = $d->{type};
797 90 100       230 $funcname = $name if $type eq 'function';
798 90 100       233 $jacname = $name if $type eq 'jacobian';
799 90 100       225 if ( defined $d->{loop} ) {
800 68         99 $loopcode = join("", @{$d->{loop} });
  68         303  
801 68 100       275 if ( $loopcode =~ /^\s*$/ ) { # loop code is whitespace
802 6         13 $loopcode = undef; # so don't print it
803             }
804             else {
805 62         119 $loop = $d->{loop};
806             }
807             }
808 90 100       206 $preloop = $d->{preloop} if defined $d->{preloop};
809              
810             # $kode1 .= sprintf($start_function->{$type},$name);
811 90         273 $kode1 .= sprintf($start_function->{$type}, '');
812 90 100       281 if (defined $preloop ) {
813 62         146 foreach (@$preloop) {
814             # p5 --> p[5]
815 259         1094 while ($_ =~ s/([^\w]|^)p(\d+)([^\w\[])/$1p[$2]$3/g){}
816 259 100       504 if ( $type eq 'function' ) {
    50          
817             # x7 -- > x[7]
818 62         356 while($_ =~ s/([^\w]|^)x(\d+)([^\w\[])/$1x[$2]$3/g){}
819             }
820             elsif ( $type eq 'jacobian' ) {
821             # d3[6] -> d[ 3+ (n-1)*6], no! [3+m*6] is correct
822 197         564 while($_ =~ /([^\w]|^)d(\d+)\[(\d+)\]/ ) {
823 140         251 my $i = "$2+m*$3" ;
824 140         742 $_ =~ s/([^\w]|^)d\d+\[\d+\]/$1d[$i]/;
825             }
826             }
827             }
828 62         199 $kode1 .= join('',@$preloop);
829             }
830 90 100       195 if ( defined $loop ) {
831 62         127 $kode1 .= $start_loop->{$type};
832 62         128 foreach ( @$loop ) {
833             # t -- > t[i]
834 182         1100 while($_ =~ s/([^\w]|^)t([^\w\[])/$1t[i]$2/g){}
835             # p5 --> p[5]
836 182         1090 while ($_ =~ s/([^\w]|^)p(\d+)([^\w\[])/$1p[$2]$3/g){}
837 182 100       429 if ( $type eq 'function' ) {
    50          
838             # x -> x[i]
839 51         298 while($_ =~ s/([^\w]|^)x([^\w\[])/$1x[i]$2/g){}
840             }
841             elsif ( $type eq 'jacobian' ) {
842 131 100       417 if ( /^\s*d\d+\[?i?\]?(.+)/ ) {
843 71         243 my $line = $1;
844 71         240 $line =~ s/\s*//; # strip space
845 71         210 $_ = " d[j++] $line\n";
846             }
847             }
848             else {
849 0         0 warn "Levmar::Func::generate_C_source: Function type neither 'function' nor 'jacobian'";
850             }
851             }
852 62         221 $kode1 .= join('',@$loop) . $end_loop;
853             }
854 90         173 $kode1 .= $end_function;
855             } #foreach my $name ..
856 46 50       408 my $export = $^O =~ /MSWin32/i ? '__declspec (dllexport)' : '';
857 46         599 $kode .= "
858             #define FLOAT double
859             #define JACFUNNAME $export $jacname
860             #define FITFUNNAME $export $funcname
861             " . $kode1 .
862             "
863             #undef FLOAT
864             #undef JACFUNNAME
865             #undef FITFUNNAME
866             #define FLOAT float
867             #define JACFUNNAME $export s$jacname
868             #define FITFUNNAME $export s$funcname
869             " . $kode1;
870 46         511 return ($funcname,$jacname,$kode);
871             } # end sub generate_C_source {
872              
873             # load shared library with fit function and find a symbol
874             # (pointer to fit function or jacobian in our case.)
875             # $lib_name : name of library file , eg "./func.so"
876             # $func_name : name of function, eg "square"
877             # $func_pointer : value of C level pointer to $func_name, cast to int
878             # $lib_handle : same, but for pointer to library
879             sub open_and_find {
880 236     236 0 685 my ($lib_name, $func_name) = @_;
881 236         385 my $lib_handle = 0;
882 236         310 my $func_pointer = 0;
883 236         292 my $nchar = 1000; # avoid buffer overun by sending this number to memccpy
884 236         1067 my $error_message = "." x $nchar;
885 236         1110 deb "call_open_and_find for lib $lib_name, func $func_name.";
886             # print STDERR "Nargs 1 ", scalar(@_) , "\n";
887 236         9847 my @res = call_open_and_find($lib_name, $func_name, $lib_handle,
888             $func_pointer, $error_message , $nchar);
889             # print STDERR "Nargs 2 ", scalar(@_) , "\n";
890             # print STDERR ("call_open_and_find returned ", scalar(@res), " items\n.");
891             # print STDERR (@res),"\n";
892 236         1276 return ($func_pointer, $lib_handle, $error_message);
893             # return ($func_pointer, $lib_handle, '');
894             }
895              
896             sub close_shared_object_file {
897 212     212 0 400 my ($lib_handle) = @_;
898 212         315 my $nchar = 1000; # avoid buffer overun by sending this number to memccpy
899 212         476 my $error_message = "." x $nchar;
900 212         273 my $ret = 0;
901 212         474 deb "Closing so file.";
902             # print STDERR "Nargs 3 ", scalar(@_) , "\n";
903 212         4055 my @res = call_close_shared_object_file( $lib_handle, $ret, $error_message, $nchar);
904             # print STDERR "Nargs 4 ", scalar(@_) , "\n";
905             # print STDERR ("close shared returned ", scalar(@res), " items\n.");
906             # print STDERR (@res),"\n";
907 212         644 return ($ret, $error_message);
908             }
909              
910             #-----------------------------------------
911             # Some methods to call the functions
912              
913             # evaluate the function.
914             # Given parameters p and coordiante pdl t,
915             # return x(t;p) with x->dims == t->dims.
916             # The functions don't really have to have
917             # this form, but this is what we assume for
918             # this call.
919             sub call {
920 0     0 1   my $self = shift;
921 0           my ($p,$t) = @_; # pdls
922 0           my $x = zeroes($t);
923 0 0         if ($self->{FPOINTER} == 0) {
924 0           warn "Levmar::Func::call : No function loaded.";
925 0           return PDL->null;
926             }
927 0           _callf(topdl($p),$t,$x, $self->{FPOINTER});
928 0           return($x);
929             }
930              
931             # call jacobian and get back 2-d pdl
932             # return jac(m,n) = jacfunc(p(m),t(n))
933             sub jac_of_t {
934 0     0 0   my $self = shift;
935 0           my ($p,$t) = @_; # pdls
936 0 0         if ($self->{JPOINTER} == 0) {
937 0           warn "Levmar::Func::jac_of_t: No jacobian function loaded.";
938 0           return PDL->null;
939             }
940 0           my @dims = dims($t);
941 0           my $jac = zeroes($p->type, $p->nelem,@dims);
942 0 0         return 0 unless ref($jac) =~ /PDL/;
943 0           _callj($p,$t,$jac, $self->{JPOINTER});
944 0           return($jac);
945             }
946              
947             # treat array of derivatives as 1-d, just at the
948             # supplied c routines do. For debugging.
949             # return jac(m*n) = jacfunc(p(m),t(n))
950             sub jac_of_t1 {
951 0     0 0   my $self = shift;
952 0           my ($p,$t) = @_; # pdls
953 0 0         if ($self->{JPOINTER} == 0) {
954 0           warn "Levmar::Func::jac_of_t1: No jacobian function loaded.";
955 0           return PDL->null;
956             }
957 0           my @dims = dims($t);
958 0           foreach (@dims) { $_ *= $p->nelem}
  0            
959 0           my $jac = zeroes($p->type, @dims);
960 0 0         return 0 unless ref($jac) =~ /PDL/;
961 0           _callj1($p,$t,$jac, $self->{JPOINTER});
962 0           return($jac);
963             }
964              
965              
966              
967              
968              
969             *_callf = \&PDL::Fit::Levmar::Func::_callf;
970              
971              
972              
973              
974              
975             *_callj = \&PDL::Fit::Levmar::Func::_callj;
976              
977              
978              
979              
980              
981             *_callj1 = \&PDL::Fit::Levmar::Func::_callj1;
982              
983              
984              
985             ;
986              
987              
988             =head1 AUTHORS
989              
990             Copyright (C) 2006 John Lapeyre.
991             All rights reserved. There is no warranty. You are allowed
992             to redistribute this software / documentation under certain
993             conditions. For details, see the file COPYING in the PDL
994             distribution. If this file is separated from the PDL distribution,
995             the copyright notice should be included in the file.
996              
997             =cut
998              
999              
1000              
1001              
1002              
1003             # Exit with OK status
1004              
1005             1;
1006              
1007