//
//  ComplexMatrix.cpp
//  ComplexMatrix
//
//  Created by Robert Delaney on 2/5/16.
//  Copyright © 2016 Robert Delaney. All rights reserved.
//

#include "ComplexMatrix.hpp"
#include "rb_plugin.h"
#include "PluginInit.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "ComplexFunctions.h"
#include "matinv.h"
#include "diags.h"
#include "myMatrixCalc.h"
#include "myTypedef.h"
#include "diagh.h"
#include "cmatinv.h"
#include "myComplexMatrixCalc.h"
#include "HandleArrays.h"
#include "LaguerreOld.h"
//#include "myFindRoots.h"
#include "fpComplex.h"
#include "findPolyRoots.h"
#include "fpMath.h"

extern double zeroDouble;

#define kREALTextEncodingUTF8	0x08000100

static int myPrecision;  // for complex output
static REALstring nullString;

REALclassRef  globalComplexRef;
REALclassRef  globalMatrixRef;
REALclassRef  globalComplexMatrixRef;
REALclassRef  globalPolynomialRef;

static void initNullString()
{
    nullString = REALBuildStringWithEncoding (nil, 0, kREALTextEncodingUTF8);
    
}/* initNullString */

static double dabs(double x)
{
    if(x<0)
        x = -x;
    
    return x;
    
}/* dabs */

/*
typedef struct
{
	double					Re;
	double					Im;
} Complex;
*/

static double absD(double x)
{
	if(x>=0)
		return x;
	
	return -x;
	
}/* absD */


static inline void complexMultiply(Complex& z, const Complex& x, const Complex& y)
{
	double			ac, bd;
	
	if(x.Re!=0 && x.Im!=0 && y.Re!=0 && y.Im!=0)
	{
		ac = x.Re*y.Re;
		bd = x.Im*y.Im;
		
		// the order here is important since z might be the same as x or y
		z.Im = (x.Re + x.Im)*(y.Re + y.Im) - ac - bd;
		z.Re = ac - bd;
		return;
	}
	
	if(x.Re==0)
	{
		ac = -x.Im*y.Im;
		z.Im = x.Im*y.Re;
		z.Re = ac;
		return;
	}
	
	if(x.Im==0)
	{
		ac = x.Re*y.Re;
		z.Im = x.Re*y.Im;
		z.Re = ac;
		return;
	}
	
	if(y.Re==0)
	{
		ac = -x.Im*y.Im;
		z.Im = x.Re*y.Im;
		z.Re = ac;
		return;
	}
	
	if(y.Im==0)
	{
		ac = x.Re*y.Re;
		z.Im = x.Im*y.Re;
		z.Re = ac;
		return;
	}
	
}/* complexMultiply */


static inline void complexDivide(Complex& z, const Complex& x, const Complex& y)
{
	double			ac, bd, den;
	
	// Re[(a + ib)/(c + id)] = (ac + bd)/(c*c + d*d)
	// Im[(a + ib)/(c + id)] = (bc - ad)/(c*c + d*d) = [(a + b)(c - d) - ac + bd]/(c*c + d*d)
	
	// a = x.Re, b = x.Im, c = y.Re, d = y.Im
	
	if(y.Re==0 && y.Im==0)
	{
		z.Re = NAN;
		z.Im = NAN;
		return;
	}
	
	if(x.Im==0 && y.Im==0)
	{
		z.Re = x.Re/y.Re;
		z.Im = 0;
		return;
	}
	
	if(x.Re==0 && y.Re==0)
	{
		z.Re = x.Im/y.Im;
		z.Im = 0;
		return;
	}
	
	if(x.Re==0 && y.Im==0)
	{
		z.Re = 0;
		z.Im = x.Im/y.Re;
		return;
	}
	
	if(x.Im==0 && y.Re==0)
	{
		z.Re = 0;
		z.Im = -x.Re/y.Im;
		return;
	}
	
	den = y.Re*y.Re + y.Im*y.Im;
	
	ac = x.Re*y.Re;
	bd = x.Im*y.Im;
	
	// the order here is important since z might be the same as x or y
	z.Im = ((x.Re + x.Im)*(y.Re - y.Im) - ac + bd)/den;
	z.Re = (ac + bd)/den;
	
}/* complexDivide */


extern REALclassDefinition		ComplexClass;
extern REALclassDefinition		MatrixClass;
extern REALclassDefinition		ComplexMatrixClass;
extern REALclassDefinition		PolynomialClass;
extern REALclassDefinition		DivideByZeroExceptionClass;
extern REALclassDefinition		NegativeNumberExceptionClass;
extern REALclassDefinition		NegativeOrZeroExceptionClass;
extern REALclassDefinition		BadEntryNumberExceptionClass;
extern REALclassDefinition		OverflowOrUnderflowExceptionClass;
extern REALclassDefinition		BadArgumentExceptionClass;
extern REALclassDefinition		RowColumnMismatchClass;

/* -------------------------------------
   ComplexConstructor
   
   Called by REALbasic when a new Complex object is instantiated.
   
   instance = the new Complex object
   ------------------------------------- */

static void ComplexConstructor(REALobject instance)
{
	Complex		*data;
	
	// Get the class data
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return;
	
	data->Re = 0;
	data->Im = 0;
	
}/* ComplexConstructor */


static void NewComplex(REALobject instance, double xRe, double xIm)
{
	Complex		*data;
	
	// Get the class data
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return;
	
	data->Re = xRe;
	data->Im = xIm;

}/* NewComplex */


static void NewComplexD(REALobject instance, double x)
{
	Complex		*data;
	
	// Get the class data
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return;
	
	data->Re = x;
	data->Im = 0;

}/* NewComplexD */


static void NewComplexS(REALobject instance, REALstring CStr)
{
	Complex         *data;
	long			k, r, len;
	char			*dataString, *doubleString, ch;
	Boolean			endOfData;
	double			theDouble;
    long            length;
    REALstringData  *outData;

	
	endOfData = false;
	
	// Get the class data
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return;
		
	// now get the complex number from CStr
	//length = CStr->Length();
    outData = new REALstringData();
    if(!REALGetStringData(CStr, kREALTextEncodingUTF8, outData))
    {
        data->Re = NAN;
        data->Im = NAN;
        REALDisposeStringData(outData);
        return;
    }

    length = outData->length;
    // if length==0 make it a NAN complex number and return
    if(length==0)
    {
        data->Re = NAN;
        data->Im = NAN;
        REALDisposeStringData(outData);
        return;
    }
    dataString = (char *)malloc((length+1)*sizeof(char));
    memcpy(dataString, outData->data, length); // to, from
    dataString[length] = 0; // makes it a C string
	
    REALDisposeStringData(outData);
	
	doubleString = (char *)malloc((length+1)*sizeof(char));
	
	k = 0; // start index of dataString
	
    endOfData = false;
		
	if(!endOfData)
	{
		r = 0; // start index of doubleString
		// get jth double string as doubleString, read to , or end of rowString
		ch = dataString[k];
		while(k<length && ch!=',')
		{
			doubleString[r] = ch;
			r++;
			k++;
			ch = dataString[k]; 
		}
		
		doubleString[r] = 0;
		
		if(k>=length)
			endOfData = true;
		else
			k++; // skip over ","
			
		if(!(sscanf(doubleString, "%lf", &theDouble)==1))
			theDouble = 0;

		data->Re = theDouble;
	}
	else
		data->Re = 0;
	
	if(!endOfData)
	{
		r = 0; // start index of doubleString
		// get jth double string as doubleString, read to , or end of rowString
		ch = dataString[k];
		while(k<length && ch!=',')
		{
			doubleString[r] = ch;
			r++;
			k++;
			ch = dataString[k]; 
		}
		
		doubleString[r] = 0;
			
		if(!(sscanf(doubleString, "%lf", &theDouble)==1))
			theDouble = 0;
			
		data->Im = theDouble;
	}
	else
		data->Im = 0;
	
	free(dataString);
	free(doubleString);

}/* NewComplexS */


/* -------------------------------------
   ComplexDestructor
   
   Called by REALbasic when a Complex object is destroyed.
   
   instance = the Complex object being destroyed
   ------------------------------------- */

static void ComplexDestructor(REALobject instance)
{
	
}/* ComplexDestructor */

/*
static REALobject Complex(double xRe, double xIm)
{
	REALobject		z;
	Complex		*zData;
	
	z = REALnewInstance("Complex");
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xRe;
	zData->Im = xIm;
	
	return z;

}*//* Complex */


