#!/usr/bin/env python

#-----------------------------------------------------------------------------
# floatcheck: Check files within floating point accuracy
#-----------------------------------------------------------------------------
#
#   Copyright (C) 2009
#   Associated Universities, Inc. Washington DC, USA.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#   Correspondence concerning AIPS++ should be addressed as follows:
#          Internet email: casa-feedback@nrao.edu.
#          Postal address: AIPS++ Project Office
#                          National Radio Astronomy Observatory
#                          520 Edgemont Road
#                          Charlottesville, VA 22903-2475 USA
#

# This script compares two text files for equality.
# If numbers mismatch, it is checked if they are near each other.
# The tolerance can be given as the third argument; it defaults to 1e-5.

import re
import sys

def splitfile (filename, regexp):
    f = open(filename, 'r')
    res = []
    for line in f:
        # Make sure numbers are separated by blanks.
        line = regexp.sub (r' \g<grp> ', line)
        res.extend (line.split())
    f.close()
    return res;

def near (val1, val2, tol):
    # ok if both close to zero.
    if abs(val1) <= tol*1e-10  and  abs(val2) <= tol*1e-10:
        return True;
    if (val1>0) != (val2>0):
        return False
    return abs(val1-val2) <= tol*max(abs(val1),abs(val2))

def main(argv=None):
    if argv is None:
        argv = sys.argv
    if len(argv) < 3:
        sys.stderr.write ('run as:   floatcheck.py file1 file2 [tolerance]\n')
        return 1
    tol = 1e-5;
    if len(argv) > 3:
        tol = float(argv[3])

    # Regular expression for an integer or float number.
    numre = re.compile (r'(?P<grp>[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+|[0-9]+)([ed][+-][0-9]+)?)', re.IGNORECASE)

    # Split file in separate values.
    res1 = splitfile (argv[1], numre);
    res2 = splitfile (argv[2], numre);

    # Keep list of possible numbers to compare.
    num1 = []
    num2 = []
    # Compare res1 and res2 for equality.
    # Mismatching numbers are kept and compared later.
    if len(res1) != len(res2):
        return 1      # mismatch
    for i in range(len(res1)):
        if res1[i] != res2[i]:
            if numre.sub('', res1[i]) != ''  or  numre.sub('', res2[i]) != '':
                return 1
            num1.append (res1[i])
            num2.append (res2[i])

    # Now compare if numbers are more or less equal.
    for i in range(len(num1)):
        val1 = float(num1[i])
        val2 = float(num2[i])
        if not near(val1, val2, tol):
            return 2
    
    return 0

if __name__ == "__main__":
    sys.exit(main())
