#!/usr/bin/env perl $^W=1; # # take output of diff and check fields for numerical equivalency: # numerical fields are considered equivalent if # 1) they agree to within $tol (which can be specified as a cmd-line option) # 2) they contain $numLeadDig identical leading digits, starting with 0. # 3) their magnitude is smaller than $zeroCutoff # or # 4) the numbers differ by 360 (degrees- this one is ugly) # # CDS 2/27/01 # use strict; use POSIX; my $tol = 0.01; my $numLeadDig = 3; my $zeroCutoff = 5e-9; while (scalar(@ARGV)>0 && $ARGV[0] =~ /^-/) { if ($ARGV[0] eq "-tol") { shift @ARGV; $tol = shift @ARGV; } } my $exit=0; while () { if ( /^([0-9,]+)c\1$/ ) { my $head = $_; my $cnt=0; my @lines1 = (); my @lines2 = (); while ( ) { /^---/ && last; $lines1[ $cnt++ ] = $_; } for (my $i=0 ; $i<$cnt ; $i++) { $_ = ; $lines2[ $i ] = $_; } my $noDiffs=1; for (my $i=0 ; $i<$cnt ; $i++) { my $l1 = $lines1[$i]; my $l2 = $lines2[$i]; $l1 =~ s/(\s|[,()\[\]<>%]|=)+/,/g; $l2 =~ s/(\s|[,()\[\]<>%]|=)+/,/g; my @fields1 = split(/\,/,$l1); my @fields2 = split(/\,/,$l2); if (@fields1 != @fields2) { ($noDiffs=0); #print STDERR "different num fields for:\n"; #print STDERR "\t@fields1\n"; #print STDERR "\t@fields2\n"; last; } # Python True/False <--> 1/0 equivalency for (my $j=1 ; $j<@fields1 ; $j++) { ($fields1[$j] eq "True" ) && ($fields1[$j] = 1); ($fields1[$j] eq "False") && ($fields1[$j] = 0); ($fields2[$j] eq "True" ) && ($fields2[$j] = 1); ($fields2[$j] eq "False") && ($fields2[$j] = 0); } #packed floating point numbers for (my $j=1 ; $j<@fields1 ; $j++) { if ( $fields1[$j] =~ /[ed][+-][0-9][0-9]-/i ) { my $tmp1 = $fields1[$j]; my $tmp2 = $fields2[$j]; splice(@fields1,$j,$j); splice(@fields2,$j,$j); while ( $tmp1 =~ s/(-?[0-9]\.[0-9]*[ed][+-][0-9][0-9])-/-/i ) { push( @fields1 , $1 ); } while ( $tmp2 =~ s/(-?[0-9]\.[0-9]*[ed][+-][0-9][0-9])-/-/i ) { push( @fields2 , $1 ); } } } #print STDERR "0: fields1: @fields1\n"; #print STDERR "0: fields2: @fields2\n"; #Python complex numbers for (my $j=0 ; $j<@fields1 ; $j++) { if ( $fields1[$j] =~ /j$/ ) { my $tmp1 = $fields1[$j]; my $tmp2 = $fields2[$j]; $tmp1 =~ /(-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?)([+-].*)j$/; #print STDERR "nums: $1 $4\n"; splice(@fields1,$j,1,$1); push( @fields1 , $4 ); $tmp2 =~ /(-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?)([+-].*)j$/; splice(@fields2,$j,1,$1); push( @fields2 , $4 ); } } #print STDERR "fields1: @fields1\n"; #print STDERR "fields2: @fields2\n"; # skip first field for (my $j=1 ; $j<@fields1 ; $j++) { if ( $fields1[$j] ne $fields2[$j] ) { if ( anum($fields1[$j]) && anum($fields2[$j]) ) { my $num1 = getNum( $fields1[$j] ); my $num2 = getNum( $fields2[$j] ); my $leadChars="AAA"; #invalid number my $numLeadDigm = $numLeadDig-1; ($num1 =~ /^[+-]?0\.\d{$numLeadDigm}/) && ($leadChars = $&); if ( # ugly: for angle fields (in degrees) abs(POSIX::fmod($num1-$num2,360)) > 0.5*$tol*abs($num1+$num2) && !($num2 =~ /^$leadChars/) && (abs($num1) > $zeroCutoff || abs($num2) > $zeroCutoff ) ) { $noDiffs=0; #print STDERR # "numbers differ2: $num1 $num2\n"; } } else { $noDiffs=0; # print STDERR # "not numbers: $fields1[$j] $fields2[$j]\n"; #print STDERR "numbers differ: $num1 $num2\n"; } } } } $noDiffs || diffFound($head,\@lines1,\@lines2); } else { print; $exit=1; } } exit($exit); sub diffFound { my ($head, $lines1, $lines2) = @_; $exit=1; print $head; my @lines1=@$lines1; for (my $i=0 ; $i<@lines1 ; $i++) { print $lines1[$i]; } print "---\n"; my @lines2=@$lines2; for (my $i=0 ; $i<@lines2 ; $i++) { print $lines2[$i]; } } sub anum { $_ = shift; return /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?([F|])?$/; } sub getNum { # just remove trailing characters $_ = shift; s/[F|]$//; return $_; }