static REALobject ComplexNegate(REALobject instance)
{
	REALobject		z;
	Complex		*data, *zData;
	
	if(instance==nil)
	{
		z = REALnewInstance("Complex");
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return instance;
		
	z = REALnewInstance("Complex");
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
	zData->Re = -data->Re;
	zData->Im = -data->Im;
	
	return z;
	
}/* ComplexNegate */


static double ComplexReal(REALobject instance)
{
	Complex		*data;
	
	if(instance==nil)
	{
		return NAN;
	}
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return NAN;
		
	return data->Re;
	
}/* ComplexReal */


static double ComplexImag(REALobject instance)
{
	Complex		*data;
	
	if(instance==nil)
	{
		return NAN;
	}
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return NAN;
		
	return data->Im;
	
}/* ComplexImag */


static REALstring ComplexStr(REALobject instance)
{
	Complex			*data;
	long			length;
	char			myString[100];
	char			formatString1[10], formatString[15], precString[5];
	
	if(instance==nil)
	{
		return nullString;
	}
	
	strcpy(formatString1, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatString1, precString);
	strcat(formatString1, "g");
	
	strcpy(formatString, formatString1);
	strcat(formatString, ", ");
	strcat(formatString, formatString1);
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		strcpy(myString, "");
	else
		sprintf(myString, formatString, data->Re, data->Im);
	
	length = strlen(myString);
	
    REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
    
	return str;
	
}/* ComplexStr */

static REALstring ComplexStr2(REALobject instance)
{
	Complex		*data;
	long			length;
	char			myString[100];
	char			formatString1[10], formatString[15], precString[5];
	
	if(instance==nil)
	{
		return nullString;
	}
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	if (data == nil)
	{
		strcpy(myString, "");
		goto endGame2;
	}
	
	strcpy(formatString1, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatString1, precString);
	strcat(formatString1, "g");
	
	strcpy(formatString, formatString1);
	if(data->Im>=0)
		strcat(formatString, " + i ");
	else
		strcat(formatString, " - i ");
	strcat(formatString, formatString1);
	
	sprintf(myString, formatString, data->Re, absD(data->Im));
		
	endGame2:
	
	length = strlen(myString);
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	return str;
	
}/* ComplexStr2 */


static REALstring ComplexStr2EE(REALobject instance)
{
	Complex         *data;
	long			length;
	char			myString[100];
	char			formatString1[10], formatString[15], precString[5];
	
	if(instance==nil)
	{
		return nullString;
	}
	
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	if (data == nil)
	{
		strcpy(myString, "");
		goto endGame2EE;
	}
	
	strcpy(formatString1, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatString1, precString);
	strcat(formatString1, "g");
	
	strcpy(formatString, formatString1);
	if(data->Im>=0)
		strcat(formatString, " + j ");
	else
		strcat(formatString, " - j ");
	strcat(formatString, formatString1);
	
	sprintf(myString, formatString, data->Re, absD(data->Im));
	
	endGame2EE:
	
	length = strlen(myString);
    REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
    
	return str;
	
}/* ComplexStr2EE */


/*
static void EquateC(REALobject instance, double xRe, double xIm)
{
	Complex		*data;
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (data == nil)
		return;
		
	data->Re = xRe;
	data->Im = xIm;
	
}*//* EquateC */


static REALobject CAddC(REALobject instance, REALobject y)
{
	Complex		*xData, *yData, *zData;
	REALobject		z;
	
	if(instance==nil || y==nil)
	{
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (xData == nil || yData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re + yData->Re;
	zData->Im = xData->Im + yData->Im;
	
	return z;
	
}/* CAdd */


static REALobject CAddS(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re + yRe;
	zData->Im = xData->Im;
	
	return z;
	
}/* CAddS */



static REALobject CSubC(REALobject instance, REALobject y)
{
	Complex		*xData, *yData, *zData;
	REALobject		z;
	
	if(instance==nil || y==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (xData == nil || yData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re - yData->Re;
	zData->Im = xData->Im - yData->Im;
	
	return z;
	
}/* CSub */


static REALobject CSubS(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re - yRe;
	zData->Im = xData->Im;
	
	return z;
	
}/* CSubS */


static REALobject SSubC(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = yRe - xData->Re;
	zData->Im = -xData->Im;
	
	return z;
	
}/* SSubC */


static REALobject CMulC(REALobject instance, REALobject y)
{
	Complex		*xData, *yData, *zData;
	REALobject		z;
	
	if(instance==nil || y==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (xData == nil || yData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	complexMultiply(*zData, *xData, *yData);
	
	return z;
	
}/* CMulC */


static REALobject CMulS(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = yRe*xData->Re;
	zData->Im = yRe*xData->Im;
	
	return z;
	
}/* CMulS */


static REALobject CDivC(REALobject instance, REALobject y)
{
	Complex		*xData, *yData, *zData;
	REALobject		z;
	
	if(instance==nil || y==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (xData == nil)
		return instance;
		
	if(yData == nil || (yData->Re==0 && yData->Im==0))
	{
		xData->Re = NAN;
		xData->Im = NAN;
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	complexDivide(*zData, *xData, *yData);
	
	return z;
	
}/* CDivC */


static REALobject CDivS(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
		
	if(yRe==0)
	{
		xData->Re = NAN;
		xData->Im = NAN;
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re/yRe;
	zData->Im = xData->Im/yRe;
	
	return z;
	
}/* CDivS */


static REALobject SDivC(REALobject instance, double yRe)
{
	Complex		*xData, *zData;
	REALobject		z;
	double			den;
	
	if(instance==nil)
	{
		//z = REALnewInstance("Complex");
        z = REALnewInstanceWithClass(globalComplexRef);
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		
		zData->Re = NAN;
		zData->Im = NAN;
		
		return z;
	}
	
	xData = (Complex *) REALGetClassData(instance, &ComplexClass);
	
	if (xData == nil)
		return instance;
		
	if(xData->Re==0 && xData->Im==0)
	{
		xData->Re = NAN;
		xData->Im = NAN;
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	den = xData->Re*xData->Re + xData->Im*xData->Im;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = yRe*xData->Re/den;
	zData->Im = -yRe*xData->Im/den;
	
	return z;
	
}/* SDivC */


static long CompareCC(REALobject instance, REALobject x)
{
	Complex		*data, *xData;
	
	if(instance==nil || x==nil)
		return 0;
		
	data = (Complex *) REALGetClassData(instance, &ComplexClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || xData==nil)
		return 0;
		
	if(data->Re<xData->Re)
		return -1;
	
	if(data->Re>xData->Re)
		return 1;
		
	if(data->Im<xData->Im)
		return -1;
		
	if(data->Im>xData->Im)
		return 1;
		
	return 0;
	
}/* CompareCC */


// REALbasic class & method definitions for the Complex object

static REALmethodDefinition ComplexMethods[] = {
	// defines methods:
	{ (REALproc) ComplexReal, REALnoImplementation, "Real() as double", REALconsoleSafe },
	{ (REALproc) ComplexImag, REALnoImplementation, "Imag() as double", REALconsoleSafe },
	{ (REALproc) ComplexStr, REALnoImplementation, "Str() as String", REALconsoleSafe },
	{ (REALproc) ComplexStr2, REALnoImplementation, "Str2() as String", REALconsoleSafe },
	{ (REALproc) ComplexStr2EE, REALnoImplementation, "Str2EE() as String", REALconsoleSafe },
	{ (REALproc) ComplexConstructor, REALnoImplementation, "Constructor()", REALconsoleSafe },
	{ (REALproc) NewComplex, REALnoImplementation, "Constructor(xRe as double, xIm as double)", REALconsoleSafe },
	{ (REALproc) NewComplexD, REALnoImplementation, "Constructor(x as double)", REALconsoleSafe },
	{ (REALproc) NewComplexS, REALnoImplementation, "Constructor(inputString As String)", REALconsoleSafe },
	{ (REALproc) ComplexNegate, REALnoImplementation, "Operator_Negate() As Complex", REALconsoleSafe },
	{ (REALproc) CAddC, REALnoImplementation, "Operator_Add(y As Complex) As Complex", REALconsoleSafe },
	{ (REALproc) CAddS, REALnoImplementation, "Operator_Add(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CAddS, REALnoImplementation, "Operator_AddRight(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CSubC, REALnoImplementation, "Operator_Subtract(y As Complex) As Complex", REALconsoleSafe },
	{ (REALproc) CSubS, REALnoImplementation, "Operator_Subtract(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) SSubC, REALnoImplementation, "Operator_SubtractRight(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CMulC, REALnoImplementation, "Operator_Multiply(y As Complex) As Complex", REALconsoleSafe },
	{ (REALproc) CMulS, REALnoImplementation, "Operator_Multiply(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CMulS, REALnoImplementation, "Operator_MultiplyRight(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CDivC, REALnoImplementation, "Operator_Divide(y As Complex) As Complex", REALconsoleSafe },
	{ (REALproc) CDivS, REALnoImplementation, "Operator_Divide(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) SDivC, REALnoImplementation, "Operator_DivideRight(yRe As Double) As Complex", REALconsoleSafe },
	{ (REALproc) CompareCC, REALnoImplementation, "Operator_Compare(x As Complex) As Integer", REALconsoleSafe },
};


REALclassDefinition ComplexClass = {
        kCurrentREALControlVersion,
        "Complex",                    			// name of class
        nil,                                    // no superclasses
        sizeof(Complex),                      // size of our data
        0,																			// --reserved--
        (REALproc) ComplexConstructor,     				// constructor
        (REALproc) ComplexDestructor,							// destructor
        nil,            												// properties
        0,																			// property count
        ComplexMethods,               					// methods
        sizeof(ComplexMethods) / sizeof(REALmethodDefinition),	// method count
        // other fields left nil -- no events etc.
};

// the following pragma is essential here (?)

#pragma mark -


// other methods

static REALobject ComplexObjectNAN()
{
	REALobject		z;
	Complex		*zData;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = NAN;
	zData->Im = NAN;
	
	return z;
	
}/* ComplexObjectNAN */


static REALobject myI()
{
	REALobject		z;
	Complex		*zData;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = 0;
	zData->Im = 1;
	
	return z;

}/* myI */

/*
static REALobject MyComplex(double xRe, double xIm)
{
	REALobject		z;
	Complex		*zData;
	
	z = REALnewInstance("Complex");
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xRe;
	zData->Im = xIm;
	
	return z;

}*//* MyComplex */

/*
static REALobject NewComplexFromD(double x)
{
	REALobject		z;
	Complex		*zData;
	
	z = REALnewInstance("Complex");
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = x;
	zData->Im = 0;
	
	return z;

}*//* NewComplexFromD */


static double AbsC(REALobject x)
{
	Complex		*xData;
	double			result;
	
	if(x==nil)
		return NAN;
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if (xData == nil)
		return NAN;
		
	result = sqrt(xData->Re*xData->Re + xData->Im*xData->Im);
	
	return result;
	
}/* AbsC */


/*
static double AbsD(double x)
{
	if(x<0)
		x = -x;
		
	return x;
	
}*//* AbsD */


/*
static void ComplexAdd(REALobject z, REALobject x, REALobject y)
{
	Complex		*xData, *yData, *zData;
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	if (xData == nil || yData == nil)
		return;
		
	if(zData == nil)
	{
		z = REALnewInstance("Complex");
		zData = (Complex *) REALGetClassData(z, &ComplexClass);
		if (zData == nil)
			return;
	}
	
	zData->Re = xData->Re + yData->Re;
	zData->Im = xData->Im + yData->Im;
	
}*//* ComplexAdd */


static REALobject ExpC(REALobject x)
{
	Complex			*xData;
	REALobject		z;
	Complex			*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myExp(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* ExpC */


static REALobject LogC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	if(xData->Re==0 && xData->Im==0)
	{
		REALobject err = REALnewInstance("BadArgumentException");
		REALRaiseException(err);
		return x;
	}
		
	myLog(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* LogC */


static REALobject SinC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	mySin(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* SinC */


static REALobject CosC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myCos(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* CosC */


static REALobject TanC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myTan(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* TanC */


static REALobject SqrtC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	mySqrt(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* SqrtC */


static REALobject SqrC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	mySqr(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* SqrC */


// RB doesn't have Sqr of a double
static double SqrD(double x)
{
	return x*x;
	
}/* SqrD */


// RB doesn't have sinh of a double
static double SinhD(double x)
{
	double		result;
	
	mySinh(result, x);
	return result;
	
}/* SinhD */


static double CoshD(double x)
{
	double		result;
	
	myCosh(result, x);
	return result;
	
}/* CoshD */


static double TanhD(double x)
{
	double		theSinh, theCosh;
	
	mySinh(theSinh, x);
	theCosh = sqrt(1 + theSinh*theSinh);
	
	return theSinh/theCosh;
	
}/* TanhD */


static double aSinhD(double x)
{
	double		result;
	
	myASinh(result, x);
	
	return result;
	
}/* aSinhD */


static double aCoshD(double x)
{
	double		result;
	
	result = 0;
	myACosh(result, x);
	
	return result;
	
}/* aCoshD */


static double aTanhD(double x)
{
	double		result;
	
	result = 0;
	myATanh(result, x);
	
	return result;
	
}/* aTanhD */


static REALobject SinhC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	mySinhC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* SinhC */


static REALobject CoshC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myCoshC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* CoshC */


static REALobject TanhC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myTanhC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* TanhC */


static REALobject aSinC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myASin(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aSinC */


static REALobject aCosC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myACos(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aCosC */


static REALobject aTanC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myATan(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aTanC */


static REALobject aSinhC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myASinhC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aSinhC */


static REALobject aCoshC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myACoshC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aCoshC */


static REALobject aTanhC(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myATanhC(zRe, zIm, xData->Re, xData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* aTanhC */


static REALobject PowCC(REALobject x, REALobject y)
{
	Complex		*xData, *yData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil || y==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	if (yData == nil)
		return y;
		
	myPowCC(zRe, zIm, xData->Re, xData->Im, yData->Re, yData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* PowCC */


static REALobject PowCD(REALobject x, double y)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	double			zRe, zIm;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
		
	myPowCD(zRe, zIm, xData->Re, xData->Im, y);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* PowCD */


static REALobject PowDC(double x, REALobject y)
{
	Complex			*yData;
	REALobject		z;
	Complex			*zData;
	double			zRe, zIm;
	
	if(y==nil)
		return ComplexObjectNAN();
		
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	if (yData == nil)
		return y;
		
	myPowDC(zRe, zIm, x, yData->Re, yData->Im);
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = zRe;
	zData->Im = zIm;
	
	return z;
	
}/* PowDC */


static REALobject Conjugate(REALobject x)
{
	Complex		*xData;
	REALobject		z;
	Complex		*zData;
	
	if(x==nil)
		return ComplexObjectNAN();
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return x;
	
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = xData->Re;
	zData->Im = -xData->Im;
	
	return z;
	
}/* Conjugate */


static void SetComplexPrecision(long precision)
{
	myPrecision = precision;
	if(myPrecision<3)
		myPrecision = 3;
	if(myPrecision>17)
		myPrecision = 17;
	
}/* SetComplexPrecision */


static long GetComplexPrecision()
{
    long    prec;
    
    prec = myPrecision;
    
    return prec;
    
}/* GetComplexPrecision */


static REALstring StrD(double x)
{
    long			length;
    char			myString[100];
    char			formatString[15], precString[5];
    
    if(!x)
    {
        myString[0] = '0';
        myString[1] = 0;
        length = strlen(myString);
        REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
        return str;
    }
    
    strcpy(formatString, "%.");
    sprintf(precString, "%d", myPrecision);
    strcat(formatString, precString);
    strcat(formatString, "g");
    
    sprintf(myString, formatString, x);
    
    length = strlen(myString);
    
    REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
    
    return str;
    
}/* StrD */

// thisis mutable
static void AssignToComplex(REALobject x, double xRe, double xIm)
{
    Complex		*xData;
    
    xData = (Complex *) REALGetClassData(x, &ComplexClass);
    if (xData == nil)
        return;
    
    xData->Re = xRe;
    xData->Im = xIm;
    
}/* AssignToComplex */


static REALmethodDefinition otherComplexMethods[] = {
	{ (REALproc) myI, REALnoImplementation, "_i() as Complex", REALconsoleSafe },
	{ (REALproc) myI, REALnoImplementation, "_j() as Complex", REALconsoleSafe },
	//{ (REALproc) MyComplex, REALnoImplementation, "Conv(xRe As Double, xIm As Double) As Complex", REALconsoleSafe },
	//{ (REALproc) NewComplexFromD, REALnoImplementation, "Complex(x As Double) As Complex", REALconsoleSafe },
	{ (REALproc) AbsC, REALnoImplementation, "Abs(x As Complex) As Double", REALconsoleSafe },
	//{ (REALproc) AbsD, REALnoImplementation, "Abs(x As Double) As Double", REALconsoleSafe },
	//{ (REALproc) ComplexAdd, REALnoImplementation, "Add(z as Complex, x as Complex, y as Complex)", REALconsoleSafe },
	{ (REALproc) ExpC, REALnoImplementation, "Exp(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) LogC, REALnoImplementation, "Log(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) SinC, REALnoImplementation, "Sin(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) CosC, REALnoImplementation, "Cos(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) TanC, REALnoImplementation, "Tan(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) SqrtC, REALnoImplementation, "Sqrt(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) SqrC, REALnoImplementation, "Sqr(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) SqrD, REALnoImplementation, "Sqr(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) SinhD, REALnoImplementation, "Sinh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) CoshD, REALnoImplementation, "Cosh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) TanhD, REALnoImplementation, "Tanh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) aSinhD, REALnoImplementation, "aSinh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) aCoshD, REALnoImplementation, "aCosh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) aTanhD, REALnoImplementation, "aTanh(x as Double) as Double", REALconsoleSafe },
	{ (REALproc) SinhC, REALnoImplementation, "Sinh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) CoshC, REALnoImplementation, "Cosh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) TanhC, REALnoImplementation, "Tanh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aSinC, REALnoImplementation, "aSin(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aCosC, REALnoImplementation, "aCos(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aTanC, REALnoImplementation, "aTan(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aSinhC, REALnoImplementation, "aSinh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aCoshC, REALnoImplementation, "aCosh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) aTanhC, REALnoImplementation, "aTanh(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) PowCC, REALnoImplementation, "Pow(x as Complex, y as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) PowCD, REALnoImplementation, "Pow(x as Complex, y as Double) as Complex", REALconsoleSafe },
	{ (REALproc) PowDC, REALnoImplementation, "Pow(x as Double, y as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) Conjugate, REALnoImplementation, "Conjugate(x as Complex) as Complex", REALconsoleSafe },
	{ (REALproc) SetComplexPrecision, REALnoImplementation, "SetComplexPrecision(precision As Integer)", REALconsoleSafe },
    { (REALproc) GetComplexPrecision, REALnoImplementation, "GetComplexPrecision() As Integer", REALconsoleSafe },
    { (REALproc) StrD, REALnoImplementation, "StrD(x As Double) As String", REALconsoleSafe },
    { (REALproc) AssignToComplex, REALnoImplementation, "AssignToComplex(xc As Complex, xRe As Double, xIm As Double)", REALconsoleSafe },
};


/*
typedef struct
{
	double		**array;
	long		nr;	// number of rows
	long		nc;	// number of columns
	
} MatrixData;
*/


//extern REALclassDefinition		MatrixClass;


static void MatrixConstructor(REALobject instance)
{
	MatrixData		*data;
	
	// Get the class data
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil)
		return;
		
	data->array = nil;
	data->nr = 0;
	data->nc = 0;
	
}/* MatrixConstructor */


static void NewMatrix(REALobject instance, long numberOfRows, long numberOfColumns)
{
	MatrixData		*data;
	long			i, j;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || numberOfRows<=0 || numberOfColumns<=0)
		return;
	
	data->nr = numberOfRows;
	data->nc = numberOfColumns;
	data->array = (double **)malloc(data->nr*sizeof(double *));
	for (i=0;i<data->nr;i++)
		(data->array)[i] = (double *)malloc(data->nc*sizeof(double));
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			(data->array)[i][j] = 0;
	
}/* NewMatrix */


static void NewMatrixS(REALobject instance, long numberOfRows, long numberOfColumns, REALstring MStr)
{
	MatrixData		*data;
	long			i, j, k, r, kd, rd, length, rowLength;
	char			*dataString, *rowString, *doubleString, ch, CR=0x0D, SP=0x20, LF=0x0A, TAB=0x09;
	double			theDouble;
	Boolean			endOfData, endOfRowData, areInNumber;
    REALstringData  *outData;
	
	endOfData = false;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || numberOfRows<=0 || numberOfColumns<=0)
		return;
	
	data->nr = numberOfRows;
	data->nc = numberOfColumns;
	data->array = (double **)malloc(data->nr*sizeof(double *));
	for (i=0;i<data->nr;i++)
		(data->array)[i] = (double *)malloc(data->nc*sizeof(double));
		
    outData = new REALstringData();
    if(!REALGetStringData(MStr, kREALTextEncodingUTF8, outData))
    {
        for(i=0;i<data->nr;i++)
            for(j=0;j<data->nc;j++)
                (data->array)[i][j] = 0;
        REALDisposeStringData(outData);
        return;
    }
	// now get the matrix elements from MStr
	//length = MStr->Length();
	length = outData->length;
	// if length==0 make it a null matrix and return
	if(length==0)
	{
		for(i=0;i<data->nr;i++)
			for(j=0;j<data->nc;j++)
				(data->array)[i][j] = 0;
        REALDisposeStringData(outData);
		return;
	}

	// length!=0
	dataString = (char *)malloc((length+1)*sizeof(char));
	rowString = (char *)malloc((length+1)*sizeof(char));
	doubleString = (char *)malloc((length+1)*sizeof(char));
	memcpy(dataString, outData->data, length); // to, from
	dataString[length] = 0; // makes it a C string
    REALDisposeStringData(outData);
	
	/*
		for example, a 2 x 3 matrix string would look like:
		1 2 3
		4 5 6
		
		Mac newline = 0xD (CR), Win32 newline = 0xD 0xA (CR LF), Unix newline = 0xA (LF)
	*/
	
	kd = 0;
	rowLength = 0;
	k = 0; // start index of dataString
	for(i=0;i<data->nr;i++)
	{
		if(k>=length)
			endOfData = true;
			
		if(!endOfData)
		{
			r = 0; // start index of rowString
			// get ith row as rowString, read to CR or end of dataString
			ch = dataString[k];
			while(k<length && ch!=CR && ch!=LF && ch!=';')
			{
				rowString[r] = ch;
				r++;
				k++;
				ch = dataString[k];
			}
			rowString[r] = 0;
			rowLength = strlen(rowString);
			if(rowLength==0)
				endOfRowData = true;
			else
				endOfRowData = false;
			
			// now either ch==';' or ch==0 because we've reached the end of dataString
			//k++; // skip over CR if necessary
			
			while(!(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
				ch = dataString[++k];
				
			
			
			/*
			#ifdef MYWIN32
				if(ch!=';')
					k++; // skip over LF if necessary
			#endif
			*/
				
			kd = 0; // start index of rowString
		}
		for(j=0;j<data->nc;j++)
		{
			if(!endOfRowData && !endOfData)
			{
				areInNumber = false;
				rd = 0; // start index of doubleString
				// get jth double string as doubleString, read to , or SP or end of rowString
				ch = rowString[kd];
				
				while(kd<rowLength && !(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
				{
					//doubleString[rd] = ch;
					//rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				// now into number, go until whitespace
				while(kd<rowLength && !(ch==SP || ch==TAB))
				{
					doubleString[rd] = ch;
					rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				doubleString[rd] = 0;
				
				if(kd>=rowLength)
					endOfRowData = true;
					
				if(!(sscanf(doubleString, "%lf", &theDouble)==1))
					theDouble = 0;

				(data->array)[i][j] = theDouble;
			}
			else
				(data->array)[i][j] = 0;
		}
		
	}
	
	free(dataString);
	free(rowString);
	free(doubleString);
	
}/* NewMatrixS */


/* -------------------------------------
   MatrixDestructor
   
   Called by REALbasic when a Matrix object is destroyed.
   
   instance = the Matrix object being destroyed
   ------------------------------------- */

static void MatrixDestructor(REALobject instance)
{
	MatrixData		*data;
	long			i;
	
	if(instance==nil)
		return;
	
	// Get the class data
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || data->array==nil)
		return;
	
	for (i=0;i<data->nr;i++)
		free((data->array)[i]);
		
	free(data->array);
	
}/* MatrixDestructor */


// access functions


static REALstring MatrixOut(REALobject instance)
{
	MatrixData		*data;
	char			*myString, ***doubleStringMatrix, CR=0x0D, SP=0x20, LF=0x0A;
	long			i, j, k, length, len, diffLen;
	char			formatStringTemp[10], formatString1[15], formatString2[15], formatString3[15], formatString4[15], precString[5];
	
	//REALstring nullString = REALBuildString (nil, 0);
	
	if(instance==nil)
		return nullString;
		
	strcpy(formatStringTemp, " %.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g  ");
	strcpy(formatString1, formatStringTemp);
	
	strcpy(formatStringTemp, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g  ");
	strcpy(formatString2, formatStringTemp);
	
	strcpy(formatStringTemp, " %.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g");
	strcpy(formatString3, formatStringTemp);
	
	strcpy(formatStringTemp, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g");
	strcpy(formatString4, formatStringTemp);
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	if(data==nil || data->nr<1 || data->nc<1)
		return nullString;
		
	length = 20; // length of string double should be less than this
		
	doubleStringMatrix = (char ***)malloc(data->nr*sizeof(char *));
	for (i=0;i<data->nr;i++)
		doubleStringMatrix[i] = (char **)malloc(data->nc*sizeof(char*));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			doubleStringMatrix[i][j] = (char *)malloc(length);
	
	
	// put doubles into doubleStringMatrix
	// if it's positive put one space at start, so negatives will align with positives in a column
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			if(j<(data->nc-1))
			{
                if(!data->array[i][j])
                {
                    doubleStringMatrix[i][j][0] = ' ';
                    doubleStringMatrix[i][j][1] = '0';
                    doubleStringMatrix[i][j][2] = 0;
                }
				if(data->array[i][j]>0)
					sprintf(doubleStringMatrix[i][j],formatString1, data->array[i][j]);
				else
                    if(data->array[i][j])
                        sprintf(doubleStringMatrix[i][j],formatString2, data->array[i][j]);
			}
			else
			{
                if(!data->array[i][j])
                {
                    doubleStringMatrix[i][j][0] = ' ';
                    doubleStringMatrix[i][j][1] = '0';
                    doubleStringMatrix[i][j][2] = 0;
                }
				if(data->array[i][j]>0)
					sprintf(doubleStringMatrix[i][j],formatString3, data->array[i][j]);
				else
                    if(data->array[i][j])
                        sprintf(doubleStringMatrix[i][j],formatString4, data->array[i][j]);
			}
				
			
	// find the largest strlen
	length = 0;
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			len = strlen(doubleStringMatrix[i][j]);
			if(len>length)
				length = len;
		}
		
	//length++;
	
	// now pad each double string on right so it has length as its strlen, except for the last column
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<(data->nc-1);j++)
		{
			len = strlen(doubleStringMatrix[i][j]);
			diffLen = length - len;
			for(k=0;k<diffLen;k++)
				doubleStringMatrix[i][j][len+k] = SP;
				
			doubleStringMatrix[i][j][length] = 0;
		}
		
	length = 30*data->nr*data->nc + data->nr + 1; // estimate of maximum length of C string returned
	
	myString = (char *)malloc(length*sizeof(char));
	myString[0] = 0;
	
	// load up myString
	for(i=0;i<data->nr;i++)
	{
		for(j=0;j<data->nc;j++)
			strcat(myString, doubleStringMatrix[i][j]);
		
		len = strlen(myString);
		myString[len] = CR;
		
		#if MYWIN32
			myString[++len] = LF;
		#endif
		myString[++len] = 0;
	}
	
	length = strlen(myString);
	
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	
	free(myString);
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			free(doubleStringMatrix[i][j]);
			
	for(i=0;i<data->nr;i++)
		free(doubleStringMatrix[i]);
		
	free(doubleStringMatrix);
	
	return str;
		
}/* MatrixOut */


// MatrixOut2 outputs as "1, 2;3, 4"
static REALstring MatrixOut2(REALobject instance)
{
	MatrixData		*data;
	char			*myString, doubleString[20];
	long			i, j, length;
	char			formatStringTemp[10], formatString1[15], formatString2[15], precString[5];
	
	//REALstring nullString = REALBuildString (nil, 0);
	
	if(instance==nil)
		return nullString;
		
	strcpy(formatStringTemp, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g, ");
	strcpy(formatString1, formatStringTemp);
	
	strcpy(formatStringTemp, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatStringTemp, precString);
	strcat(formatStringTemp, "g");
	strcpy(formatString2, formatStringTemp);
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	if(data==nil || data->nr<1 || data->nc<1)
		return nullString;
		
	length = 30*data->nr*data->nc + data->nr + 1; // estimate of maximum length of C string returned
	
	myString = (char *)malloc(length*sizeof(char));
	myString[0] = 0;
	
	for(i=0;i<data->nr;i++)
	{
		for(j=0;j<data->nc;j++)
		{
			if(j<(data->nc-1))
				sprintf(doubleString, formatString1, (data->array)[i][j]);
			else
				sprintf(doubleString, formatString2, (data->array)[i][j]);
				
			strcat(myString, doubleString);
		}
		
		if(i<(data->nr-1))
		{
			length = strlen(myString);
			myString[length] = ' ';
			myString[++length] = ';';
			myString[++length] = ' ';
			myString[++length] = 0;
		}
	}
	
	length = strlen(myString);
	
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	
	free(myString);
	
	return str;
		
}/* MatrixOut2 */


static double Element(REALobject instance, long i, long j)
{
	MatrixData		*data;
	
	if(instance==nil)
		return NAN;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || i>=data->nr || j>=data->nc || i<0 || j<0)
		return NAN;
		
	return (data->array)[i][j];
	
}/* Element */


static REALobject MatrixNegate(REALobject instance)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	
	zData->array = (double **)malloc(data->nr*sizeof(double *));
	for (i=0;i<data->nr;i++)
		(zData->array)[i] = (double *)malloc(data->nc*sizeof(double));
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			(zData->array)[i][j] = -(data->array)[i][j];
			
	return z;
	
}/* MatrixNegate */


static REALobject AddMM(REALobject instance, REALobject x)
{
	MatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc || data->nr<1 || data->nc<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j] + (xData->array)[i][j];
			
	return z;
	
}/* AddMM */


static REALobject AddMD(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
				(zData->array)[i][j] = (data->array)[i][j];
			else
				(zData->array)[i][i] = (data->array)[i][i] + x;
			
	return z;
	
}/* AddMD */


static REALobject AddMC(REALobject instance, REALobject x)
{
	MatrixData			*data;
	ComplexMatrixData	*zData;
	Complex			*xData;
	REALobject			z;
	long				i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || xData==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
			{
				zData->array[i][j].Re = data->array[i][j];
				zData->array[i][j].Im = 0;
				
			}
			else
			{
				zData->array[i][i].Re = data->array[i][i] + xData->Re;
				zData->array[i][i].Im = xData->Im;
			}
			
	return z;
	
}/* AddMC */


static REALobject SubMM(REALobject instance, REALobject x)
{
	MatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j] - (xData->array)[i][j];
			
	return z;
	
}/* SubMM */


static REALobject SubMD(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
				(zData->array)[i][j] = (data->array)[i][j];
			else
				(zData->array)[i][i] = (data->array)[i][i] - x;
			
	return z;
	
}/* SubMD */


static REALobject SubDM(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
				(zData->array)[i][j] = -(data->array)[i][j];
			else
				(zData->array)[i][i] = -(data->array)[i][i] + x;
			
	return z;
	
}/* SubDM */


static REALobject SubMC(REALobject instance, REALobject x)
{
	MatrixData			*data;
	ComplexMatrixData	*zData;
	Complex			*xData;
	REALobject			z;
	long				i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
			{
				zData->array[i][j].Re = data->array[i][j];
				zData->array[i][j].Im = 0;
				
			}
			else
			{
				zData->array[i][i].Re = data->array[i][i] - xData->Re;
				zData->array[i][i].Im = -xData->Im;
			}
			
	return z;
	
}/* SubMC */


static REALobject SubCM(REALobject instance, REALobject x)
{
	MatrixData			*data;
	ComplexMatrixData	*zData;
	Complex			*xData;
	REALobject			z;
	long				i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(i!=j)
			{
				zData->array[i][j].Re = -data->array[i][j];
				zData->array[i][j].Im = 0;
				
			}
			else
			{
				zData->array[i][i].Re = -data->array[i][i] + xData->Re;
				zData->array[i][i].Im = xData->Im;
			}
			
	return z;
	
}/* SubCM */


static REALobject MulMM(REALobject instance, REALobject x)
{
	MatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j, k;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			{
				(zData->array)[i][j] = 0;
				for(k=0;k<data->nc;k++)
					(zData->array)[i][j] = (zData->array)[i][j] + (data->array)[i][k] * (xData->array)[k][j];
			}
    
    // we cannot have any extremely small but non-zero elements
    for(i=0;i<zData->nr;++i)
    {
        for(j=0;j<zData->nc;++j)
        {
            if(dabs(zData->array[i][j])<zeroDouble)
                zData->array[i][j] = 0;
        }
    }
			
	return z;
	
}/* MulMM */


static REALobject MulDM(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = x*(data->array)[i][j];
			
	return z;
	
}/* MulDM */


static REALobject MulMC(REALobject instance, REALobject x)
{
	MatrixData			*data;
	ComplexMatrixData	*zData;
	Complex			*xData;
	REALobject			z;
	long				i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			{
				zData->array[i][j].Re = xData->Re*data->array[i][j];
				zData->array[i][j].Im = xData->Im*data->array[i][j];
			}
			
	return z;
	
}/* MulMC */


static REALobject DivMD(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(x!=0)
				(zData->array)[i][j] = (data->array)[i][j]/x;
			else
			{
				REALobject err = REALnewInstance("DivideByZeroException");
				REALRaiseException(err);
				(zData->array)[i][j] = NAN;
			}
			
	return z;
	
}/* DivMD */


static REALobject DivDM(REALobject instance, double x)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	double			determinant;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil || data->nr!=data->nc || data->nr<1 || data->nc<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
				(zData->array)[i][j] = (data->array)[i][j];
				
	determinant = matinv(zData->array, zData->nr);
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			if(determinant!=0)
				(zData->array)[i][j] = x*(zData->array)[i][j];
			else
			{
				REALobject err = REALnewInstance("DivideByZeroException");
				REALRaiseException(err);
				(zData->array)[i][j] = NAN;
			}
			
	return z;
	
}/* DivDM */


static REALobject DivMC(REALobject instance, REALobject x)
{
	MatrixData				*data;
	ComplexMatrixData		*zData;
	Complex				*xData, temp, one;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || (xData->Re==0 && xData->Im==0))
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	one.Re = 1;
	one.Im = 0;
	
	complexDivide(temp, one, *xData);
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			{
				zData->array[i][j].Re = temp.Re*data->array[i][j];
				zData->array[i][j].Im = temp.Im*data->array[i][j];
			}
			
	return z;
	
}/* DivMC */


static REALobject DivCM(REALobject instance, REALobject x)
{
	MatrixData				*data;
	ComplexMatrixData		*zData;
	Complex				*xData;
	REALobject				z;
	long					i, j;
	double					**array, determinant;
	
	if(instance==nil)
		return instance;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || xData==nil || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	array = (double **)malloc(data->nr*sizeof(double *));
	for (i=0;i<data->nr;i++)
		array[i] = (double *)malloc(data->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
				array[i][j] = data->array[i][j];
				
	determinant = matinv(array, data->nr);
	if(determinant==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
			{
				zData->array[i][j].Re = data->array[i][j];
				zData->array[i][j].Im = 0;
			}
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return z;
	}
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = xData->Re*array[i][j];
			zData->array[i][j].Im = xData->Im*array[i][j];
		}
			
				
	for (i=0;i<data->nr;i++)
		free(array[i]);
		
	free(array);
			
	return z;
	
}/* DivCM */


static REALobject DivMM(REALobject instance, REALobject x)
{
	MatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j, k;
	double			**array, determinant;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nc!=xData->nr || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	array = (double **)malloc(xData->nr*sizeof(double *));
	for (i=0;i<xData->nr;i++)
		array[i] = (double *)malloc(xData->nc*sizeof(double));
		
	for(i=0;i<xData->nr;i++)
		for(j=0;j<xData->nc;j++)
			array[i][j] = (xData->array)[i][j];
			
	determinant = matinv(array, xData->nr);
	
	if(determinant==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			(zData->array)[i][j] = 0;
			for(k=0;k<xData->nc;k++)
				(zData->array)[i][j] = (zData->array)[i][j] + (data->array)[i][k] * array[k][j];
		}
			
	for (i=0;i<xData->nr;i++)
		free(array[i]);
		
	free(array);
			
	return z;
	
}/* DivMM */


static long CompareMM(REALobject instance, REALobject x)
{
	MatrixData		*data, *xData;
	long			i, j;
	
	if(instance==nil)
		return 0;
		
	if(x==nil)
		return 0;
		
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return 0;
		
	if(data->nr!=xData->nr || data->nc!=xData->nc)
		return 1;
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			{
				if((data->array)[i][j] < (xData->array)[i][j])
					return -1;
				else
					if((data->array)[i][j] > (xData->array)[i][j])
						return 1;
			}
				
				
	return 0;

}/* CompareMM */


static long CompareM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*xData;
	MatrixData				*data;
	long					i, j;
	
	if(instance==nil)
		return 0;
		
	if(x==nil)
		return 0;
		
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return 0;
		
	if(data->nr!=xData->nr || data->nc!=xData->nc)
		return 1;
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			{
				if(data->array[i][j] < xData->array[i][j].Re)
					return -1;
					
				if(data->array[i][j] > xData->array[i][j].Re)
					return 1;
					
				if(0 < xData->array[i][j].Im)
					return -1;
					
				if(0 > xData->array[i][j].Im)
					return 1;
			}
				
	return 0;

}/* CompareM_CM */


static long NumRowsR(REALobject instance)
{
	MatrixData		*data;
	
	if(instance==nil)
		return 0;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil)
		return 0;
	
	return data->nr;
	
}/* NumRowsR */


static long NumColumnsR(REALobject instance)
{
	MatrixData		*data;
	
	if(instance==nil)
		return 0;
	
	data = (MatrixData *) REALGetClassData(instance, &MatrixClass);
	
	if (data == nil)
		return 0;
	
	return data->nc;
	
}/* NumColumnsR */


// REALbasic class & method definitions for the Matrix object

static REALmethodDefinition MatrixMethods[] = {
	// defines methods:
	{ (REALproc) MatrixConstructor, REALnoImplementation, "Constructor()", REALconsoleSafe },
	{ (REALproc) NewMatrix, REALnoImplementation, "Constructor(numberOfRows As Integer, numberOfColumns As Integer)", REALconsoleSafe },
	{ (REALproc) NewMatrixS, REALnoImplementation, "Constructor(numberOfRows As Integer, numberOfColumns As Integer, matrixString As String)", REALconsoleSafe },
	{ (REALproc) MatrixOut, REALnoImplementation, "Str() As String", REALconsoleSafe },
	{ (REALproc) MatrixOut2, REALnoImplementation, "Str2() As String", REALconsoleSafe },
	{ (REALproc) Element, REALnoImplementation, "Element(rowIndex As Integer, columnIndex As Integer) As Double", REALconsoleSafe },
	{ (REALproc) MatrixNegate, REALnoImplementation, "Operator_Negate() As Matrix", REALconsoleSafe },
	{ (REALproc) AddMM, REALnoImplementation, "Operator_Add(x As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) AddMD, REALnoImplementation, "Operator_Add(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) AddMD, REALnoImplementation, "Operator_AddRight(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) AddMC, REALnoImplementation, "Operator_Add(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddMC, REALnoImplementation, "Operator_AddRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubMM, REALnoImplementation, "Operator_Subtract(x As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) SubMD, REALnoImplementation, "Operator_Subtract(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) SubDM, REALnoImplementation, "Operator_SubtractRight(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) SubMC, REALnoImplementation, "Operator_Subtract(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubCM, REALnoImplementation, "Operator_SubtractRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulMM, REALnoImplementation, "Operator_Multiply(x As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) MulDM, REALnoImplementation, "Operator_Multiply(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) MulDM, REALnoImplementation, "Operator_MultiplyRight(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) MulMC, REALnoImplementation, "Operator_Multiply(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulMC, REALnoImplementation, "Operator_MultiplyRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivMD, REALnoImplementation, "Operator_Divide(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) DivDM, REALnoImplementation, "Operator_DivideRight(x As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) DivMC, REALnoImplementation, "Operator_Divide(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivCM, REALnoImplementation, "Operator_DivideRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivMM, REALnoImplementation, "Operator_Divide(x As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) CompareMM, REALnoImplementation, "Operator_Compare(x As Matrix) As Integer", REALconsoleSafe },
	{ (REALproc) CompareM_CM, REALnoImplementation, "Operator_Compare(x As ComplexMatrix) As Integer", REALconsoleSafe },
	{ (REALproc)NumRowsR, REALnoImplementation, "NumRows() As Integer", REALconsoleSafe },
	{ (REALproc)NumColumnsR, REALnoImplementation, "NumColumns() As Integer", REALconsoleSafe },
};


REALclassDefinition MatrixClass = {
        kCurrentREALControlVersion,
        "Matrix",                    			// name of class
        nil,                                    // no superclasses
        sizeof(MatrixData),                      // size of our data
        0,																			// --reserved--
        (REALproc) MatrixConstructor,     				// constructor
        (REALproc) MatrixDestructor,							// destructor
        nil,            												// properties
        0,																			// property count
        MatrixMethods,               					// methods
        sizeof(MatrixMethods) / sizeof(REALmethodDefinition),	// method count
        // other fields left nil -- no events etc.
};

// the following pragma is essential here (?)

#pragma mark -

/*
static REALobject NewMatrix(long numberOfRows, long numberOfColumns)
{
	MatrixData		*zData;
	REALobject		z;
	long			i, j;
		
	z = REALnewInstance("Matrix");
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = numberOfRows;
	zData->nc = numberOfColumns;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = 0;
			
	return z;
	
}*//* NewMatrix */


/* uses input format "1,2,3;4,5,6" */
static REALobject CreateMatrixS(long numberOfRows, long numberOfColumns, REALstring MStr)
{
	MatrixData		*zData;
	long			i, j, k, r, kd, rd, length, rowLength;
	char			*dataString, *rowString, *doubleString, ch;
	double			theDouble;
	Boolean			endOfData, endOfRowData;
	REALobject		z;
    REALstringData  *outData;
	
	endOfData = false;
	
	kd = 0;
	
	
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	if (zData == nil || numberOfRows<=0 || numberOfColumns<=0)
		return z;
	
	zData->nr = numberOfRows;
	zData->nc = numberOfColumns;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
    
    outData = new REALstringData();
    if(!REALGetStringData(MStr, kREALTextEncodingUTF8, outData))
    {
        for(i=0;i<zData->nr;i++)
            for(j=0;j<zData->nc;j++)
                (zData->array)[i][j] = 0;
        REALDisposeStringData(outData);
        return z;
    }

		
	// now get the matrix elements from MStr
	//length = MStr->Length();
	length = outData->length;
	// if length==0 make it a null matrix and return
	if(length==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
				(zData->array)[i][j] = 0;
        REALDisposeStringData(outData);
		return z;
	}

	// length!=0
	dataString = (char *)malloc((length+1)*sizeof(char));
	rowString = (char *)malloc((length+1)*sizeof(char));
	doubleString = (char *)malloc((length+1)*sizeof(char));
	memcpy(dataString, outData->data, length); // to, from
	dataString[length] = 0; // makes it a C string
    REALDisposeStringData(outData);
	
	// for example, a 2 x 3 matrix string would look like: "1,2,3;4,5,6"
	k = 0; // start index of dataString
	for(i=0;i<zData->nr;i++)
	{
		if(k>=length)
			endOfData = true;
			
		if(!endOfData)
		{
			r = 0; // start index of rowString
			// get ith row as rowString, read to ; or end of dataString
			ch = dataString[k];
			while(k<length && ch!=';')
			{
				rowString[r] = ch;
				r++;
				k++;
				ch = dataString[k];
			}
			rowString[r] = 0;
			rowLength = strlen(rowString);
			if(rowLength==0)
				endOfRowData = true;
			else
				endOfRowData = false;
			
			// now either ch==';' or ch==0 because we've reached the end of dataString
			k++; // skip over ";" if necessary
				
			kd = 0; // start index of rowString
		}
		for(j=0;j<zData->nc;j++)
		{
			if(!endOfRowData && !endOfData)
			{
				rd = 0; // start index of doubleString
				// get jth double string as doubleString, read to , or end of rowString
				ch = rowString[kd];
				while(kd<rowLength && ch!=',')
				{
					doubleString[rd] = ch;
					rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				doubleString[rd] = 0;
				
				if(kd>=rowLength)
					endOfRowData = true;
				else
					kd++; // skip over ","
					
				if(!(sscanf(doubleString, "%lf", &theDouble)==1))
					theDouble = 0;

				(zData->array)[i][j] = theDouble;
			}
			else
				(zData->array)[i][j] = 0;
		}
		
	}
	
	free(dataString);
	free(rowString);
	free(doubleString);
	
	return z;
	
}/* CreateMatrixS */



static REALobject ChangeElement(REALobject theMatrix, long rowIndex, long columnIndex, double value)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || rowIndex>=data->nr || columnIndex>=data->nc || rowIndex<0 || columnIndex<0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	if(zData==nil)
		return theMatrix;
		
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j];
		
	(zData->array)[rowIndex][columnIndex] = value;
	
	return z;
	
}/* ChangeElement */


static void NewElement(REALobject theMatrix, long rowIndex, long columnIndex, double value)
{
	MatrixData		*data;
	
	if(theMatrix==nil)
		return;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || rowIndex>=data->nr || columnIndex>=data->nc || rowIndex<0 || columnIndex<0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return;
	}
		
	(data->array)[rowIndex][columnIndex] = value;
	
}/* NewElement */


static REALobject Inverse(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	double			determinant;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j];
			
	determinant = matinv(zData->array, zData->nr);
	
	if(determinant==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
				(zData->array)[i][j] = 0;
	}
		
	return z;
	
}/* Inverse */


static REALobject InverseDet(REALobject theMatrix, double& determinant)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j];
			
	determinant = matinv(zData->array, zData->nr);
	
	if(determinant==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
				(zData->array)[i][j] = 0;
	}
		
	return z;
	
}/* InverseDet */


static double Determinant(REALobject theMatrix)
{
	MatrixData		*data;
	long			i, j;
	double			**array, determinant;
	
	if(theMatrix==nil)
		return NAN;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return NAN;
	}
	
	array = (double **)malloc(data->nr*sizeof(double *));
	for (i=0;i<data->nr;i++)
		array[i] = (double *)malloc(data->nc*sizeof(double));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			array[i][j] = (data->array)[i][j];
			
	determinant = matinv(array, data->nr);
	
	for (i=0;i<data->nr;i++)
		free(array[i]);
		
	free(array);
		
	return determinant;
	
}/* Determinant */


static REALobject Transpose(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return theMatrix;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nc;
	zData->nc = data->nr;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[j][i];
		
	return z;
	
}/* Transpose */


static REALobject Diagonalize(REALobject theMatrix, REALobject EigenvectorMatrix, double eps)
{
	MatrixData		*data, *zData, *EData;
	REALobject		z;
	long			i,j;
	
	if(theMatrix==nil)
		return theMatrix;
	
	if(EigenvectorMatrix==nil)
		return theMatrix;
	
	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	EData = (MatrixData *) REALGetClassData(EigenvectorMatrix, &MatrixClass);
	
	if (EData == nil || data == nil || data->nr!=data->nc || data->nr<=1 || EData->nr!=data->nr ||  EData->nc!=data->nc || eps<=0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			(zData->array)[i][j] = (data->array)[i][j];
	
	/*
	EigenvectorMatrix = REALnewInstance("Matrix");
	EData = (MatrixData *) REALGetClassData(EigenvectorMatrix, &MatrixClass);
	EData->nr = data->nr;
	EData->nc = data->nc;
	EData->array = (double **)malloc(EData->nr*sizeof(double *));
	for(i=0;i<EData->nr;i++)
		(EData->array)[i] = (double *)malloc(EData->nc*sizeof(double));
	*/
		
	diags(zData->array, EData->array, zData->nr, eps);
	
	// make z matrix symmetric
	/*
	for(i=0;i<zData->nr;i++)
		for(j=i+1;j<zData->nc;j++)
			(zData->array)[j][i] = (zData->array)[i][j];
	*/
	
	return z;
	
}/* Diagonalize */


static REALobject SqrM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
			
	mySqr(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SqrM */


static REALobject ExpM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
			
	myExp(zData->array, data->array, zData->nr);
		
	return z;
	
}/* ExpM */


static REALobject SinM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;

	if(theMatrix==nil)
		return theMatrix;
		
	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	mySin(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SinM */


static REALobject CosM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	myCos(zData->array, data->array, zData->nr);
		
	return z;
	
}/* CosM */


static REALobject TanM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	myTan(zData->array, data->array, zData->nr);
		
	return z;
	
}/* TanM */


static REALobject SinhM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	mySinh(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SinhM */


static REALobject CoshM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	myCosh(zData->array, data->array, zData->nr);
		
	return z;
	
}/* CoshM */


static REALobject TanhM(REALobject theMatrix)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
			
	myTanh(zData->array, data->array, zData->nr);
		
	return z;
	
}/* TanhM */


static REALobject Commutator(REALobject x, REALobject y)
{
	MatrixData		*xData, *yData, *zData;
	REALobject		z;
	long			i;
	
	if(x==nil)
		return x;
		
	if(y==nil)
		return y;
		
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	yData = (MatrixData *) REALGetClassData(y, &MatrixClass);
	
	if(xData==nil || yData==nil || xData->nr!=xData->nc || yData->nr!=yData->nc || xData->nr!=yData->nr || xData->nr<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return x;
	}
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
		
	myCommutator(zData->array, xData->array, yData->array, zData->nr);
	
	return z;
		
}/* Commutator */


static REALobject PowerM(REALobject theMatrix, long n)
{
	MatrixData		*data, *zData;
	REALobject		z;
	long			i;
	
	if(theMatrix==nil)
		return theMatrix;
	
	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
	
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (double *)malloc(zData->nc*sizeof(double));
	
	myPower(zData->array, data->array, n, zData->nr);
	
	return z;
	
}/* PowerM */


static REALmethodDefinition otherMatrixMethods[] = {
	{ (REALproc) CreateMatrixS, REALnoImplementation, "CreateMatrix(numberOfRows As Integer, numberOfColumns As Integer, inputString As String) As Matrix", REALconsoleSafe },
	{ (REALproc) ChangeElement, REALnoImplementation, "ChangeElement(theMatrix As Matrix, rowIndex As Integer, columnIndex As Integer, value As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) NewElement, REALnoImplementation, "NewElement(theMatrix As Matrix, rowIndex As Integer, columnIndex As Integer, value As Double)", REALconsoleSafe },
	{ (REALproc) Inverse, REALnoImplementation, "Inverse(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) InverseDet, REALnoImplementation, "Inverse(theMatrix As Matrix, ByRef theDeterminant As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) Determinant, REALnoImplementation, "Determinant(theMatrix As Matrix) As Double", REALconsoleSafe },
	{ (REALproc) Transpose, REALnoImplementation, "Transpose(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) Diagonalize, REALnoImplementation, "Diagonalize(theMatrix As Matrix, EigenvectorMatrix As Matrix, eps As Double) As Matrix", REALconsoleSafe },
	{ (REALproc) SqrM, REALnoImplementation, "Sqr(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) ExpM, REALnoImplementation, "Exp(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) SinM, REALnoImplementation, "Sin(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) CosM, REALnoImplementation, "Cos(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) TanM, REALnoImplementation, "Tan(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) SinhM, REALnoImplementation, "Sinh(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) CoshM, REALnoImplementation, "Cosh(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) TanhM, REALnoImplementation, "Tanh(theMatrix As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) Commutator, REALnoImplementation, "Commutator(x As Matrix, y As Matrix) As Matrix", REALconsoleSafe },
	{ (REALproc) PowerM, REALnoImplementation, "Power(theMatrix As Matrix, n As Integer) As Matrix", REALconsoleSafe },
	{ (REALproc)NumRowsR, REALnoImplementation, "NumRows(theMatrix As Matrix) As Integer", REALconsoleSafe },
	{ (REALproc)NumColumnsR, REALnoImplementation, "NumColumns(theMatrix As Matrix) As Integer", REALconsoleSafe },
};


/*
typedef struct
{
	Complex		**array;
	long			nr;	// number of rows
	long			nc;	// number of columns
	
} ComplexMatrixData;
*/


//extern REALclassDefinition		ComplexMatrixClass;


static void ComplexMatrixConstructor(REALobject instance)
{
	ComplexMatrixData		*data;
	
	// Get the class data
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil)
		return;
		
	data->array = nil;
	data->nr = 0;
	data->nc = 0;
	
}/* ComplexMatrixConstructor */


static void NewComplexMatrix(REALobject instance, long numberOfRows, long numberOfColumns)
{
	ComplexMatrixData		*data;
	long					i, j;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || numberOfRows<=0 || numberOfColumns<=0)
		return;
	
	data->nr = numberOfRows;
	data->nc = numberOfColumns;
	data->array = (Complex **)malloc(data->nr*sizeof(Complex *));
	for (i=0;i<data->nr;i++)
		(data->array)[i] = (Complex *)malloc(data->nc*sizeof(Complex));
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			data->array[i][j].Re = 0;
			data->array[i][j].Im = 0;
		}
	
}/* NewComplexMatrix */


static void NewComplexMatrixS(REALobject instance, long numberOfRows, long numberOfColumns, REALstring CMStr)
{
	ComplexMatrixData		*data;
	long			i, j, k, r, kd, rd, length, rowLength;
	char			*dataString, *rowString, *doubleString, ch, CR=0x0D, SP=0x20, LF=0x0A, TAB=0x09;
	double			theDouble;
	Boolean			endOfData, endOfRowData, areInNumber;
    REALstringData  *outData;
	
	endOfData = false;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || numberOfRows<=0 || numberOfColumns<=0)
		return;
		
	data->nr = numberOfRows;
	data->nc = numberOfColumns;
	data->array = (Complex **)malloc(data->nr*sizeof(Complex *));
	for (i=0;i<data->nr;i++)
		(data->array)[i] = (Complex *)malloc(data->nc*sizeof(Complex));
	
    outData = new REALstringData();
    if(!REALGetStringData(CMStr, kREALTextEncodingUTF8, outData))
    {
        for(i=0;i<data->nr;i++)
            for(j=0;j<data->nc;j++)
            {
                data->array[i][j].Re = 0;
                data->array[i][j].Im = 0;
            }
        REALDisposeStringData(outData);
        return;
    }
    
	// now get the matrix elements from MStr
	//length = CMStr->Length();
    length = outData->length;
	
	// if length==0 make it a null matrix and return
	if(length==0)
	{
		for(i=0;i<data->nr;i++)
			for(j=0;j<data->nc;j++)
			{
				data->array[i][j].Re = 0;
				data->array[i][j].Im = 0;
			}
		return;
	}
	
	// length!=0
	dataString = (char *)malloc((length+1)*sizeof(char));
	rowString = (char *)malloc((length+1)*sizeof(char));
	doubleString = (char *)malloc((length+1)*sizeof(char));
	memcpy(dataString, outData->data, length); // to, from
	dataString[length] = 0; // makes it a C string
    REALDisposeStringData(outData);
	
	/*
		for example, a 2 x 3 matrix string could look like:
		1,2 2,0 3,4
		4,5 5,6 6,7
		
		or like this
		1,2 2,0 3,4 ; 4,5 5,6 6,7
		
		Mac newline = 0xD (CR), Win32 newline = 0xD 0xA (CR LF), Unix newline = 0xA (LF)
	*/
	
	k = 0; // start index of dataString
	for(i=0;i<data->nr;i++)
	{
		if(k>=length)
			endOfData = true;
			
		if(!endOfData)
		{
			r = 0; // start index of rowString
			// get ith row as rowString, read to CR or ';' or end of dataString
			ch = dataString[k];
			while(k<length && ch!=CR && ch!=LF && ch!=';')
			{
				rowString[r] = ch;
				r++;
				k++;
				ch = dataString[k];
			}
			rowString[r] = 0;
			rowLength = strlen(rowString);
			if(rowLength==0)
				endOfRowData = true;
			else
				endOfRowData = false;
				
			while(!(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
				ch = dataString[++k];
			
			// now either ch==';' or ch==0 because we've reached the end of dataString
			//k++; // skip over CR or ';' if necessary
			/*
			#if MYWIN32
				if(ch!=';')
					k++; // skip over LF if necessary
			#endif
			*/
				
			kd = 0; // start index of rowString
		}
		for(j=0;j<data->nc;j++)
		{
			if(!endOfRowData && !endOfData)
			{
				areInNumber = false;
				rd = 0; // start index of doubleString
				// get jth double string as doubleString, read to , or SP or end of rowString
				ch = rowString[kd];
				
				while(kd<rowLength && !(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
				{
					//doubleString[rd] = ch;
					//rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				// now into real number part, go until comma
				while(kd<rowLength && !(ch==','))
				{
					doubleString[rd] = ch;
					rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				doubleString[rd] = 0;
				
				if(kd>=rowLength)
					endOfRowData = true;
					
				if(!(sscanf(doubleString, "%lf", &theDouble)==1))
					theDouble = 0;

				data->array[i][j].Re = theDouble;
			}
			else
				data->array[i][j].Re = 0;
				
			if(!endOfRowData && !endOfData)
			{
				areInNumber = false;
				rd = 0; // start index of doubleString
				// get jth double string as doubleString, read to , or SP or end of rowString
				ch = rowString[kd];
				
				while(kd<rowLength && !(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
				{
					//doubleString[rd] = ch;
					//rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				// now into imaginary number part, go until whitespace
				while(kd<rowLength && !(ch==SP || ch==TAB))
				{
					doubleString[rd] = ch;
					rd++;
					kd++;
					ch = rowString[kd]; 
				}
				
				doubleString[rd] = 0;
				
				if(kd>=rowLength)
					endOfRowData = true;
					
				if(!(sscanf(doubleString, "%lf", &theDouble)==1))
					theDouble = 0;

				data->array[i][j].Im = theDouble;
			}
			else
				data->array[i][j].Im = 0;
		}
	}
	
	free(dataString);
	free(rowString);
	free(doubleString);
	
}/* NewComplexMatrixS */


static void ComplexMatrixDestructor(REALobject instance)
{
	ComplexMatrixData		*data;
	long					i;
	
	if(instance==nil)
		return;
	
	// Get the class data
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || data->array==nil)
		return;
	
	for (i=0;i<data->nr;i++)
		free((data->array)[i]);
		
	free(data->array);
	
}/* ComplexMatrixDestructor */


static REALstring ComplexMatrixOut(REALobject instance)
{
	ComplexMatrixData		*data;
	char					*myString, ***complexStringMatrix, CR=0x0D, SP=0x20, LF=0x0A;
	long					i, j, k, length, len, diffLen;
	char					formatString1[15], formatString2[15], formatString3[15], formatString4[15], precString[5];
	
	//REALstring nullString = REALBuildString (nil, 0);
	
	if(instance==nil)
		return nullString;
		
	sprintf(precString, "%d", myPrecision);
		
	strcpy(formatString1, " %.");
	strcat(formatString1, precString);
	strcat(formatString1, "g,%.");
	strcat(formatString1, precString);
	strcat(formatString1, "g  ");
	
	strcpy(formatString2, "%.");
	strcat(formatString2, precString);
	strcat(formatString2, "g,%.");
	strcat(formatString2, precString);
	strcat(formatString2, "g  ");
	
	strcpy(formatString3, " %.");
	strcat(formatString3, precString);
	strcat(formatString3, "g,%.");
	strcat(formatString3, precString);
	strcat(formatString3, "g");
	
	strcpy(formatString4, "%.");
	strcat(formatString4, precString);
	strcat(formatString4, "g,%.");
	strcat(formatString4, precString);
	strcat(formatString4, "g");
	
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	if(data==nil || data->nr<1 || data->nc<1)
		return nullString;
		
	length = 50; // length of string complex should be less than this
	
	complexStringMatrix = (char ***)malloc(data->nr*sizeof(char **));
	for (i=0;i<data->nr;i++)
		complexStringMatrix[i] = (char **)malloc(data->nc*sizeof(char*));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			complexStringMatrix[i][j] = (char *)malloc(length*sizeof(char));
			
	// put complex numbers into complexStringMatrix
	// if real part is positive put one space at start, so negatives will align with positives in a column
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			if(j<(data->nc-1))
			{
				if(data->array[i][j].Re>=0)
					sprintf(complexStringMatrix[i][j],formatString1, data->array[i][j].Re, data->array[i][j].Im);
				else
					sprintf(complexStringMatrix[i][j],formatString2, data->array[i][j].Re, data->array[i][j].Im);
			}
			else
			{
				if(data->array[i][j].Re>=0)
					sprintf(complexStringMatrix[i][j],formatString3, data->array[i][j].Re, data->array[i][j].Im);
				else
					sprintf(complexStringMatrix[i][j],formatString4, data->array[i][j].Re, data->array[i][j].Im);
			}
				
			
	// find the largest strlen
	length = 0;
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			len = strlen(complexStringMatrix[i][j]);
			if(len>length)
				length = len;
		}
		
	// now pad each complex string on right so it has length as its strlen, except for the last column
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<(data->nc-1);j++)
		{
			len = strlen(complexStringMatrix[i][j]);
			diffLen = length - len;
			for(k=0;k<diffLen;k++)
				complexStringMatrix[i][j][len+k] = SP;
				
			complexStringMatrix[i][j][length] = 0;
		}		
	
	length = 50*data->nr*data->nc + data->nr + 1; // estimate of maximum length of C string returned
	
	myString = (char *)malloc(length*sizeof(char));
	myString[0] = 0;
	
	// load up myString
	for(i=0;i<data->nr;i++)
	{
		for(j=0;j<data->nc;j++)
			strcat(myString, complexStringMatrix[i][j]);
		
		len = strlen(myString);
		myString[len] = CR;
		
		#if MYWIN32
			myString[++len] = LF;
		#endif
		myString[++len] = 0;
	}
	
	length = strlen(myString);
	
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	
	
	free(myString);
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			free(complexStringMatrix[i][j]);
			
	for(i=0;i<data->nr;i++)
		free(complexStringMatrix[i]);
		
	free(complexStringMatrix);
	
	return str;
	
}/* ComplexMatrixOut */


static REALstring ComplexMatrixOut2(REALobject instance)
{
	ComplexMatrixData		*data;
	char					*myString, ***complexStringMatrix, CR=0x0D, SP=0x20, LF=0x0A;
	long					i, j, length, len;
	char					formatString1[10], formatString[15], precString[5];
	
	//REALstring nullString = REALBuildString (nil, 0);
	
	if(instance==nil)
		return nullString;
		
	strcpy(formatString1, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatString1, precString);
	strcat(formatString1, "g");
	
	strcpy(formatString, formatString1);
	strcat(formatString, ",");
	strcat(formatString, formatString1);
	strcat(formatString, " ");
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	if(data==nil || data->nr<1 || data->nc<1)
		return nullString;
		
	length = 50; // length of string complex should be less than this
	
	complexStringMatrix = (char ***)malloc(data->nr*sizeof(char **));
	for (i=0;i<data->nr;i++)
		complexStringMatrix[i] = (char **)malloc(data->nc*sizeof(char*));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			complexStringMatrix[i][j] = (char *)malloc(length*sizeof(char));
			
	// put complex numbers into complexStringMatrix
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			sprintf(complexStringMatrix[i][j],formatString, data->array[i][j].Re, data->array[i][j].Im);
	
	length = 50*data->nr*data->nc + data->nr + 1; // estimate of maximum length of C string returned
	
	myString = (char *)malloc(length*sizeof(char));
	myString[0] = 0;
	
	// load up myString
	for(i=0;i<data->nr;i++)
	{
		for(j=0;j<data->nc;j++)
			strcat(myString, complexStringMatrix[i][j]);
		
		len = strlen(myString);
		if(i!=data->nr-1)
		{
			myString[len] = ';';
			myString[++len] = ' ';
			myString[++len] = 0;
		}
	}
	
	length = strlen(myString);
	
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	
	
	free(myString);
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			free(complexStringMatrix[i][j]);
			
	for(i=0;i<data->nr;i++)
		free(complexStringMatrix[i]);
		
	free(complexStringMatrix);
	
	return str;
	
}/* ComplexMatrixOut2 */


static REALobject CMReal(REALobject instance)
{
	ComplexMatrixData		*data;
	MatrixData				*zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
	{
		return instance;
	}
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			zData->array[i][j] = data->array[i][j].Re;
		
	return z;
	
}/* CMReal */


static REALobject CMImag(REALobject instance)
{
	ComplexMatrixData		*data;
	MatrixData				*zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
	{
		return instance;
	}
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("Matrix");
    z = REALnewInstanceWithClass(globalMatrixRef);
	zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	
	zData->array = (double **)malloc(zData->nr*sizeof(double *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
			zData->array[i][j] = data->array[i][j].Im;
		
	return z;
	
}/* CMImag */


static REALobject CMElement(REALobject instance, long i, long j)
{
	ComplexMatrixData		*data;
	Complex					*zData;
	REALobject				z;
	
	if(instance==nil)
		return ComplexObjectNAN();
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || i>=data->nr || j>=data->nc || i<0 || j<0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return ComplexObjectNAN();
	}
		
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	zData->Re = data->array[i][j].Re;
	zData->Im = data->array[i][j].Im;
	
	return z;
	
}/* CMElement */


static REALobject CMatrixNegate(REALobject instance)
{
	ComplexMatrixData		*data, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	
	zData->array = (Complex **)malloc(data->nr*sizeof(Complex *));
	for (i=0;i<data->nr;i++)
		(zData->array)[i] = (Complex *)malloc(data->nc*sizeof(Complex));
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			zData->array[i][j].Re = -data->array[i][j].Re;
			zData->array[i][j].Im = -data->array[i][j].Im;
		}
			
	return z;
	
}/* CMatrixNegate */


static REALobject AddCM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re + xData->array[i][j].Re;
			zData->array[i][j].Im = data->array[i][j].Im + xData->array[i][j].Im;
		}
			
	return z;
	
}/* AddCM_CM */


static REALobject AddCM_M(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re + xData->array[i][j];
			zData->array[i][j].Im = data->array[i][j].Im;
		}
			
	return z;
	
}/* AddCM_M */


static REALobject AddCM_C(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			if(i!=j)
			{
				zData->array[i][j].Re = data->array[i][j].Re;
				zData->array[i][j].Im = data->array[i][j].Im;
			}
			else
			{
				zData->array[i][j].Re = data->array[i][j].Re + xData->Re;
				zData->array[i][j].Im = data->array[i][j].Im + xData->Im;
			}
		}
			
	return z;
	
}/* AddCM_C */


static REALobject AddCM_D(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Im = data->array[i][j].Im;
			if(i!=j)
				zData->array[i][j].Re = data->array[i][j].Re;
			else
				zData->array[i][j].Re = data->array[i][j].Re + x;
		}
			
	return z;
	
}/* AddCM_D */


static REALobject SubCM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *xData, *zData;
	REALobject		z;
	long			i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re - xData->array[i][j].Re;
			zData->array[i][j].Im = data->array[i][j].Im - xData->array[i][j].Im;
		}
			
	return z;
	
}/* SubCM_CM */


static REALobject SubCM_M(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re - xData->array[i][j];
			zData->array[i][j].Im = data->array[i][j].Im;
		}
			
	return z;
	
}/* SubCM_M */


static REALobject SubM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nr!=data->nr || xData->nc!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = -data->array[i][j].Re + xData->array[i][j];
			zData->array[i][j].Im = -data->array[i][j].Im;
		}
			
	return z;
	
}/* SubM_CM */


static REALobject SubCM_C(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			if(i!=j)
			{
				zData->array[i][j].Re = data->array[i][j].Re;
				zData->array[i][j].Im = data->array[i][j].Im;
			}
			else
			{
				zData->array[i][j].Re = data->array[i][j].Re - xData->Re;
				zData->array[i][j].Im = data->array[i][j].Im - xData->Im;
			}
		}
			
	return z;
	
}/* SubCM_C */


static REALobject SubC_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex				*xData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil || x==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			if(i!=j)
			{
				zData->array[i][j].Re = -data->array[i][j].Re;
				zData->array[i][j].Im = -data->array[i][j].Im;
			}
			else
			{
				zData->array[i][j].Re = -data->array[i][j].Re + xData->Re;
				zData->array[i][j].Im = -data->array[i][j].Im + xData->Im;
			}
		}
			
	return z;
	
}/* SubC_CM */


static REALobject SubCM_D(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Im = data->array[i][j].Im;
			if(i!=j)
				zData->array[i][j].Re = data->array[i][j].Re;
			else
				zData->array[i][j].Re = data->array[i][j].Re - x;
		}
			
	return z;
	
}/* SubCM_D */


static REALobject SubD_CM(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Im = -data->array[i][j].Im;
			if(i!=j)
				zData->array[i][j].Re = -data->array[i][j].Re;
			else
				zData->array[i][j].Re = -data->array[i][j].Re + x;
		}
			
	return z;
	
}/* SubD_CM */


static REALobject MulCM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *xData, *zData;
	REALobject				z;
	long					i, j, k;
	Complex				temp;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			for(k=0;k<data->nc;k++)
			{
				complexMultiply(temp, data->array[i][k], xData->array[k][j]);
				zData->array[i][j].Re = zData->array[i][j].Re + temp.Re;
				zData->array[i][j].Im = zData->array[i][j].Im + temp.Im;
			}
		}
    
    // we cannot have any extremely small but non-zero elements
    for(i=0;i<zData->nr;++i)
    {
        for(j=0;j<zData->nc;++j)
        {
            if(dabs(zData->array[i][j].Re)<zeroDouble)
                zData->array[i][j].Re = 0;
            
            if(dabs(zData->array[i][j].Im)<zeroDouble)
                zData->array[i][j].Im = 0;
        }
    }
			
	return z;
	
}/* MulCM_CM */


static REALobject MulCM_M(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j, k;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			for(k=0;k<data->nc;k++)
			{
				zData->array[i][j].Re = zData->array[i][j].Re + data->array[i][k].Re*xData->array[k][j];
				zData->array[i][j].Im = zData->array[i][j].Im + data->array[i][k].Im*xData->array[k][j];
			}
		}
    
    // we cannot have any extremely small but non-zero elements
    for(i=0;i<zData->nr;++i)
    {
        for(j=0;j<zData->nc;++j)
        {
            if(dabs(zData->array[i][j].Re)<zeroDouble)
                zData->array[i][j].Re = 0;
            
            if(dabs(zData->array[i][j].Im)<zeroDouble)
                zData->array[i][j].Im = 0;
        }
    }
			
	return z;
	
}/* MulCM_M */


static REALobject MulM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j, k;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nc!=data->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			for(k=0;k<xData->nc;k++)
			{
				zData->array[i][j].Re = zData->array[i][j].Re + xData->array[i][k]*data->array[k][j].Re;
				zData->array[i][j].Im = zData->array[i][j].Im + xData->array[i][k]*data->array[k][j].Im;
			}
		}
    
    // we cannot have any extremely small but non-zero elements
    for(i=0;i<zData->nr;++i)
    {
        for(j=0;j<zData->nc;++j)
        {
            if(dabs(zData->array[i][j].Re)<zeroDouble)
                zData->array[i][j].Re = 0;
            
            if(dabs(zData->array[i][j].Im)<zeroDouble)
                zData->array[i][j].Im = 0;
        }
    }
			
	return z;
	
}/* MulM_CM */


static REALobject MulCM_C(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex				*xData, temp;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			complexMultiply(temp, data->array[i][j], *xData);
			zData->array[i][j].Re = temp.Re;
			zData->array[i][j].Im = temp.Im;
		}
			
	return z;
	
}/* MulCM_C */


static REALobject MulCM_D(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = x*data->array[i][j].Re;
			zData->array[i][j].Im = x*data->array[i][j].Im;
		}
			
	return z;
	
}/* MulCM_D */


static REALobject DivCM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *xData, *zData;
	REALobject				z;
	long					i, j, k;
	Complex				**array, determinant, temp;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nc!=xData->nr || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	array = (Complex **)malloc(xData->nr*sizeof(Complex *));
	for (i=0;i<xData->nr;i++)
		array[i] = (Complex *)malloc(xData->nc*sizeof(Complex));
		
	for(i=0;i<xData->nr;i++)
		for(j=0;j<xData->nc;j++)
		{
			array[i][j].Re = xData->array[i][j].Re;
			array[i][j].Im = xData->array[i][j].Im;
		}
			
	determinant = cmatinv(array, xData->nr);
	
	if(determinant.Re==0 && determinant.Im==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			
			for(k=0;k<xData->nc;k++)
			{
				complexMultiply(temp, data->array[i][k], array[k][j]);
				zData->array[i][j].Re = zData->array[i][j].Re + temp.Re;
				zData->array[i][j].Im = zData->array[i][j].Im + temp.Im;
			}
		}
			
	for(i=0;i<xData->nr;i++)
		free(array[i]);
		
	free(array);
			
	return z;
	
}/* DivCM_CM */


//instance is CM, x is M
static REALobject DivCM_M(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j, k;
	//Complex				temp;
	double					**array, determinant;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || xData->nc!=xData->nr || data->nc!=xData->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	array = (double **)malloc(xData->nr*sizeof(double *));
	for (i=0;i<xData->nr;i++)
		array[i] = (double *)malloc(xData->nc*sizeof(double));
		
	for(i=0;i<xData->nr;i++)
		for(j=0;j<xData->nc;j++)
		{
			array[i][j] = xData->array[i][j];
		}
			
	determinant = matinv(array, xData->nr);
	
	if(determinant==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			
			for(k=0;k<xData->nc;k++)
			{
				zData->array[i][j].Re = zData->array[i][j].Re + data->array[i][k].Re*array[k][j];
				zData->array[i][j].Im = zData->array[i][j].Im + data->array[i][k].Im*array[k][j];
			}
		}
			
	for(i=0;i<xData->nr;i++)
		free(array[i]);
		
	free(array);
			
	return z;
	
}/* DivCM_M */


//instance is CM, x is M. Doing inverse of instance
static REALobject DivM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i, j, k;
	Complex				**array, determinant;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || data->nc!=data->nr || xData->nc!=data->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
		
	array = (Complex **)malloc(data->nr*sizeof(Complex *));
	for (i=0;i<data->nr;i++)
		array[i] = (Complex *)malloc(data->nc*sizeof(Complex));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			array[i][j].Re = data->array[i][j].Re;
			array[i][j].Im = data->array[i][j].Im;
		}
			
	determinant = cmatinv(array, data->nr);
	
	if(determinant.Re==0 && determinant.Im==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = 0;
			zData->array[i][j].Im = 0;
			
			for(k=0;k<xData->nc;k++)
			{
				zData->array[i][j].Re = zData->array[i][j].Re + xData->array[i][k]*array[k][j].Re;
				zData->array[i][j].Im = zData->array[i][j].Im + xData->array[i][k]*array[k][j].Im;
			}
		}
			
	for(i=0;i<data->nr;i++)
		free(array[i]);
		
	free(array);
			
	return z;
	
}/* DivM_CM */


