http://www.perlmonks.org?node_id=60513

rbi has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I have translated a program from FORTRAN to perl.
When I run it as FORTRAN-compiled executable, it is at least 4 times faster than perl, on input files of about 120000 records.
Since I'm a beginner, I'm sure the perl I've written is not very good... In particular, in (1) I prepare a $tmp string through a loop to be printed. the subroutine decode might have problems too... I've replicated the FORTRAN code and there I compute the exponential, but maybe string manipulation can do much better...
Thanks in advance for any corrections/suggestions
Roberto
# here some initialisation or operations on small # vectors .... $nvar = 9; .... foreach $k (1..$nvar) { $record = <IN>; chomp($record); @values = &decode($record,$nt,$val_m); foreach $it (1..$nt) { if ($values[$it-1] < 0 and $values[$it-1] != $val_m) + { die "error: found negative value.\n"; } $field[$it-1][$k-1] = $values[$it-1]; } } foreach $it (1..$nt) { $tmp = sprintf "%s", $some_vector[$it-1]; foreach $k (1..$nvar) { $tmp = $tmp.sprintf " %11.4E", $field[$it-1][$k-1]; # (1) in Fortran this should be a single write intruction with FORMAT ('i4.4,4i2.2,9(1x,1pe11.4))') } $tmp = $tmp."\n"; print OUT $tmp; } # (2) this is seems to go the same speed as the one above ... # # foreach $it (1..$nt) { # printf OUT "%s", $some_vector[$it-1]; # foreach $k (1..$nvar) { # printf OUT " %11.4E", $field[$it-1][$k-1]; # } # print OUT "\n"; # } .... sub decode() { # this routine should decode the $record where there are a series of # $nt decimal fractions in the first part of the string # (5*$nt characters),and exponents in the last decimal fractions are # written as 5-digit integers, and must be multiplied by 10.**(-5), # negative exponents are coded as 2-digit odd numbers, while positive # exponents are even numbers # 12345...01... where 01 are characters $nt*5 and $nt*5+1 will give # 1.234E-01 my $record = shift(); my $nt = shift(); my $val_missing = shift(); $lmina = 0; $lminb = 5 * $nt; foreach $it (1..$nt) { $ia = substr($record,$lmina,5); $ib = substr($record,$lminb,2); if ($ia == 0 and $ib == 99) { $values[$it-1] = $val_missing; } else { $x1 = $ia * 10.**(-5); if (($ib % 2) == 0) { $x2 = 10.**($ib/2); } else { $x2 = 10.**(-($ib+1)/2); } $values[$it-1] = $x1 * $x2; } $lmina = $lmina + 5; $lminb = $lminb + 2; } return @values; }