#!/usr/bin/env perl

# A very, extremely primitive comparator intended as a stop-gap tool
# until xyce_verify.pl can be adapted to handle AC analysis properly (a much
# harder task than this one).

# This script takes two file names, a "gold standard" and a file to test
# against that standard.

# It performs the following checks:

# - First, it compares the contents of the first line, presumed to be the 
#   header.  It checks that the columns present in the gold standard header
#   are also present in the test file.
# - It then reads both files into arrays, and checks that their sizes are
#   equal.
# - It then checks each line of the test array and makes sure that its
#   frequency value matches (to within a precision "$freqprec") the value
#   in the gold standard on that line.
# - Finally, it performs a point-wise error computation on each value
#   present on the line, requiring that each quantity in the test file be 
#   within 2% of the corresponding value in the gold standard.

use Carp;

$goldstandard=$ARGV[0];
$testfile=$ARGV[1];
$absprec=1e-6;
$absprec2=1e-6;
$freqprec=1e-6;  # .0001 percent
$relprec=2e-2;   # 2%

open(GSFILEH,$goldstandard) || croak "Could not open gold standard $goldstandard\n";
open(TESTFILEH,$testfile) || croak "Could not open test file $testfile\n";

@gsdata=ReadDataFile(GSFILEH,\@gsheaderdata);
@testdata=ReadDataFile(TESTFILEH,\@testheaderdata);


# Compare the headers.  For our purposes, FREQ and "frequency" are equivalent,
# as one is used by Xyce and the other by SPICE.
for ($i=0;$i<=$#gsheaderdata;$i++)
{
    $gsheaderdata[$i] =~ s/frequency/FREQ/;
    if ($gsheaderdata[$i] ne $testheaderdata[$i])
    {
        print STDERR "Header mismatch on field $i, GS has $gsheaderdata[$i], test has $testheaderdata[$i]\n";
        exit 1;
    }
}

# compare the number of entries:
if ($#gsdata != $#testdata)
{
    print "Test data file has max entry of $#testdata, gs has $#gsdata \n";
}

# Now compare every line's index
for ($i=0;$i<=$#gsdata;$i++)
{
    if ($gsdata[$i][0] != $testdata[$i][0])
    {
        print STDERR "Frequency mismatch on index $i! GS $gsdata[$i][1] test $testdata[$i][1]\n";
        exit 2;
    }
}

# Now compare every line's frequency
for ($i=0;$i<=$#gsdata;$i++)
{
    if ($gsdata[$i][1] != $testdata[$i][1])
    {
        if ($gsdata[$i][1] != 0)
        {
            if (abs($testdata[$i][1]-$gsdata[$i][1])/$gsdata[$i][1]>$freqprec)
            {
                print STDERR "Frequency mismatch on index $i! GS $gsdata[$i][1] test $testdata[$i][1]\n";
                exit 2;
            }
        }
        else
        {
            if ($testdata[$i][1]>$absprec)
            {
                print STDERR "Frequency mismatch on index $i! GS $gsdata[$i][1] test $testdata[$i][1]\n";
                exit 2;
            }
        }
    }
}

# now compare all the other data:
for ($i=0;$i<=$#gsdata;$i++)
{
    for ($j=2;$j<=$#{$gsdata[$i]};$j++)
    {
        if ($gsdata[$i][$j] != $testdata[$i][$j])
        {
            if (abs($gsdata[$i][$j]) > $absprec )
            {
                if (abs(($testdata[$i][$j]-$gsdata[$i][$j])/$gsdata[$i][$j])>$relprec)
                {
                    print STDERR "Data mismatch on column $j line index $i! GS $gsdata[$i][$j] test $testdata[$i][$j]\n";
                    exit 3;
                }
                else
                {
#                    print "Data match on column $j line index $i. ($gsdata[$i][$j] close enough to $testdata[$i][$j])\n";
                }
            }
            else
            {
                if (abs($gsdata[$i][$j]-$testdata[$i][$j])>$absprec2)
                {
                    print STDERR "Data mismatch on column $j line index $i! GS $gsdata[$i][$j] test $testdata[$i][$j]\n";
                    exit 3;
                }
                else
                {
#                    print "Data match on column $j line index $i. (gs is zero, test=$testdata[$i][$j]\n";
                }
            }
        }
        else
        {
#            print "Data match on column $j line index $i. ($gsdata[$i][$j]  to $testdata[$i][$j]\n";
        }
    }
}

sub ReadDataFile
{
    my ($fileh,$headerref)=@_;

    my $headread,$line;
    my @retarray;

    $headread=0;

    while ($line=<$fileh>)
    {
        chomp($line);
        if ($headread==0)
        {
            @$headerref=split(' ',$line);
            $headread=1;
        }
        else
        {
            push @retarray,[split(' ',$line)];
        }

    }

    return @retarray;
}