//instance is CM, x is Complex, instance/x
static REALobject DivCM_C(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex					*xData;
	REALobject				z;
	long					i, j;
	Complex					temp, one;
	
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return instance;
		
	if(xData->Re==0 && xData->Im==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	one.Re = 1;
	one.Im = 0;
	complexDivide(temp, one, *xData); // temp = 1/x
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			complexMultiply(zData->array[i][j], temp, data->array[i][j]);
		}
			
	return z;
	
}/* DivCM_C */


//instance is CM, x is C. Doing x/instance
static REALobject DivC_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *zData;
	Complex				*xData;
	REALobject				z;
	long					i, j;
	Complex				determinant;
	
	if(instance==nil)
		return instance;
		
	if(x==nil)
		return instance;
	
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil || data->nc!=data->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
	
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re;
			zData->array[i][j].Im = data->array[i][j].Im;
		}
		
	determinant = cmatinv(zData->array, zData->nr);
	
	if(determinant.Re==0 && determinant.Im==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			complexMultiply(zData->array[i][j], *xData, zData->array[i][j]);
		}
			
	return z;
	
}/* DivC_CM */


//instance is CM, x is double, instance/x
static REALobject DivCM_D(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	double					temp;
	
	
	if(instance==nil)
		return instance;
		
	if(x==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1)
		return instance;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	temp = 1/x;
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = temp*data->array[i][j].Re;
			zData->array[i][j].Im = temp*data->array[i][j].Im;
		}
			
	return z;
	
}/* DivCM_D */


