//***************************************************************************
#ifndef MATRIX_H
#define MATRIX_H
//***************************************************************************
#include <iostream.h>
#include <fstream.h>
//***************************************************************************
class Matrix
{
   private:
        int     allocateFlag;
        int     Optimization2D;

    public:
        int     nx;
        int     ny;
        float   **p;
        Matrix ( );             // Constructor
        Matrix (int m, int n);          // Constructor
        void Init (int m, int n);               // Constructor
        void allocateMem (int m, int n);
        ~Matrix ( );            // Destructor
        void deAllocateMem( );
        void Identity ();
        void translate (float x, float y, float z);
        void scale (float x, float y, float z);
        void rotate (float angle, float x, float y, float z);
        void translate_and_rotate2D (float x, float y, float angle);
                        // optimized 2D version of translation and rotation
        Matrix &Transpose ();
        Matrix &operator+ (Matrix &M1);
        void operator+= (Matrix &M);
        Matrix &operator- (Matrix &M1);
        Matrix &operator* (Matrix &M1);
        Matrix &operator* (float k);
        Matrix &operator/ (float k);
        Matrix &operator= (const Matrix &M);
        float operator() (int i, int j);
        float *arrayform();
        friend ostream &operator<< (ostream &Out, Matrix &M);
        void transformXY (int x, int y, int *xf, int *yf);
        void Abs();
        float Norm();
        void Normalize();
        void Normalize2();
        void NormalizeEnergy();
        void Zero();
        void scale(float k);
        void Threshold(float k);

        // pixel by pixel multiplication
        Matrix &operator^ (Matrix &M1);
        // pixel by pixel division
        Matrix &operator/ (Matrix &M1);
        int operator== (Matrix &M);

        void WriteFFTImage(char *FileName, char *fmt);
        void WriteFFTImage(char *FileName);
        void WriteImage(char *FileName, char *fmt);
        void WriteImage(char *FileName);
        int WriteToFile(char *FileName);
        int ReadFromFile(char *FileName);

        int isBoundaryPixel(int x, int y);
};
//***************************************************************************
#define DEG2RAD (0.01745329251994329576)
#define RAD2DEG (57.29577951308232087721)
#define Pi      (3.141592653589793115997963468544185161590576171875)
#define TwoPi   (6.283185307179586231995926937088370323181152343750)
Matrix &Transpose (Matrix &M);
Matrix &Rotate (float angle, float x, float y, float z);
Matrix &xRotate (float angle);
Matrix &yRotate (float angle);
Matrix &zRotate (float angle);
Matrix &Translate (float x, float y, float z);
Matrix &Scale (float x, float y, float z);
Matrix &Perspective (float lambda);
Matrix &Identity (int n);
Matrix &TransformToImagePlane (float x0, float y0, float z0, float xC,
        float yC, float zC, float r1, float r2, float r3, float lambda);
void PerspectiveTransform (Matrix T, float x, float y, float z,
                        float *xp, float *yp);

// New functions (added 7th April, 2000)
// Only Or and Oi are changed
void MatrixFFT2D(Matrix *Or, Matrix *Oi, Matrix *Ir, Matrix *Ii, int isign);
void MatrixFFT2D(Matrix *Or, Matrix *Oi, Matrix *Ir, Matrix *Ii);
void MatrixIFFT2D(Matrix *Or, Matrix *Oi, Matrix *Ir, Matrix *Ii);

// A is changed, B is not
void MatCopy(Matrix *A, Matrix *B, int h_target, int w_target,
                int h_begin, int w_begin, int h_end, int w_end);
void Matrix2Vector(Matrix *m, float *v);
// Pixel by Pixel product A = B * C
void MatProduct(Matrix *A, Matrix *B, Matrix *C);
void MatSum(Matrix *A, Matrix *B, Matrix *C);
void MatDiff(Matrix *A, Matrix *B, Matrix *C);
void Complex2Polar(Matrix *Real, Matrix *Imag);

Matrix *allocateMatrixArray(int n, int height, int width);
void deallocateMatrixArray(Matrix *M, int n);
void printMatrixArray(Matrix *M, char *filename, int n, int height, int width);

Matrix **allocateMatrixArray(int nx, int ny, int height, int width);
void deallocateMatrixArray(Matrix **M, int nx, int ny);
void printMatrixArray(Matrix **M, char *filename, int nx, int ny, int height, int width);

void Write2DTecplotFile(Matrix *R, Matrix *I, char *filename);

float log2(double x);
//***************************************************************************
#endif // MATRIX_H
//***************************************************************************