//
//  matc.cpp
//  fpComplex
//
//  Created by Robert Delaney on 2/2/17.
//
//

#include "matc.hpp"
#include "matc.hpp"
#include "matcConv.hpp"
#include "matcMath.hpp"

//long myDecPrec=16;

// Constructor
matc::matc()
{   /*
    nr = 1;
    nc = 1;
    array = (fpComplex**)malloc(nr*sizeof(fpComplex*));
    array[0] = (fpComplex*)malloc(nc*sizeof(fpComplex));
    array[0][0] = 0.;
     */
    nr = 0;
    nc = 0;
    array = NULL;
}

// destructor
matc::~matc()
{
    INT32		i;
    
    if(array)
    {
        for(i=0;i<nr;i++)
            if(array[i])
            {   /*
                for(j=0;j<nc;j++)
                {
                    if(array[i][j].re.i.n && array[i][j].re.i.b)
                        free(array[i][j].re.i.b);
                    if(array[i][j].im.i.n && array[i][j].im.i.b)
                        free(array[i][j].im.i.b);
                }
                 */
                free(array[i]);
            }
        free(array);
    }
}

matc::matc(const char *inString)
{
    matc		z;
    INT32		i, j;
    
    nr = 0;
    nc = 0;
    array = NULL;
    
    if(!matcConvFromStr(*this, inString))
        exit(1);
    /*
    nr = z.nr;
    nc = z.nc;
    
    array = (fpComplex**)malloc(nr*sizeof(fpComplex*));
    for(i=0;i<nr;i++)
        array[i] = (fpComplex*)malloc(nc*sizeof(fpComplex));
    
    for(i=0;i<nr;i++)
        for(j=0;j<nc;j++)
            array[i][j] = z.array[i][j];
     */
}

matc& matc::operator= (const matc& x)
{
    INT32	i, j;
    
    if(this==&x)
        return *this;
    
    if(!x.array)
    {
        return *this;
    }
    
    nr = x.nr;
    nc = x.nc;
    
    array = (fpComplex**)malloc(nr*sizeof(fpComplex*));
    for(i=0;i<nr;i++)
        array[i] = (fpComplex*)malloc(nc*sizeof(fpComplex));
    
    for(i=0;i<nr;i++)
        for(j=0;j<nc;j++)
        {
            init(array[i][j].re);
            init(array[i][j].im);
        }
    
    
    for(i=0;i<nr;i++)
        for(j=0;j<nc;j++)
            array[i][j] = x.array[i][j];
    
    return *this;
}

matc matc::operator- ()
{
    matc		z;
    INT32		i, j;
    
    z = *this;
    for(i=0;i<z.nr;i++)
        for(j=0;j<z.nc;j++)
            z.array[i][j] = -z.array[i][j];
    
    return z;
}

matc matc::operator- () const
{
    matc		z;
    INT32		i, j;
    
    z = *this;
    for(i=0;i<z.nr;i++)
        for(j=0;j<z.nc;j++)
            z.array[i][j] = -z.array[i][j];
    
    return z;
}

bool matc::operator== (const matc& y)
{
    INT32		i, j;
    
    if((*this).nr!=y.nr || (*this).nc!=y.nc)
        return false;
    
    for(i=0;i<y.nr;i++)
        for(j=0;j<y.nc;j++)
            if((*this).array[i][j]!=y.array[i][j])
                return false;
    
    return true;
}

bool matc::operator!= (const matc& y)
{
    INT32		i, j;
    
    if((*this).nr!=y.nr || (*this).nc!=y.nc)
        return true;
    
    for(i=0;i<y.nr;i++)
        for(j=0;j<y.nc;j++)
            if((*this).array[i][j]!=y.array[i][j])
                return true;
    
    return false;
}

bool matc::operator! ()
{
    INT32		i, j;
    
    for(i=0;i<(*this).nr;i++)
        for(j=0;j<(*this).nc;j++)
            if((*this).array[i][j].re.i.n || (*this).array[i][j].im.i.n)
                return false;
    
    return true;
}

bool matc::operator== (const matc& y) const
{
    INT32		i, j;
    
    if((*this).nr!=y.nr || (*this).nc!=y.nc)
        return false;
    
    for(i=0;i<y.nr;i++)
        for(j=0;j<y.nc;j++)
            if((*this).array[i][j]!=y.array[i][j])
                return false;
    
    return true;
}

bool matc::operator!= (const matc& y) const
{
    INT32		i, j;
    
    if((*this).nr!=y.nr || (*this).nc!=y.nc)
        return true;
    
    for(i=0;i<y.nr;i++)
        for(j=0;j<y.nc;j++)
            if((*this).array[i][j]!=y.array[i][j])
                return true;
    
    return false;
}

bool matc::operator! () const
{
    INT32		i, j;
    
    for(i=0;i<(*this).nr;i++)
        for(j=0;j<(*this).nc;j++)
            if((*this).array[i][j].re.i.n || (*this).array[i][j].im.i.n)
                return false;
    
    return true;
}

matc matc::operator+ (const matc& y)
{
    matc		z;
    
    add(z, *this, y);
    
    return z;
}

matc matc::operator- (const matc& y)
{
    matc		z;
    
    sub(z, *this, y);
    
    return z;
}


matc matc::operator* (const matc& y)
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator+ (const matc& y) const
{
    matc		z;
    
    add(z, *this, y);
    
    return z;
}

matc matc::operator- (const matc& y) const
{
    matc		z;
    
    sub(z, *this, y);
    
    return z;
}


matc matc::operator* (const matc& y) const
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator* (const fp& y)
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator* (const fp& y) const
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator* (const mb& y)
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator* (const mb& y) const
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}

matc matc::operator* (double y)
{
    matc		z;
    
    mul(z, *this, y);
    
    return z;
}
/*
 matc matc::operator* (double y) const
 {
 matc		z;
 
 mul(z, *this, y);
 
 return z;
 }
 */

matc matc::operator/ (const fp& y)
{
    matc		z;
    
    div(z, *this, y);
    
    return z;
}

matc matc::operator/ (const fp& y) const
{
    matc		z;
    
    div(z, *this, y);
    
    return z;
}

matc matc::operator/ (const mb& y)
{
    matc		z;
    
    div(z, *this, y);
    
    return z;
}

matc matc::operator/ (const mb& y) const
{
    matc		z;
    
    div(z, *this, y);
    
    return z;
}

matc matc::operator/ (double y)
{
    matc		z;
    
    div(z, *this, y);
    
    return z;
}
/*
 matc matc::operator/ (const double& y) const
 {
 matc		z;
 
 div(z, *this, y);
 
 return z;
 }
 */
ostream& operator <<(ostream &s, const matc& x)
{
    char	*xString;
    
    matcConvToStr(xString, x);
    s << xString;
    
    free(xString);
    
    return s;
}


istream& operator >>(istream &s, matc& x)
{
    char	xStr[10000]; // increase if needed
    
    s.width(10000); // increase if needed
    
    s >> xStr;
    
    if(!matcConvFromStr(x, xStr))
        cerr << "conversion error!" << endl;
    
    return s;
}

matc operator* (const fp& x, const matc& y)
{
    matc		z;
    
    mul(z, y, x);
    
    return z;
}

matc operator* (const mb& x, const matc& y)
{
    matc		z;
    
    mul(z, y, x);
    
    return z;
}

matc operator* (double x, const matc& y)
{
    matc		z;
    
    mul(z, y, x);
    
    return z;
}


