#! /usr/bin/perl -w
# $Id: numdiff,v 1.1 2003/06/25 16:54:49 oliver Exp $
# numdiff
# calculate difference of numeric fields in two structural identical
# files
# Time-stamp: <2003-06-25 17:59:59 oliver>


# subs

sub beautify {
    my @parms = @_;
    for (@parms) {
	# x=.123 -> x=0.123
	s/=\./=0\./;
	
	# 345} -> 345 } etc
	s/([0-9])}/$1 }/;
	s/{([-0-9])/{ $1/;

        # compress space
        tr/ \t,/ /s;

        # delete space at start or end
        s/ *$//;
        s/^ *//;

	# special nfp hacks
	s/EKS/EKS /g;
	}
    return wantarray ? @parms : $parms[0];
}

# no elaborate opt processing

$File1 = $ARGV[0];
$File2 = $ARGV[1];

# open files for reading

open (FILE1, "< $File1") or die "Could not open $File1, stopped ";
open (FILE2, "< $File2") or die "Could not open $File2, stopped ";


print "**************************************\n";
print "* difference: $File1 - $File2\n";
print "**************************************\n\n";     

# read in  files, line per line
# then work on each line

LINES: while ( defined ($line1=<FILE1>) && defined ($line2=<FILE2>) ) {
    chop $line1;
    chop $line2;

    # but it may contain x=.2 or x=0.2, and other oddities, so beautify
    $line1 = &beautify ($line1);
    $line2 = &beautify ($line2);

    # this split to workaround a bug in perl 580 with 'split [, ], $in' Error: Split loop
    # (needs help from beautify)
    @list1 = split / /, $line1;
    @list2 = split / /, $line2;
    
    # list1 is the masterlist. We assume the same structure in both files!

    # there are special id and iteration lines in nfp output. 
    # We keep these:
    if ( $line1 =~ /^(nf ----- )|( ----- Start iteration)/ ) {
	print "$line1\n";
	#... and look at the next line
	next LINES;
    }

    # for gromacs log files
    if ( $line1 =~ /^[[:space:]]*Step[[:space:]]+Time/ ) {
	print "$line1\n";
	# get the next line as well
	$line1=<FILE1>;
	$line2=<FILE2>;
	print $line1;
	#... and look at the next line
	next LINES;
    }

    for ($i = 0, $line_out = ""; $i < @list1; $i++) {
	# print "** field: $i   content 1/2: [$list1[$i]] / [$list2[$i]]\n"; 

	# check if field contains a number:
	# numbers: .23 -.23 0.23 0.23d-01 0.23e+3

	if ($list1[$i] =~ /^[.+-]?\d*[.]?\d*([eEdD][+-]\d+)?$/) {

	    # perl does not understand 1d-06 (FORTRAN double): numberify
	    $list1[$i] =~ s/[dD]/e/;
	    $list2[$i] =~ s/[dD]/e/;

	    $diff = $list1[$i] - $list2[$i];
	    $diff = ( $diff == 0 ? "." : (sprintf "[%g]", $diff) );
	    $line_out = "$line_out$diff ";
	}
	else {
	    # we hit a token

	    # do simple consistency check before proceeding
	    #
	    do { 
		print "$File1 out of sync with $File2 at tokens";
		print " [$list1[$i]] and [$list2[$i]]\n"; 
	        next LINES; 
	    }  unless ( $list1[$i] eq $list2[$i] ) ;
	    
	    # still in sync, so proceed
	    $line_out = "$line_out$list1[$i] ";
	}
    }
    print "$line_out\n";
}

close (FILE1);
close (FILE2);

exit;