//instance is CM, x is D. Doing x/instance
static REALobject DivD_CM(REALobject instance, double x)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	Complex				determinant;
	
	if(instance==nil)
		return instance;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || data->nc!=data->nr)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return instance;
	}
	
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j] = data->array[i][j];
		}
		
	determinant = cmatinv(zData->array, zData->nr);
	
	if(determinant.Re==0 && determinant.Im==0)
	{
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
		return instance;
	}
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = x*zData->array[i][j].Re;
			zData->array[i][j].Im = x*zData->array[i][j].Im;
		}
			
	return z;
	
}/* DivD_CM */


static long CompareCM_CM(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data, *xData;
	long					i, j;
	
	if(instance==nil)
		return 0;
		
	if(x==nil)
		return 0;
		
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return 0;
		
	if(data->nr != xData->nr || data->nc != xData->nc)
		return 1;
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			{
				if(data->array[i][j].Re < xData->array[i][j].Re)
					return -1;
					
				if(data->array[i][j].Re > xData->array[i][j].Re)
					return 1;
					
				if(data->array[i][j].Im < xData->array[i][j].Im)
					return -1;
					
				if(data->array[i][j].Im > xData->array[i][j].Im)
					return 1;
			}
				
	return 0;

}/* CompareCM_CM */


