#!/usr/bin/perl
# Generate the outer product table.  The basic idea is if the two terms have something in common, then the answer is 0.  If they have
# nothing in common, then merge them, keeping track of swaps to get the sign right.

@be = qw(S  EO E1 E2 E3 EI  EO1 EO2 EO3 EOI E12 E13 E1I E23 E2I E3I  EO12 EO13 EO1I EO23 EO2I EO3I E123 E12I E13I E23I EO123 EO12I EO13I EO23I E123I EO123I);
#@be = qw(S E1 E2 E3 E12 E23 E13 E123);
#@be = qw(S E1 E2 E12);

sub outTerms {
  my($aind,$bind) = @_;
  my($v) = 1;

  printf("\noutTerm($aind,$bind)\n");
  if ( $aind==0 ) {
  printf("  aind==0\n");
    $combInd=$bind;
  } elsif ($bind==0 ) {
  printf("  bind==0\n");
    $combInd=$aind;
  } else {
    my($r);
    @r=('E');
    printf("  r is initially @r\n");

    my @arr = split //,$be[$aind];
    my @brr = split //,$be[$bind];
    printf("  arr = @arr\n");
    printf("  brr = @brr\n");
    # remove leading E
    shift @arr;
    shift @brr;
    printf("  arr = @arr\n");
    printf("  brr = @brr\n");

    my($i);
    while ($#arr >= 0 && $#brr >= 0) {
	    # linearly dependent; return 0
	    printf("  ** arr[0] vs brr[0] $arr[0],$brr[0]\n");
      if ( $arr[0] eq $brr[0] ) {
      printf("  @arr[0] == @brr[0] => li.  Returning\n");
        return 0,-1,-1;
      }
      if ( $arr[0] eq 'O') {
	      printf("  A $arr[0] == 'O'\n");
        push(@r, shift(@arr));
      } elsif ( @arr[0] eq 'I') {
	      printf("  B @arr[0] == 'I'\n");
        if ( ($#brr+1)%2 == 1 ) {$v = -1*$v;}
	push(@r, @brr);	@brr = ();
	push(@r, shift(@arr));
	printf("  B r is @r\n");
	last;
      } elsif ( $brr[0] eq 'O' ) {
        if ( ($#arr+1)%2 == 1 ) {$v = -1*$v;}
	push(@r,shift(@brr));
      } elsif ( $brr[0] eq 'I' ) {
	      push(@r,@arr); @arr=();
	      push(@r,@brr); @brr=();
	last;
      } elsif ( $arr[0] < $brr[0] ) {
        printf("  $arr[0] < $brr[0] : push $arr[0] to r.\n");
        $r[$#r+1] = shift(@arr);
	printf("  arr @arr, brr @brr, $#arr\n");
      } else {
        printf("  last case\n");
        if ( ($#arr+1)%2 == 1 ) {$v = -1*$v;}
	printf("  old r is @r\n");
        $r[$#r+1] = shift(@brr);
	printf("  new r is @r\n");
        if ( $#brr < 0 ) {
		printf("   done\n");
          last;
        }
      }
	    printf("end of loop, $#arr\n");
    }
    printf("  End of loop r is @r\n");
    if ( $#arr >=0 ) { push(@r,@arr); }
    if ( $#brr >=0 ) { push(@r,@brr); }
    printf("$be[$aind]^$be[$bind] = @r\n");
    $ncv = join("",@r);
    printf("  ncv is $ncv, v is $v\n");
    my($idx);
    for ($idx=0; $idx<=$#be; $idx++) {
	    printf("$dxi: $be[$idx], $ncv\n");
      if ( $be[$idx] =~ $ncv ) { last; }
    }
    printf("  idx is $idx\n");
    $combInd = $idx;
  }
  printf("v $v, bind $bind, combInd $combInd\n");
  return $v,$bind,$combInd;
}


$sz = 32;
#$sz = 8;
my @array = map[(0) x $sz], 1 .. $sz;
my @Aarray = map[(-1) x $sz], 1 .. $sz;

#printf("array is @array\n");
#use Data::Dump 'dd'; dd @array;

for ($i=0; $i<$sz; $i++) {
  for ($j=0; $j<$sz; $j++) {
      printf(" $be[$i]^$be[$j]");
	my($v,$bi,$ci) = outTerms($i,$j);
	printf("bi $bi, ci $ci\n");
	if ( $bi != -1 && $ci != -1 ) {	$array[$ci][$bi] = $v; $Aarray[$ci][$bi]=$i;}
	printf("vls = $v,$bi,$ci\n");
#    if ( ($be[$i]=~/O/ && $be[$j]=~/O/) ||
#         ($be[$i]=~/1/ && $be[$j]=~/1/) ||
#         ($be[$i]=~/2/ && $be[$j]=~/2/) ||
#         ($be[$i]=~/3/ && $be[$j]=~/3/) ||
#         ($be[$i]=~/I/ && $be[$j]=~/I/) 
#          ) {
#        printf(" 0");
#    } else {
#        printf(" $be[$i]^$be[$j]");
        #[$v,$fi,$si] =
 #   }
  printf("\n");
  }
  printf("\n");
}

for ($i=0; $i<$sz; $i++) {
	for ($j=0; $j<$sz; $j++) {
		printf(" %3d ",$array[$i][$j]);
	}
	printf("\n");
}
printf("\n");
#use Data::Dump 'dd'; dd @array;

for ($i=0; $i<$sz; $i++) {
	for ($j=0; $j<$sz; $j++) {
		printf(" %3d ",$Aarray[$i][$j]);
	}
	printf("\n");
}

for ($i=0; $i<$sz; $i++) {
	for ($j=0; $j<$sz; $j++) {
		if ( $Aarray[$i][$j]>=0 ) {
			$a = $be[$Aarray[$i][$j]];
#			$a =~ s/E/A/;
#			$a =~ s/S/A0/;
			$a =~ s/S/scal/;
			if ( $array[$i][$j] < 0 ) {
				$a = "-" . $a;
			}
			printf(" %6s ",$a);
		} else {
			printf(" %6s ", 0);
		}
	}
	printf(";\n");
}
#use Data::Dump 'dd'; dd @Aarray;
