#ifndef BINOPPROPERTIES_H
#define BINOPPROPERTIES_H

#include <cassert>
using namespace std;

#include <typedefs.h>


/*!
\brief Investigate the binary operators mathematical properties.

For example is the binary operator a group?

The binary matrix is passed in as a square N by N matrix.
 The matrix is made up of zero and positive integers.
 Let * be the binary operator.

\par Example
\verbatim
  cout << "Test if rotating a triange and flipping it form a group." << endl;
  uint mat[] = 
  {
    0,1,2,3,4,5,
    1,2,0,5,3,4,
    2,0,1,4,5,3,
    3,4,5,0,1,2,
    4,5,3,2,0,1,
    5,3,4,1,2,0
  };

  binopproperties gt(mat,6);
  cout << "isGroup()=" << gt.isGroup() << endl;
\endverbatim
*/
class binopproperties
{
public:

  /** mat_ is a pointer to a N_ by N_ matrix representing
      the binary operator. */
  binopproperties( uintc * mat_, uintc N_)
    : mat(mat_), N(N_) {}

  /** Matrix of binary operator N by N. */
  uintc * mat;
  /** N operators. */
  uintc N;

  // Operations

  /** i*k == e then determine k. */
  uintc inverseright(bool & found, uintc i, uintc e) const; 
  /** i*k == e then determine i. */
  uintc inverseleft(bool & found, uintc k, uintc e) const; 
  /** Find the identity element. */
  uintc identityfind(bool & found) const;
  /** Access the binary operator i*k. */
  uintc matik(uintc i, uintc k) const
    { assert(i<N); assert(k<N); return mat[i*N+k]; }

  // Determine properties of Operator.

  /** Is the operator closed : each element
      0 <= i*j < N . */
  boolc isClosed() const;
  /** Is a*b == b*a? */
  boolc isCommutative() const;
  /** Is  a*(b*c) == (a*b)*c? */
  boolc isAssociative() const;
  /** Operator * is closed, associative, has identity 
      and inverse on each element? */
  boolc isGroup() const;
  /** A group plus a*b==b*a. */
  boolc isGroupAbelian() const;


};

#endif