static long CompareCM_M(REALobject instance, REALobject x)
{
	ComplexMatrixData		*data;
	MatrixData				*xData;
	long					i, j;
	
	if(instance==nil)
		return 0;
		
	if(x==nil)
		return 0;
		
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if(data==nil || data->nr<1 || data->nc<1 || xData==nil)
		return 0;
		
	if(data->nr!=xData->nr || data->nc!=xData->nc)
		return 1;
	
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
			{
				if(data->array[i][j].Re < xData->array[i][j])
					return -1;
					
				if(data->array[i][j].Re > xData->array[i][j])
					return 1;
					
				if(data->array[i][j].Im < 0)
					return -1;
					
				if(data->array[i][j].Im > 0)
					return 1;
			}
				
	return 0;

}/* CompareCM_M */


static long NumRowsC(REALobject instance)
{
	ComplexMatrixData		*data;
	
	if(instance==nil)
		return 0;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil)
		return 0;
	
	return data->nr;
	
}/* NumRowsC */


static long NumColumnsC(REALobject instance)
{
	ComplexMatrixData		*data;
	
	if(instance==nil)
		return 0;
	
	data = (ComplexMatrixData *) REALGetClassData(instance, &ComplexMatrixClass);
	
	if (data == nil)
		return 0;
	
	return data->nc;
	
}/* NumColumnsC */


