-# Returns the argument value incremented by one unit in its final
-# decimal place.
-sub increment {
- local ($_) = @_;
- my ($last_digit, $i);
- for ($i = 0; $i < length $_; $i++) {
- my ($c) = substr ($_, $i, 1);
- last if ($c eq 'E');
- $last_digit = $i if $c =~ /[0-9]/;
- }
- return $_ if !defined $last_digit;
- for ($i = $last_digit; $i >= 0; $i--) {
- my ($c) = substr ($_, $i, 1);
- if ($c eq '9') {
- substr ($_, $i, 1) = '0';
- } elsif ($c =~ /[0-8]/) {
- substr ($_, $i, 1) = chr (ord ($c) + 1);
- last;
- }
- }
- $_ = "1$_" if $i < 0;
- return $_;
-}
+n_exact = 0
+bad_round = 0
+approximate = 0
+spss_wtf1 = 0
+spss_wtf2 = 0
+lost_sign = 0
+errors = 0
+line_number = 0
+for a, b in itertools.zip_longest(open(args[0], 'r'),
+ open(args[1], 'r')):
+ line_number += 1
+ if not b:
+ print("Extra lines in %s" % args[0])
+ errors += 1
+ break
+ if not a:
+ print("Extra lines in %s" % args[1])
+ errors += 1
+ break
+
+ a = a.rstrip('\r\n')
+ b = b.rstrip('\r\n')
+ if a == b:
+ n_exact += 1
+ if not a.isspace() and ':' not in a:
+ expr = a.strip()
+ else:
+ fmt, a_out = re.match(r'^ (.*): "(.*)"$', a).groups()
+ b_fmt, b_out = re.match(r'^ (.*): "(.*)"$', b).groups()
+ assert fmt == b_fmt
+ assert a_out != b_out
+
+ if not exact:
+ if increment(a_out) == b_out or increment(b_out) == a_out:
+ approximate += 1
+ continue
+ if spss:
+ if re.search(r'0.*0', a_out) and not re.search(r'[1-9]', a_out):
+ bad_round += 1
+ continue
+ elif '*' in a_out and len(a_out.strip('*')):
+ spss_wtf1 += 1
+ continue
+ elif (expr.startswith('-')
+ and re.fullmatch(r'\*+', a_out)
+ and re.match(r'-\d(\.\d*#*)?E[-+]\d\d\d', b_out)
+ and fmt.startswith('E')):
+ spss_wtf2 += 1
+ continue
+ elif (expr.startswith('-')
+ and (('-' not in a_out
+ and re.search(r'[1-9]', a_out)
+ and '-' in b_out)
+ or (a_out.isdigit()
+ and re.fullmatch(r'\*+', b_out)))):
+ lost_sign += 1
+ continue
+
+ if verbose > 1:
+ print('%s: %s in %s: expected "%s", got "%s'
+ % (line_number, expr, fmt, a_out, b_out))
+ errors += 1
+if verbose:
+ print("%s exact matches" % n_exact)
+ print("%s errors" % errors)
+ if not exact:
+ print('%s approximate matches' %approximate)
+ if spss:
+ print("%s bad rounds" % bad_round)
+ print("%s SPSS WTF 1" % spss_wtf1)
+ print("%s SPSS WTF 2" % spss_wtf2)
+ print("%s lost signs" % lost_sign)
+sys.exit(1 if errors else 0)