// This may look like C code, but it is really -*- C++ -*-

/*
 *  Copyright (c) University of Aizu
 */

#ifndef _Cmatrix_h
#define _Cmatrix_h 1

#ifdef __GNUG__
#pragma interface
#endif

#include <stdarg.h>
#include <complex.h>
#include "Cvector.h"

class Cmatrix 
{
 private:
  Cvector **m;
  int r, c;

 public:
  // constructors and destructors
  Cmatrix(int rows, int cols, const complex& value = 0);
  Cmatrix(const Cmatrix&);
  ~Cmatrix();

  // elementary operations
  Cvector& operator [](int) const;
  int      rows() const;
  int      cols() const;
  void     set(double ...);
  void     set(float ...);
  void     set(int ...);

  // Assignment
  Cmatrix& operator = (const Cmatrix& y);
  Cmatrix& operator = (const Cvector& y);    // set diagonal to y
  Cmatrix& operator = (const complex& y);    // set matrix to yI

  // Basic Math
  Cmatrix& operator += (const Cmatrix& y);
  Cmatrix& operator += (const Cvector& y);   // add y to diagonal
  Cmatrix& operator += (const complex& y);   // add yI to matrix
  Cmatrix& operator -= (const Cmatrix& y);
  Cmatrix& operator -= (const Cvector& y);   // see addition
  Cmatrix& operator -= (const complex& y);   //  "     "
  Cmatrix& operator *= (const complex& y);
  Cmatrix& operator /= (const complex& y);
  Cmatrix& operator -  ();
  Cmatrix& operator +  ();

// other functions
friend istream&  operator >> (istream& s, Cmatrix& x);
friend ostream&  operator << (ostream& s, const Cmatrix& x);

// adding und subtracting
friend Cmatrix operator  + (const Cmatrix&, const Cmatrix&);
friend Cmatrix operator  - (const Cmatrix&, const Cmatrix&);

// adding/subtracing  a scalar z to a matrix A is A + zI (I = identity)
friend Cmatrix operator  + (const complex&, const Cmatrix&);
friend Cmatrix operator  + (const Cmatrix&, const complex&);
friend Cmatrix operator  - (const complex&, const Cmatrix&);
friend Cmatrix operator  - (const Cmatrix&, const complex&);

// adding/subtracting a vector to a matrix is adding/subtracting the 
// vector to the diagonal of the matrix
friend Cmatrix operator  + (const Cvector&, const Cmatrix&);
friend Cmatrix operator  + (const Cmatrix&, const Cvector&);
friend Cmatrix operator  - (const Cvector&, const Cmatrix&);
friend Cmatrix operator  - (const Cmatrix&, const Cvector&);

// multiplication and division by scalar values
friend Cmatrix operator  * (const complex&, const Cmatrix&);
friend Cmatrix operator  * (const Cmatrix&, const complex&);
friend Cmatrix operator  / (const Cmatrix&, const complex&);

// multiplication by a vector (note the non-commutativity)
friend Cvector operator  * (const Cvector&, const Cmatrix&);
friend Cvector operator  * (const Cmatrix&, const Cvector&);

// Multiplication of 2 matrices
friend Cmatrix operator  * (const Cmatrix&, const Cmatrix&);

// comparisons
friend int     operator == (const Cmatrix&, const Cmatrix&);
friend int     operator != (const Cmatrix&, const Cmatrix&);

// the "infinity" norm
friend double norm(const Cmatrix&);
friend complex max(const Cmatrix&);

// Transposition
friend Cmatrix transpose(const Cmatrix&);

};

#endif