// REALbasic class & method definitions for the ComplexMatrix object

static REALmethodDefinition ComplexMatrixMethods[] = {
	// defines methods:
	{ (REALproc) ComplexMatrixConstructor, REALnoImplementation, "Constructor()", REALconsoleSafe },
	{ (REALproc) NewComplexMatrix, REALnoImplementation, "Constructor(numberOfRows As Integer, numberOfColumns As Integer)", REALconsoleSafe },
	{ (REALproc) NewComplexMatrixS, REALnoImplementation, "Constructor(numberOfRows As Integer, numberOfColumns As Integer,  ComplexMatrixString As String)", REALconsoleSafe },
	{ (REALproc) ComplexMatrixOut, REALnoImplementation, "Str() As String", REALconsoleSafe },
	{ (REALproc) ComplexMatrixOut2, REALnoImplementation, "Str2() As String", REALconsoleSafe },
	{ (REALproc) CMReal, REALnoImplementation, "Real() as Matrix", REALconsoleSafe },
	{ (REALproc) CMImag, REALnoImplementation, "Imag() as Matrix", REALconsoleSafe },
	{ (REALproc) CMElement, REALnoImplementation, "Element(rowIndex As Integer, columnIndex As Integer) As Complex", REALconsoleSafe },
	{ (REALproc) CMatrixNegate, REALnoImplementation, "Operator_Negate() As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_CM, REALnoImplementation, "Operator_Add(x As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_M, REALnoImplementation, "Operator_Add(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_M, REALnoImplementation, "Operator_AddRight(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_C, REALnoImplementation, "Operator_Add(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_C, REALnoImplementation, "Operator_AddRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_D, REALnoImplementation, "Operator_Add(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) AddCM_D, REALnoImplementation, "Operator_AddRight(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubCM_CM, REALnoImplementation, "Operator_Subtract(x As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubCM_M, REALnoImplementation, "Operator_Subtract(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubM_CM, REALnoImplementation, "Operator_SubtractRight(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubCM_C, REALnoImplementation, "Operator_Subtract(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubC_CM, REALnoImplementation, "Operator_SubtractRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubCM_D, REALnoImplementation, "Operator_Subtract(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SubD_CM, REALnoImplementation, "Operator_SubtractRight(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_CM, REALnoImplementation, "Operator_Multiply(x As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_M, REALnoImplementation, "Operator_Multiply(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulM_CM, REALnoImplementation, "Operator_MultiplyRight(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_C, REALnoImplementation, "Operator_Multiply(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_C, REALnoImplementation, "Operator_MultiplyRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_D, REALnoImplementation, "Operator_Multiply(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) MulCM_D, REALnoImplementation, "Operator_MultiplyRight(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivCM_CM, REALnoImplementation, "Operator_Divide(x As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivCM_M, REALnoImplementation, "Operator_Divide(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivM_CM, REALnoImplementation, "Operator_DivideRight(x As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivCM_C, REALnoImplementation, "Operator_Divide(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivC_CM, REALnoImplementation, "Operator_DivideRight(x As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivCM_D, REALnoImplementation, "Operator_Divide(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DivD_CM, REALnoImplementation, "Operator_DivideRight(x As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CompareCM_CM, REALnoImplementation, "Operator_Compare(x As ComplexMatrix) As Integer", REALconsoleSafe },
	{ (REALproc) CompareCM_M, REALnoImplementation, "Operator_Compare(x As Matrix) As Integer", REALconsoleSafe },
	{ (REALproc)NumRowsC, REALnoImplementation, "NumRows() As Integer", REALconsoleSafe },
	{ (REALproc)NumColumnsC, REALnoImplementation, "NumColumns() As Integer", REALconsoleSafe },
};


REALclassDefinition ComplexMatrixClass = {
        kCurrentREALControlVersion,
        "ComplexMatrix",                    			// name of class
        nil,                                    // no superclasses
        sizeof(ComplexMatrixData),                      // size of our data
        0,																			// --reserved--
        (REALproc) ComplexMatrixConstructor,     				// constructor
        (REALproc) ComplexMatrixDestructor,							// destructor
        nil,            												// properties
        0,																			// property count
        ComplexMatrixMethods,               					// methods
        sizeof(ComplexMatrixMethods) / sizeof(REALmethodDefinition),	// method count
        // other fields left nil -- no events etc.
};

// the following pragma is essential here (?)

#pragma mark -

// other ComplexMatrix methods


static REALobject ChangeElementCM(REALobject theMatrix, long rowIndex, long columnIndex, REALobject value)
{
	ComplexMatrixData		*data, *zData;
	Complex				*valueData;
	REALobject				z;
	long					i, j;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	valueData = (Complex *) REALGetClassData(value, &ComplexClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || valueData==nil || rowIndex>=data->nr || columnIndex>=data->nc || rowIndex<0 || columnIndex<0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	if(zData==nil)
		return theMatrix;
		
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j] = data->array[i][j];
		}
		
	zData->array[rowIndex][columnIndex] = *valueData;
	
	return z;
	
}/* ChangeElementCM */

// changes in place
static void NewElementCM(REALobject theMatrix, long rowIndex, long columnIndex, REALobject value)
{
	ComplexMatrixData		*data;
	Complex					*valueData;
	
	if(theMatrix==nil)
		return;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	valueData = (Complex *) REALGetClassData(value, &ComplexClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || valueData==nil || rowIndex>=data->nr || columnIndex>=data->nc || rowIndex<0 || columnIndex<0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return;
	}
		
	data->array[rowIndex][columnIndex] = *valueData;
	
}/* NewElementCM */


static REALobject CMInverse(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	Complex				determinant;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
		return theMatrix;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re;
			zData->array[i][j].Im = data->array[i][j].Im;
		}
			
	determinant = cmatinv(zData->array, zData->nr);
	
	if(determinant.Re==0 && determinant.Im==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
			{
				zData->array[i][j].Re = 0;
				zData->array[i][j].Im = 0;
			}
		REALobject err = REALnewInstance("DivideByZeroException");
		REALRaiseException(err);
	}
		
	return z;
	
}/* CMInverse */


static REALobject CMInverseDet(REALobject theMatrix, REALobject& determinant)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	Complex					*determinantData;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	determinantData = (Complex *) REALGetClassData(determinant, &ComplexClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || determinantData==nil || data->nr!=data->nc)
		return theMatrix;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = data->array[i][j].Re;
			zData->array[i][j].Im = data->array[i][j].Im;
		}
			
	*determinantData = cmatinv(zData->array, zData->nr);
	
	if(determinantData->Re==0 && determinantData->Im==0)
	{
		for(i=0;i<zData->nr;i++)
			for(j=0;j<zData->nc;j++)
			{
				zData->array[i][j].Re = 0;
				zData->array[i][j].Im = 0;
			}
	}
		
	return z;
	
}/* CMInverseDet */


static REALobject CMDeterminant(REALobject theMatrix)
{
	ComplexMatrixData		*data;
	long					i, j;
	Complex				**array, *determinantData;
	REALobject				determinant;
	
	if(theMatrix==nil)
		return ComplexObjectNAN();

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
		return ComplexObjectNAN();
		
	
	determinant = REALnewInstance("Complex");
	determinantData = (Complex *) REALGetClassData(determinant, &ComplexClass);
	
	array = (Complex **)malloc(data->nr*sizeof(Complex *));
	for (i=0;i<data->nr;i++)
		array[i] = (Complex *)malloc(data->nc*sizeof(Complex));
		
	for(i=0;i<data->nr;i++)
		for(j=0;j<data->nc;j++)
		{
			array[i][j].Re = data->array[i][j].Re;
			array[i][j].Im = data->array[i][j].Im;
		}
			
	*determinantData = cmatinv(array, data->nr);
	
	for (i=0;i<data->nr;i++)
		free(array[i]);
		
	free(array);
		
	return determinant;
	
}/* CMDeterminant */


static REALobject CMTranspose(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i, j;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1)
		return theMatrix;
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nc;
	zData->nc = data->nr;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j] = data->array[j][i];
		}
		
	return z;
	
}/* CMTranspose */


static REALobject SqrCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	mySqrCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SqrCM */


static REALobject SqrtCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	mySqrtCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SqrtCM */


static REALobject SqrtM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	mySqrtM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SqrtM */


static REALobject ExpCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myExpCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* ExpCM */


static REALobject LogCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myLogCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* LogCM */


static REALobject LogM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myLogM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* LogM */


static REALobject SinCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	mySinCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SinCM */


static REALobject CosCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myCosCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* CosCM */


static REALobject TanCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myTanCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* TanCM */


static REALobject aSinCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myASinCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aSinCM */


static REALobject aCosCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myACosCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aCosCM */


static REALobject aTanCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myATanCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aTanCM */


static REALobject aSinM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myASinM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aSinM */


static REALobject aCosM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myACosM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aCosM */


static REALobject aTanM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myATanM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aTanM */


static REALobject SinhCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	mySinhCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* SinhCM */


static REALobject CoshCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myCoshCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* CoshCM */


static REALobject TanhCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myTanhCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* TanhCM */


static REALobject aSinhCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myASinhCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aSinhCM */


static REALobject aCoshCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myACoshCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aCoshCM */


static REALobject aTanhCM(REALobject theMatrix)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myATanhCM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aTanhCM */


static REALobject aSinhM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myASinhM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aSinhM */


static REALobject aCoshM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myACoshM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aCoshM */


static REALobject aTanhM(REALobject theMatrix)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myATanhM(zData->array, data->array, zData->nr);
		
	return z;
	
}/* aTanhM */


static REALobject PowCM_C(REALobject theMatrix, REALobject y)
{
	ComplexMatrixData		*data, *zData;
	Complex					*yData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (data == nil || yData==nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myPowCM_C(zData->array, data->array, *yData, zData->nr);
		
	return z;
	
}/* PowCM_C */


static REALobject PowCM_D(REALobject theMatrix, double y)
{
	ComplexMatrixData		*data, *zData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myPowCM_D(zData->array, data->array, y, zData->nr);
		
	return z;
	
}/* PowCM_D */


static REALobject PowM_C(REALobject theMatrix, REALobject y)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	Complex					*yData;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	yData = (Complex *) REALGetClassData(y, &ComplexClass);
	
	if (data == nil || yData==nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myPowM_C(zData->array, data->array, *yData, zData->nr);
		
	return z;
	
}/* PowM_C */


static REALobject PowM_D(REALobject theMatrix, double y)
{
	ComplexMatrixData		*zData;
	MatrixData				*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;

	data = (MatrixData *) REALGetClassData(theMatrix, &MatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
			
	myPowM_D(zData->array, data->array, y, zData->nr);
		
	return z;
	
}/* PowM_D */


static REALobject CommutatorCM_CM(REALobject x, REALobject y)
{
	ComplexMatrixData		*xData, *yData, *zData;
	REALobject				z;
	long					i;
	
	if(x==nil)
		return x;
		
	if(y==nil)
		return y;
		
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	yData = (ComplexMatrixData *) REALGetClassData(y, &ComplexMatrixClass);
	
	if(xData==nil || yData==nil || xData->nr!=xData->nc || yData->nr!=yData->nc || xData->nr!=yData->nr || xData->nr<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return x;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	myCommutatorCM_CM(zData->array, xData->array, yData->array, zData->nr);
	
	return z;
		
}/* CommutatorCM_CM */


static REALobject CommutatorCM_M(REALobject x, REALobject y)
{
	ComplexMatrixData		*xData, *zData;
	MatrixData				*yData;
	REALobject				z;
	long					i;
	
	if(x==nil)
		return x;
		
	if(y==nil)
		return x;
		
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	yData = (MatrixData *) REALGetClassData(y, &MatrixClass);
	
	if(xData==nil || yData==nil || xData->nr!=xData->nc || yData->nr!=yData->nc || xData->nr!=yData->nr || xData->nr<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return x;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	myCommutatorCM_M(zData->array, xData->array, yData->array, zData->nr);
	
	return z;
		
}/* CommutatorCM_M */


static REALobject CommutatorM_CM(REALobject x, REALobject y)
{
	ComplexMatrixData		*yData, *zData;
	MatrixData				*xData;
	REALobject				z;
	long					i;
	
	if(x==nil)
		return y;
		
	if(y==nil)
		return y;
		
	xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
	yData = (ComplexMatrixData *) REALGetClassData(y, &ComplexMatrixClass);
	
	if(xData==nil || yData==nil || xData->nr!=xData->nc || yData->nr!=yData->nc || xData->nr!=yData->nr || xData->nr<1)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return x;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	myCommutatorM_CM(zData->array, xData->array, yData->array, zData->nr);
	
	return z;
		
}/* CommutatorM_CM */


static REALobject ConjugateCM(REALobject x)
{
	ComplexMatrixData		*xData, *zData;
	REALobject				z;
	long					i, j;
	
	if(x==nil)
		return x;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	if (xData == nil)
		return x;
	
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nr;
	zData->nc = xData->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for(i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			zData->array[i][j].Re = xData->array[i][j].Re;
			zData->array[i][j].Im = -xData->array[i][j].Im;
		}
	
	return z;
	
}/* ConjugateCM */


static REALobject HConjugateCM(REALobject x)
{
	ComplexMatrixData		*xData, *zData;
	REALobject				z;
	long					i, j;
	
	if(x==nil)
		return x;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	if (xData == nil)
		return x;
	
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	zData->nr = xData->nc;
	zData->nc = xData->nr;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for(i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
            zData->array[i][j].Re = xData->array[j][i].Re;
            zData->array[i][j].Im = -xData->array[j][i].Im;
		}
	
	return z;
	
}/* HConjugateCM */



static REALobject DiagonalizeH(REALobject theMatrix, REALobject EigenvectorMatrix, double eps)
{
	ComplexMatrixData		*data, *zData, *EData;
	REALobject				z;
	long					i, j;
	
	if(theMatrix==nil)
		return theMatrix;
	
	if(EigenvectorMatrix==nil)
		return theMatrix;
	
	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	EData = (ComplexMatrixData *) REALGetClassData(EigenvectorMatrix, &ComplexMatrixClass);
	
	if (EData == nil || data == nil || data->nr!=data->nc || data->nr<=1 || EData->nr!=data->nr ||  EData->nc!=data->nc || eps<=0)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
		
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		(zData->array)[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
		
	for(i=0;i<zData->nr;i++)
		for(j=0;j<zData->nc;j++)
		{
			(zData->array)[i][j].Re = (data->array)[i][j].Re;
			(zData->array)[i][j].Im = (data->array)[i][j].Im;
		}
		
	diagh(zData->array, EData->array, zData->nr, eps);
		
	return z;
	
}/* DiagonalizeH */


static REALobject PowerCM(REALobject theMatrix, long n)
{
	ComplexMatrixData		*zData;
	ComplexMatrixData		*data;
	REALobject				z;
	long					i;
	
	if(theMatrix==nil)
		return theMatrix;
	
	data = (ComplexMatrixData *) REALGetClassData(theMatrix, &ComplexMatrixClass);
	
	if (data == nil || data->nr<1 || data->nc<1 || data->nr!=data->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return theMatrix;
	}
	
	//z = REALnewInstance("ComplexMatrix");
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
	zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
	
	zData->nr = data->nr;
	zData->nc = data->nc;
	zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
	for (i=0;i<zData->nr;i++)
		zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
	
	myPowerCM(zData->array, data->array, n, zData->nr);
	
	return z;
	
}/* PowerCM */


static REALobject GaussElimCM(REALobject x)
{
    REALobject              z;
    ComplexMatrixData       *xData, *zData;
    long                    i;
    
    if(x==nil)
        return x;
    
    xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
    if(xData==nil)
        return x;
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc;
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    GaussElimC(zData->array, zData->nr, zData->nc, xData->array);
    
    return z;
    
}/* GaussElimCM */


static REALobject GaussElimM(REALobject x)
{
    REALobject              z;
    MatrixData              *xData, *zData;
    long                    i;
    
    if(x==nil)
        return x;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return x;
    
    z = REALnewInstanceWithClass(globalMatrixRef);
    zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc;
    zData->array = (double **)malloc(zData->nr*sizeof(double *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
    
    GaussElimD(zData->array, zData->nr, zData->nc, xData->array);
    
    return z;
    
}/* GaussElimM */

static REALobject CreateRealUnit(long nr, long nc)
{
    REALobject      z;
    MatrixData      *zData;
    long            i;
    
    z = REALnewInstanceWithClass(globalMatrixRef);
    zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
    
    zData->nr = nr;
    zData->nc = nc;
    zData->array = (double **)malloc(zData->nr*sizeof(double *));
    for(i=0;i<zData->nr;++i)
        zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
    
    CreateUnitD(zData->array, nr, nc);
    
    return z;
    
}/* CreateRealUnit */


static REALobject RealToComplexCM(REALobject x)
{
    REALobject              z;
    ComplexMatrixData       *zData;
    MatrixData              *xData;
    long                    i;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return x;
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc;
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    RealToComplex(zData->array, zData->nr, zData->nc, xData->array);
    
    return z;
    
}/* RealToComplexCM */


static REALobject ReduceCM(REALobject x)
{
    REALobject      z;
    ComplexMatrixData      *xData, *zData;
    long            i;
    
    xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
    if(xData==nil)
        return x;
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc;
    
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    Reduce(zData->array, zData->nr, zData->nc, xData->array);
    
    return z;
    
}/* ReduceCM */

static REALobject ReduceM(REALobject x)
{
    REALobject      z;
    MatrixData      *xData, *zData;
    long            i;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return x;
    
    z = REALnewInstanceWithClass(globalMatrixRef);
    zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc;
    
    zData->array = (double **)malloc(zData->nr*sizeof(double *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
    
    ReduceD(zData->array, zData->nr, zData->nc, xData->array);
    
    return z;
    
}/* ReduceM */

static REALobject AugmentM_M(REALobject x, REALobject y)
{
    REALobject          z;
    MatrixData          *xData, *yData, *zData;
    long                i;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return x;
    
    yData = (MatrixData *) REALGetClassData(y, &MatrixClass);
    if(yData==nil)
        return y;
    
    if(xData->nr != yData->nr)
    {
        return x;
    }
    
    z = REALnewInstanceWithClass(globalMatrixRef);
    zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc + yData->nc;
    
    zData->array = (double **)malloc(zData->nr*sizeof(double *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (double *)malloc(zData->nc*sizeof(double));
    
    Augment(zData->array, xData->array, xData->nr, xData->nc, yData->array, yData->nr, yData->nc);
    
    return z;
    
}/* AugmentM_M */

static REALobject AugmentCM_M(REALobject x, REALobject y)
{
    REALobject          z;
    MatrixData          *yData;
    ComplexMatrixData   *xData, *zData;
    long                i;
    
    xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
    if(xData==nil)
        return x;
    
    yData = (MatrixData *) REALGetClassData(y, &MatrixClass);
    if(yData==nil)
        return y;
    
    if(xData->nr != yData->nr)
    {
        return x;
    }
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc + yData->nc;
    
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    Augment(zData->array, xData->array, xData->nr, xData->nc, yData->array, yData->nr, yData->nc);
    
    return z;
    
}/* AugmentCM_M */


static REALobject AugmentM_CM(REALobject x, REALobject y)
{
    REALobject          z;
    MatrixData          *xData;
    ComplexMatrixData   *yData, *zData;
    long                i;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return x;
    
    yData = ( ComplexMatrixData *) REALGetClassData(y, & ComplexMatrixClass);
    if(yData==nil)
        return y;
    
    if(xData->nr != yData->nr)
    {
        return x;
    }
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc + yData->nc;
    
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    Augment(zData->array, xData->array, xData->nr, xData->nc, yData->array, yData->nr, yData->nc);
    
    return z;
    
}/* AugmentM_CM */


static REALobject AugmentCM_CM(REALobject x, REALobject y)
{
    REALobject          z;
    ComplexMatrixData   *xData;
    ComplexMatrixData   *yData, *zData;
    long                i;
    
    xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
    if(xData==nil)
        return x;
    
    yData = ( ComplexMatrixData *) REALGetClassData(y, & ComplexMatrixClass);
    if(yData==nil)
        return y;
    
    if(xData->nr != yData->nr)
    {
        return x;
    }
    
    z = REALnewInstanceWithClass(globalComplexMatrixRef);
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    
    zData->nr = xData->nr;
    zData->nc = xData->nc + yData->nc;
    
    zData->array = (Complex **)malloc(zData->nr*sizeof(Complex *));
    for(i=0;i<zData->nr;i++)
        zData->array[i] = (Complex *)malloc(zData->nc*sizeof(Complex));
    
    Augment(zData->array, xData->array, xData->nr, xData->nc, yData->array, yData->nr, yData->nc);
    
    return z;
    
}/* AugmentCM_CM */

// z -> xy
static void unAugmentM(REALobject x, REALobject y, long nCols, REALobject z)
{
    MatrixData      *xData, *yData, *zData;
    long            i;
    
    zData = (MatrixData *) REALGetClassData(z, &MatrixClass);
    if(zData==nil)
        return;
    
    if(nCols>=zData->nc)
        return;
    
    xData = (MatrixData *) REALGetClassData(x, &MatrixClass);
    if(xData==nil)
        return;
    
    yData = (MatrixData *) REALGetClassData(y, &MatrixClass);
    if(yData==nil)
        return;
    
    xData->nr = zData->nr;
    xData->nc = nCols;
    yData->nr = zData->nr;
    yData->nc = zData->nc - nCols;
    
    xData->array = (double **)malloc(xData->nr*sizeof(double *));
    for(i=0;i<xData->nr;i++)
        xData->array[i] = (double *)malloc(xData->nc*sizeof(double));
    
    yData->array = (double **)malloc(yData->nr*sizeof(double *));
    for(i=0;i<yData->nr;i++)
        yData->array[i] = (double *)malloc(yData->nc*sizeof(double));
    
    unAugmentD(xData->array, yData->array, nCols, zData->nr, zData->nc, zData->array);
    
}/* unAugmentM */


// z -> xy
static void unAugmentCM(REALobject x, REALobject y, long nCols, REALobject z)
{
    ComplexMatrixData      *xData, *yData, *zData;
    long            i;
    
    zData = (ComplexMatrixData *) REALGetClassData(z, &ComplexMatrixClass);
    if(zData==nil)
        return;
    
    if(nCols>=zData->nc)
        return;
    
    xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
    if(xData==nil)
        return;
    
    yData = (ComplexMatrixData *) REALGetClassData(y, &ComplexMatrixClass);
    if(yData==nil)
        return;
    
    xData->nr = zData->nr;
    xData->nc = nCols;
    yData->nr = zData->nr;
    yData->nc = zData->nc - nCols;
    
    xData->array = (Complex **)malloc(xData->nr*sizeof(Complex *));
    for(i=0;i<xData->nr;i++)
        xData->array[i] = (Complex *)malloc(xData->nc*sizeof(Complex));
    
    yData->array = (Complex **)malloc(yData->nr*sizeof(Complex *));
    for(i=0;i<yData->nr;i++)
        yData->array[i] = (Complex *)malloc(yData->nc*sizeof(Complex));
    
    unAugmentC(xData->array, yData->array, nCols, zData->nr, zData->nc, zData->array);
    
}/* unAugmentCM */

static REALmethodDefinition otherComplexMatrixMethods[] = {
	{ (REALproc) ChangeElementCM, REALnoImplementation, "ChangeElement(theMatrix As ComplexMatrix, rowIndex As Integer, columnIndex As Integer, value As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) NewElementCM, REALnoImplementation, "NewElement(theMatrix As ComplexMatrix, rowIndex As Integer, columnIndex As Integer, value As Complex)", REALconsoleSafe },
	{ (REALproc) CMInverse, REALnoImplementation, "Inverse(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CMInverseDet, REALnoImplementation, "Inverse(theMatrix As ComplexMatrix, ByRef theDeterminant As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CMDeterminant, REALnoImplementation, "Determinant(theMatrix As ComplexMatrix) As Complex", REALconsoleSafe },
	{ (REALproc) CMTranspose, REALnoImplementation, "Transpose(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SqrCM, REALnoImplementation, "Sqr(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SqrtCM, REALnoImplementation, "Sqrt(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SqrtM, REALnoImplementation, "Sqrt(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) ExpCM, REALnoImplementation, "Exp(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) LogCM, REALnoImplementation, "Log(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) LogM, REALnoImplementation, "Log(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SinCM, REALnoImplementation, "Sin(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CosCM, REALnoImplementation, "Cos(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) TanCM, REALnoImplementation, "Tan(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aSinCM, REALnoImplementation, "aSin(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aCosCM, REALnoImplementation, "aCos(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aTanCM, REALnoImplementation, "aTan(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aSinM, REALnoImplementation, "aSin(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aCosM, REALnoImplementation, "aCos(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aTanM, REALnoImplementation, "aTan(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) SinhCM, REALnoImplementation, "Sinh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CoshCM, REALnoImplementation, "Cosh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) TanhCM, REALnoImplementation, "Tanh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aSinhCM, REALnoImplementation, "aSinh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aCoshCM, REALnoImplementation, "aCosh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aTanhCM, REALnoImplementation, "aTanh(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aSinhM, REALnoImplementation, "aSinh(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aCoshM, REALnoImplementation, "aCosh(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) aTanhM, REALnoImplementation, "aTanh(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) PowCM_C, REALnoImplementation, "Pow(theMatrix As ComplexMatrix, y As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) PowCM_D, REALnoImplementation, "Pow(theMatrix As ComplexMatrix, y As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) PowM_C, REALnoImplementation, "Pow(theMatrix As Matrix, y As Complex) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) PowM_D, REALnoImplementation, "Pow(theMatrix As Matrix, y As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CommutatorCM_CM, REALnoImplementation, "Commutator(x As ComplexMatrix, y As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CommutatorCM_M, REALnoImplementation, "Commutator(x As ComplexMatrix, y As Matrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) CommutatorM_CM, REALnoImplementation, "Commutator(x As Matrix, y As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) ConjugateCM, REALnoImplementation, "Conjugate(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) HConjugateCM, REALnoImplementation, "HermitianConjugate(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) DiagonalizeH, REALnoImplementation, "Diagonalize(theMatrix As ComplexMatrix, EigenvectorMatrix As ComplexMatrix, eps As Double) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc) PowerCM, REALnoImplementation, "Power(theMatrix As ComplexMatrix, n As Integer) As ComplexMatrix", REALconsoleSafe },
	{ (REALproc)NumRowsC, REALnoImplementation, "NumRows(theMatrix As ComplexMatrix) As Integer", REALconsoleSafe },
	{ (REALproc)NumColumnsC, REALnoImplementation, "NumColumns(theMatrix As ComplexMatrix) As Integer", REALconsoleSafe },
    { (REALproc)GaussElimCM, REALnoImplementation, "GaussElimCM(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)GaussElimM, REALnoImplementation, "GaussElimM(theMatrix As Matrix) As Matrix", REALconsoleSafe },
    { (REALproc)CreateRealUnit, REALnoImplementation, "CreateRealUnit(nRows As Integer, nCols As Integer) As Matrix", REALconsoleSafe },
    { (REALproc)RealToComplexCM, REALnoImplementation, "RealToComplex(theMatrix As Matrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)ReduceCM, REALnoImplementation, "ReduceCM(theMatrix As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)ReduceM, REALnoImplementation, "ReduceM(theMatrix As Matrix) As Matrix", REALconsoleSafe },
    { (REALproc)AugmentM_M, REALnoImplementation, "Augment(x As Matrix, y As Matrix) As Matrix", REALconsoleSafe },
    { (REALproc)AugmentCM_M, REALnoImplementation, "Augment(x As ComplexMatrix, y As Matrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)AugmentM_CM, REALnoImplementation, "Augment(x As Matrix, y As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)AugmentCM_CM, REALnoImplementation, "Augment(x As ComplexMatrix, y As ComplexMatrix) As ComplexMatrix", REALconsoleSafe },
    { (REALproc)unAugmentM, REALnoImplementation, "unAugment(x As Matrix, y As Matrix, nCols As Integer, z As Matrix)", REALconsoleSafe },
    { (REALproc)unAugmentCM, REALnoImplementation, "unAugment(x As ComplexMatrix, y As ComplexMatrix, nCols As Integer, z As ComplexMatrix)", REALconsoleSafe },
};


/* -------------------------------------
   PolynomialConstructor
   
   Called by REALbasic when a new Polynomial object is instantiated.
   
   instance = the new Polynomial object
   ------------------------------------- */

static void PolynomialConstructor(REALobject instance)
{
	Polynomial		*data;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil)
		return;
	
	data->n = -1;
	data->coeff = nil;
	
}/* PolynomialConstructor */


static void NewPolynomial(REALobject instance, long n, REALstring CMStr)
{
	Polynomial		*data;
	long			i, kd, rd, length;
	char			*dataString, *doubleString, ch, CR=0x0D, SP=0x20, TAB=0x09;
	double			theDouble;
	Boolean			endOfData, areInNumber;
    REALstringData  *outData;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil)
		return;
	
	data->n = n;
	data->coeff = (Complex*)malloc((n+1)*sizeof(Complex));
    
    outData = new REALstringData();
    if(!REALGetStringData(CMStr, kREALTextEncodingUTF8, outData))
    {
        for(i=0;i<=data->n;i++)
            data->coeff[i].Re = 0;
        data->coeff[i].Im = 0;
        REALDisposeStringData(outData);
        return;
    }
	
	// now get the matrix elements from MStr
	//length = CMStr->Length();
	length = outData->length;
	// if length==0 make it a null polynomial and return
	if(length==0)
	{
		for(i=0;i<=data->n;i++)
			data->coeff[i].Re = 0;
			data->coeff[i].Im = 0;
	
		return;
	}
	
	// length!=0
	dataString = (char *)malloc((length+1)*sizeof(char));
	doubleString = (char *)malloc((length+1)*sizeof(char));
    memcpy(dataString, outData->data, length); // to, from
    dataString[length] = 0; // makes it a C string
    REALDisposeStringData(outData);
	
	/*
		for example, a 3 coeff string could look like:
		1,2 2,0 3,4
		
		
		or like this
		1,2
		2,0
		3,4
		
		Mac newline = 0xD (CR), Win32 newline = 0xD 0xA (CR LF), Unix newline = 0xA (LF)
	*/
	
	endOfData = false;
	kd = 0;
	for(i=0;i<=data->n;i++)
	{
		if(!endOfData)
		{
			areInNumber = false;
			rd = 0; // start index of doubleString
			// get jth double string as doubleString, read to , or SP or CR or end of dataString
			ch = dataString[kd];
			
			while(kd<length && !(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
			{
				kd++;
				ch = dataString[kd]; 
			}
			
			// now into real number part, go until comma
			while(kd<length && !(ch==','))
			{
				doubleString[rd] = ch;
				rd++;
				kd++;
				ch = dataString[kd]; 
			}
			
			doubleString[rd] = 0;
			
			if(kd>=length)
				endOfData = true;
				
			if(!(sscanf(doubleString, "%lf", &theDouble)==1))
				theDouble = 0;

			data->coeff[i].Re = theDouble;
		}
		else
			data->coeff[i].Re = 0;
			
		if(!endOfData)
		{
			areInNumber = false;
			rd = 0; // start index of doubleString
			// get jth double string as doubleString, read to , or SP or end of rowString
			ch = dataString[kd];
			
			while(kd<length && !(ch=='+' || ch=='-' || ch=='e' || ch=='E' || ch=='.' || (ch>=0x30 && ch<=0x39)))
			{
				kd++;
				ch = dataString[kd]; 
			}
			
			// now into imaginary number part, go until whitespace or CR
			while(kd<length && !(ch==SP || ch==TAB || ch==CR))
			{
				doubleString[rd] = ch;
				rd++;
				kd++;
				ch = dataString[kd]; 
			}
			
			doubleString[rd] = 0;
			
			if(kd>=length)
				endOfData = true;
				
			if(!(sscanf(doubleString, "%lf", &theDouble)==1))
				theDouble = 0;

			data->coeff[i].Im = theDouble;
		}
		else
			data->coeff[i].Im = 0;
	}
	
	
	free(dataString);
	free(doubleString);

}/* NewPolynomial */


/* -------------------------------------
  PolynomialDestructor
   
   Called by REALbasic when a Polynomial object is destroyed.
   
   instance = the Polynomial object being destroyed
   ------------------------------------- */

static void PolynomialDestructor(REALobject instance)
{
	Polynomial		*data;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil)
		return;
		
	if(data->coeff != nil)
		free(data->coeff);
	
}/* PolynomialDestructor */


static REALstring PolyOut(REALobject instance)
{
	Polynomial				*data;
	char					*myString, **polyString, CR=0x0D, SP=0x20, LF=0x0A;
	long					i, length, len;
	char					formatString1[10], formatString[15], precString[5];
	
	//REALstring nullString = REALBuildString (nil, 0);
	
	if(instance==nil)
		return nullString;
		
	strcpy(formatString1, "%.");
	sprintf(precString, "%d", myPrecision);
	strcat(formatString1, precString);
	strcat(formatString1, "g");
	
	strcpy(formatString, formatString1);
	strcat(formatString, ",");
	strcat(formatString, formatString1);
	//strcat(formatString, " ");
	
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	if(data==nil || data->n<0)
		return nullString;
		
	length = 50; // length of string complex should be less than this
	
	polyString = (char **)malloc((data->n+1)*sizeof(char *));
	for (i=0;i<=data->n;i++)
		polyString[i] = (char *)malloc(length*sizeof(char));
		
			
	// put complex numbers into polyStringMatrix
	for(i=0;i<=data->n;i++)
		sprintf(polyString[i],formatString, data->coeff[i].Re, data->coeff[i].Im);
	
	length = 50*(data->n+1) + 1; // estimate of maximum length of C string returned
	
	myString = (char *)malloc(length*sizeof(char));
	myString[0] = 0;
	
	// load up myString
	for(i=0;i<=data->n;i++)
	{
		strcat(myString, polyString[i]);
		
		len = strlen(myString);
		if(i!=data->n)
		{
			myString[len] = CR;
			#if MYWIN32
				myString[++len] = LF;
			#endif
			myString[++len] = 0;
		}
	}
	
	length = strlen(myString);
	
	REALstring str = REALBuildStringWithEncoding(myString, length, kREALTextEncodingUTF8);
	
	
	free(myString);
	
	for(i=0;i<=data->n;i++)
		free(polyString[i]);
		
	free(polyString);
	
	return str;
	
}/* PolyOut */



static REALobject Coeff(REALobject instance, long index)
{
	Polynomial		*data;
	REALobject		z;
	Complex			*zData;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil || index<0 || index>data->n)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return ComplexObjectNAN();
	}
		
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	if(zData==nil)
		return ComplexObjectNAN();
		
	*zData = data->coeff[index];
	
	return z;
	
}/* Coeff */


static void SetCoeffC(REALobject instance, long index, REALobject x)
{
	Polynomial		*data;
	Complex			*xData;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil || index<0 || index>data->n)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return;
	}
		
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	
	if(xData==nil)
		return;
		
	data->coeff[index] = *xData;
	
}/* SetCoeffC */


static void SetCoeffDD(REALobject instance, long index, double xRe, double xIm)
{
	Polynomial		*data;
	
	// Get the class data
	data = (Polynomial *) REALGetClassData(instance, &PolynomialClass);
	
	if (data == nil || index<0 || index>data->n)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return;
	}
		
	data->coeff[index].Re = xRe;
	data->coeff[index].Im = xIm;
	
}/* SetCoeffDD */


// REALbasic class & method definitions for the Polynomial object

static REALmethodDefinition PolynomialMethods[] = {
	// defines methods:
	{ (REALproc) ComplexConstructor, REALnoImplementation, "Constructor()", REALconsoleSafe },
	{ (REALproc) NewPolynomial, REALnoImplementation, "Constructor(n As Integer, inputString As String)", REALconsoleSafe },
	{ (REALproc) PolyOut, REALnoImplementation, "Str() as String", REALconsoleSafe },
	{ (REALproc) Coeff, REALnoImplementation, "Coeff(Index As Integer) as Complex", REALconsoleSafe },
	{ (REALproc) SetCoeffC, REALnoImplementation, "SetCoeff(Index As Integer, x As Complex)", REALconsoleSafe },
	{ (REALproc) SetCoeffDD, REALnoImplementation, "SetCoeff(Index As Integer, xRe As Double, xIm As Double)", REALconsoleSafe },
};


REALclassDefinition PolynomialClass = {
        kCurrentREALControlVersion,
        "Polynomial",                    			// name of class
        nil,                                    // no superclasses
        sizeof(Polynomial),                      // size of our data
        0,																			// --reserved--
        (REALproc) PolynomialConstructor,     				// constructor
        (REALproc) PolynomialDestructor,							// destructor
        nil,            												// properties
        0,																			// property count
        PolynomialMethods,               					// methods
        sizeof(PolynomialMethods) / sizeof(REALmethodDefinition),	// method count
        // other fields left nil -- no events etc.
};

// the following pragma is essential here

#pragma mark -


// other Polynomial methods
/*
static REALobject FindRoots(REALobject x)
{
	Polynomial		*xData;
	REALobject		z;
	Polynomial		*zData;
	
	if(x==nil)
		return x;
		
	xData = (Polynomial *) REALGetClassData(x, &PolynomialClass);
	if (xData == nil)
		return x;
		
	//z = REALnewInstance("Polynomial");
    z = REALnewInstanceWithClass(globalPolynomialRef);
	zData = (Polynomial *) REALGetClassData(z, &PolynomialClass);
	if(xData->n<1)
        return x;
	zData->n = xData->n - 1;
	zData->coeff = (Complex*)malloc(zData->n*sizeof(Complex)); // will hold roots
		
	if(myFindRoots(zData->coeff, xData->coeff, xData->n))
		return z;
	else
		return x;
	
}*//* FindRoots */


// evaluates polynomial P(x)
static REALobject Eval(REALobject P, REALobject x)
{
	REALobject		z;
	Polynomial		*PData;
	Complex			*xData, *zData;
	
	
	if(P==nil || x==nil)
		return ComplexObjectNAN();
		
	PData = (Polynomial *) REALGetClassData(P, &PolynomialClass);
	if (PData == nil)
		return ComplexObjectNAN();
		
	xData = (Complex *) REALGetClassData(x, &ComplexClass);
	if (xData == nil)
		return ComplexObjectNAN();
		
	//z = REALnewInstance("Complex");
    z = REALnewInstanceWithClass(globalComplexRef);
	zData = (Complex *) REALGetClassData(z, &ComplexClass);
	
	if(zData==nil)
		return ComplexObjectNAN();
		
	Evaluate(PData->coeff, PData->n, *xData, *zData);
		
	return z;
	
}/* Eval */


// this returns the eigenvalues of x in a polynomial
static REALobject Eigenvalues(REALobject x)
{
	ComplexMatrixData	*xData;
	REALobject			z;
	Polynomial			*zData;
	long				n, i, j;
	bool				isHermitian;
	
	//z = REALnewInstance("Polynomial");
    z = REALnewInstanceWithClass(globalPolynomialRef);
	zData = (Polynomial *) REALGetClassData(z, &PolynomialClass);
	
	if(x==nil)
		return z;
	
	xData = (ComplexMatrixData *) REALGetClassData(x, &ComplexMatrixClass);
	if (xData == nil || xData->nr != xData->nc)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return z;
	}
		
	// get n first
	n = xData->nr;
	/*
	// check if Hermitian
	isHermitian = true;
	for(i=0;i<n;i++)
		for(j=0;j<=i;j++)
			{
				if((xData->array[i][j].Re != xData->array[j][i].Re) || (xData->array[i][j].Im != -xData->array[j][i].Im))
				{
					isHermitian = false;
					goto bailout;
				}
			}
	bailout:
	
	if(!isHermitian)
	{
		REALobject err = REALnewInstance("RowColumnMismatch");
		REALRaiseException(err);
		return z;
	}
 */
	
	zData->n = n-1;
	zData->coeff = (Complex*)malloc(n*sizeof(Complex));
	
	myEigenvalues(xData->array, zData->coeff, n);
		
	return z;

}/* Eigenvalues */




static REALmethodDefinition otherPolynomialMethods[] = {
	//{ (REALproc) FindRoots, REALnoImplementation, "FindRoots(P As Polynomial) as Polynomial", REALconsoleSafe },
	{ (REALproc) Eval, REALnoImplementation, "Eval(P As Polynomial, x As Complex) as Complex", REALconsoleSafe },
	{ (REALproc) Eigenvalues, REALnoImplementation, "Eigenvalues(theMatrix As ComplexMatrix) As Polynomial", REALconsoleSafe },
    { (REALproc) setBlockPrec, REALnoImplementation, "SetBlockPrec(thePrec As Integer)", REALconsoleSafe },
    { (REALproc) getBlockPrec, REALnoImplementation, "GetBlockPrec() As Integer", REALconsoleSafe },
    
};


REALclassDefinition DivideByZeroExceptionClass = {
        kCurrentREALControlVersion,
        "DivideByZeroException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};

REALclassDefinition NegativeNumberExceptionClass = {
        kCurrentREALControlVersion,
        "NegativeNumberException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};

REALclassDefinition NegativeOrZeroExceptionClass = {
        kCurrentREALControlVersion,
        "NegativeOrZeroException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};
REALclassDefinition BadEntryNumberExceptionClass = {
        kCurrentREALControlVersion,
        "BadEntryNumberException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};

REALclassDefinition OverflowOrUnderflowExceptionClass = {
        kCurrentREALControlVersion,
        "OverflowOrUnderflowException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};

REALclassDefinition BadArgumentExceptionClass = {
        kCurrentREALControlVersion,
        "BadArgumentException",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};

REALclassDefinition RowColumnMismatchClass = {
        kCurrentREALControlVersion,
        "RowColumnMismatch",                    			// name of class
        nil,                                    // no superclasses
        0,                      // size of our data
        0,																			// --reserved--
        nil,     				// constructor
        nil,							// destructor
        nil,            												// properties
        0,																			// property count
        nil,               					// methods
        0,	// method count
        // other fields left nil -- no events etc.
};


void PluginEntry(void)
{
	int		i;
	
	REALRegisterClass(&DivideByZeroExceptionClass);
	REALRegisterClass(&NegativeNumberExceptionClass);
	REALRegisterClass(&NegativeOrZeroExceptionClass);
	REALRegisterClass(&BadEntryNumberExceptionClass);
	REALRegisterClass(&OverflowOrUnderflowExceptionClass);
	REALRegisterClass(&BadArgumentExceptionClass);
	REALRegisterClass(&RowColumnMismatchClass);
	
    SetClassConsoleSafe(&ComplexClass);
    SetClassConsoleSafe(&MatrixClass);
    SetClassConsoleSafe(&ComplexMatrixClass);
    SetClassConsoleSafe(&PolynomialClass);
    
    globalComplexRef = REALGetClassRef("Complex");
    globalMatrixRef = REALGetClassRef("Matrix");
    globalComplexMatrixRef = REALGetClassRef("ComplexMatrix");
    globalPolynomialRef = REALGetClassRef("Polynomial");
	
	REALRegisterClass(&ComplexClass);
	
	for (i = 0; i < sizeof(otherComplexMethods) / sizeof(REALmethodDefinition); ++i)
		REALRegisterMethod(&otherComplexMethods[i]);
		
	
	REALRegisterClass(&MatrixClass);
	
	for (i = 0; i < sizeof(otherMatrixMethods) / sizeof(REALmethodDefinition); ++i)
		REALRegisterMethod(&otherMatrixMethods[i]);
		
		
	REALRegisterClass(&ComplexMatrixClass);
	
	for (i = 0; i < sizeof(otherComplexMatrixMethods) / sizeof(REALmethodDefinition); ++i)
		REALRegisterMethod(&otherComplexMatrixMethods[i]);
		
		
	REALRegisterClass(&PolynomialClass);
	
	for (i = 0; i < sizeof(otherPolynomialMethods) / sizeof(REALmethodDefinition); ++i)
		REALRegisterMethod(&otherPolynomialMethods[i]);
	
    setBlockPrec(16);
	myPrecision = 7;
    initNullString();
    PluginInit();
    
}
