/*
 * app_matrixproduct.cpp
 *
 *  Created on: Jan 4, 2011
 *      Author: anders
 */

#include "parser.h"
#include "printer.h"
#include "gfanapplication.h"
#include "matrix.h"

class MatrixProductApplication : public GFanApplication
{
public:
  SimpleOption optionTropical;
  SimpleOption optionNegate;
  SimpleOption optionSelectZero;
  SimpleOption optionSelectNegative;
  SimpleOption optionSelectPositive;
  bool includeInDefaultInstallation()
  {
    return false;
  }
  const char *helpText()
  {
    return "This program computes the product of two matrices.\n";
  }
  MatrixProductApplication():
    optionTropical("--tropical","Do the computation in the max-plus semi-ring."),
    optionNegate("--negate","Change the sign of a matrix instead."),
	optionSelectZero("--selectzero","Instead select rows of the first matrix contributing to zero-rows of the product."),
	optionSelectNegative("--selectnegative","Instead select rows of the first matrix contributing to negative rows of the product."),
	optionSelectPositive("--selectpositive","Instead select rows of the first matrix contributing to positive rows of the product.")
  {
    registerOptions();
  }

  const char *name()
  {
    return "_matrixproduct";
  }

  int main()
  {
    FileParser P(Stdin);

    IntegerMatrix A=rowsToIntegerMatrix(P.parseIntegerVectorList());
    if(optionNegate.getValue())
      pout<<(-A).getRows();
    else
      {
        IntegerMatrix B=rowsToIntegerMatrix(P.parseIntegerVectorList());

        if(optionSelectZero.getValue())
        {
        	IntegerMatrix AA=A;
        	int AAindex=0;
        	for(int i=0;i<A.getHeight();i++)
        	{
				auto C=A.submatrixRows(i,i+1)*B;
				bool good=true;
				for(int j=0;j<C.getWidth();j++)if(C[0][j]!=0)good=false;
				if(good)AA[AAindex++]=A[i];
        	}
        	AA=AA.submatrixRows(0,AAindex);
        	pout<<AA.getRows();
        }
        else
            if(optionSelectNegative.getValue())
            {
            	IntegerMatrix AA=A;
            	int AAindex=0;
            	for(int i=0;i<A.getHeight();i++)
            	{
    				auto C=A.submatrixRows(i,i+1)*B;
    				bool good=true;
    				for(int j=0;j<C.getWidth();j++)if(C[0][j]>=0)good=false;
    				if(good)AA[AAindex++]=A[i];
            	}
            	AA=AA.submatrixRows(0,AAindex);
            	pout<<AA.getRows();
            }
            else
                if(optionSelectPositive.getValue())
                {
                	IntegerMatrix AA=A;
                	int AAindex=0;
                	for(int i=0;i<A.getHeight();i++)
                	{
        				auto C=A.submatrixRows(i,i+1)*B;
        				bool good=true;
        				for(int j=0;j<C.getWidth();j++)if(C[0][j]<=0)good=false;
        				if(good)AA[AAindex++]=A[i];
                	}
                	AA=AA.submatrixRows(0,AAindex);
                	pout<<AA.getRows();
                }
                else
            	pout<<((optionTropical.getValue())?tropicalProduct(A,B):A*B).getRows();
      }

    return 0;
  }
};

static MatrixProductApplication theApplication;
