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

#include "matcConv.hpp"
#include "matc.hpp"
#include "fpComplexConv.h"
#include "stringUtils.h"
#include "matfp.hpp"

extern INT32 decPrec;

static char* matNULL()
{
    char    *z;
    
    z = (char*)malloc(5*sizeof(char));
    strcpy(z, "NULL");
    return z;
    
}/* matNULL */

void init(matc& z, INT32 nr, INT32 nc)
{
    INT32   i, j;
    
    z.nr = nr;
    z.nc = nc;
    z.array = (fpComplex**)malloc(nr*sizeof(fpComplex*));
    for(i=0;i<nr;++i)
        z.array[i] = (fpComplex*)malloc(nc*sizeof(fpComplex));
    for(i=0;i<nr;++i)
        for(j=0;j<nc;++j)
        {
            init(z.array[i][j].re);
            init(z.array[i][j].im);
        }
    
}

// fills matrix with fpComplex
// in xString row elements seperated by |'s and rows seperated by semicolons
bool matcConvFromStr(matc& z, const char *xString)
{
    INT32		i, j, k;
    char		*rowString, *numString;
    char		*zString, ch;
    INT32		length, nr, nc;
    
    length = strlen(xString);
    
    if(!xString || !length)
    {
        z.nr = z.nc = 0;
        z.array = NULL;
        return false;
    }
    
    zString = (char*)malloc((length+1)*sizeof(char));
    zString[0] = 0;
    
    strcpy(zString, xString);
    
    // trim non-numerics from end of xtString
    i = length - 1;
    ch = zString[i];
    while((ch<'0' || ch>'9') && i>0)
    {
        ch = zString[--i];
    }
    zString[i+1] = 0;
    
    nr = CountFields(zString, ";");
    
    rowString = NthField(zString, ";", 1);
    
    nc = CountFields(rowString, "|");
    
    init(z, nr, nc);
    
    for(i=0;i<nr;i++)
    {
        for(j=0;j<nc;j++)
        {
            numString = NthField(rowString, "|", j+1);
            if(!fpConvFromString(z.array[i][j], numString))
            {
                for(k=0;k<nr;k++)
                    free(z.array[k]);
                free(z.array);
                z.nr = z.nc = 0;
                z.array = NULL;
                return false;
            }
            free(numString);
        }
        
        free(rowString);
        if(i<(nr-1))
            rowString = NthField(zString, ";", i+2);
    }
    
    free(zString);
    
    return true;
    
}/* matcConvFromStr */


void matcConvToStr(char*& matcStr, const matc& x)
{
    INT32		i, j;
    char		*numStr;
    INT32		allNumLen;
    
    if(!x)
    {
        matcStr = matNULL();
        return;
    }
    
    allNumLen = 0;
    
    for(i=0;i<x.nr;i++)
        for(j=0;j<x.nc;j++)
        {
            numStr = fpComplexToStr(x.array[i][j], decPrec);
            allNumLen = allNumLen + strlen(numStr);
            free(numStr);
        }
    // account for |'s and semicolons
    allNumLen = allNumLen + x.nr*x.nc + x.nr + 20;
    matcStr = (char*)malloc(allNumLen*sizeof(char));
    matcStr[0] = 0;
    
    for(i=0;i<x.nr;i++)
    {
        for(j=0;j<x.nc;j++)
        {
            numStr = fpComplexToStr(x.array[i][j], decPrec);
            strcat(matcStr, numStr);
            if(j<(x.nc-1))
                strcat(matcStr, "|");
            free(numStr);
        }
        if(i<(x.nr-1))
            strcat(matcStr, ";");
    }
    
}/* matcConvToStr */


// convert matfp to matc
void conv(matc& z, const matfp& x)
{
    INT32   i, j;
    
    init(z, x.nr, x.nc);
    
    for(i=0;i<x.nr;++i)
        for(j=0;j<x.nc;++j)
        {
            z.array[i][j].re = x.array[i][j];
            z.array[i][j].im = 0.;
        }
}

