#!/usr/bin/env perl

# Take the output of reduce.pl and verify that the given matrix represents
# the sign pattern using exact rational arithmetic.

use Modern::Perl 2018;
use Test::More;

use Math::BigRat lib => 'GMP';
use Matrix::Simple;
use Algorithm::Combinatorics qw(subsets);

my $n = shift // die 'need dimension';

sub matrix {
    my $n = shift;
    my $A = [ map [ map 0, 1 .. $n ], 1 .. $n ];
    for (my $i = 0; $i < $n; $i++) {
        for (my $j = $i; $j < $n; $j++) {
            $A->[$i][$j] = $A->[$j][$i] = Math::BigRat->new(shift);
        }
    }
    $A
}

sub submatrix {
    my ($A, $I, $J) = @_;
    [ map { [ $_->@[@$J] ] } $A->@[@$I] ]
}

sub pr {
    my ($A, $K) = @_;
    return 1 if @$K == 0;
    det submatrix($A, $K, $K)
}

sub signs {
    my $A = shift;
    my $n = @$A;
    my @signs;
    for my $k (0 .. $n) {
        for my $K (subsets([0 .. $n-1], $k)) {
            my $v = pr($A, $K);
            push @signs, ($v < 0 ? '-' : ($v > 0 ? '+' : '0'));
        }
    }
    join '', @signs
}

my $i = 1;
while (<<>>) {
    chomp;
    die "can't parse record '$_'" unless /(.+): (\d+) \[(.+)\]/;
    my ($s, undef, $nums) = ($1, $2, $3);
    my $t = signs matrix($n, split /, /, $nums);
    is $t, $s, "entry #$i";
    $i++;
}
done_testing;
