/*------------------------------------------------------------------------------*
 * File Name: MatrixData.h														*
 * Creation: TD 4-16-03															*
 * Purpose: Origin C header file for Origin basic Data matrix types				*
 * Copyright (c) OriginLab Corp.	2002 - 2007									*
 * All Rights Reserved															*
 * Modifications:
 *------------------------------------------------------------------------------*/

#ifndef _MATRIXDATA_H
#define _MATRIXDATA_H

#ifndef _STRING_H
#include <string.h>		// Most likely will need strings
#endif // _STRING_H

#ifndef _OC_TYPES_H
#include <OC_types.h>	// Structures used in Origin internal functions
#endif

#ifndef _WKSHEET_H
#include <Wksheet.h>
#endif // _WKSHEET_H

#ifndef _VECTOR_H
#include <vector.h>
#endif

/////////////////////////////////////////////////////////////////////////
// matrixbase object
/** >Composite Data Types
		The Origin C matrixbase class is an abstract base class used for polymorphic
		handling of the matrix and Matrix template class types. Origin C objects of
		type matrixbase can not be constructed. Derived classes such as matrix and
		Matrix inherit matrixbase class methods and should be used instead.
*/
class matrixbase
{

protected:
	
	/**#
		Objects of type matrixbase can not be constructed. This is an abstract base
		class used for polymorphic handling of all matrix and Matrix template types.
	*/
	matrixbase();	

public:
	
 	/**
			Set the size (number of columns and number of rows) in any matrixbase derived
			object (e.g. matrix, Matrix).
		Example:
			matrix m;
			int iNumRows = 7;
			int iNumCols = 5;
			m.SetSize( iNumRows, iNumCols );      // Set the number of rows and columns in matrix
			ASSERT( m.GetNumRows() == iNumRows);  // Check the number of rows is correct
			ASSERT( m.GetNumCols() == iNumCols ); // Check the number of columns is correct
		Parameters:
			wNumRows=The number of rows in the newly sized matrix
			wNumCols=The number of columns in the newly sized matrix
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::GetNumRows, matrixbase::GetNumCols
	*/
	BOOL	SetSize(UINT wNumRows, UINT wNumCols); // Set the size of any matrixbase derived object.

	/**
			Get the number of rows in any matrixbase derived object (e.g. matrix, Matrix).
		Example:
			// Assumes Matrix1 window in Origin 
			Matrix mat("Matrix1");
			int iNumRows;
			iNumRows = mat.GetNumRows(); // Get number of rows
		Return:
			Returns the number of rows in this matrixbase object.
		SeeAlso:
			matrixbase::SetSize, matrixbase::GetNumCols
	*/
	UINT	GetNumRows() const; // Get the number of rows in any matrixbase derived object.
	
	/**
			Get the number of columns in any matrixbase derived object (e.g. matrix, Matrix).
		Example:
			// Assumes Matrix1 window in Origin 
			Matrix mat("Matrix1");
			int iNumCols;
			iNumCols = mat.GetNumCols(); // Get number of columns
		Return:
			Returns the number of columns in this matrixbase object.
		SeeAlso:
			matrixbase::SetSize, matrixbase::GetNumRows
	*/
	UINT	GetNumCols() const; // Get the number of columns in any matrixbase derived object.

	/**
			Pad a matrix with 0 or with adjacent cell values.
		Example:
			// Assumes Matrix1 and Matrix2 exist in Origin
			Matrix mat1("Matrix1"), mat2("Matrix2");
			mat1.Padding( mat2, 2, 1 );
		Parameters:
			mPadding=Output matrix with padded cells having same underlying base type of this matrix
			nPadSize=Input padding width, must be larger than 0
			nPaddingOption=Input padding method, 0 pads with zeroes and 1 pads with adjacent cell values
		Return:
			Returns TRUE on success and FALSE on failure.
 	*/
 	BOOL Padding( matrixbase &mPadding, int nPadSize, int nPaddingOption = 0 ); // Pad a matrix with 0 or with adjacent cell values.

	/**
			MedianFilter examines the N x N pixels centered around each pixel
			of an image (matrix), finds the median value of the N x N pixels,
			and then replaces the central pixel with the median value. It is a useful
			filter to remove spot noise (white spots, black spots) in an
			image because such noisy pixels have values way off the median value.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			2	2	2	2	2
			100	2	2	100	2
			2	2	2	2	2
			2	100	2	2	2
			2	2	2	2	2
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.MedianFilter(3,1); // Use 3 x 3 median filter padding outside borders with adjacent cells
			// Results in all cells of Matrix1 = 2 
		Parameters:
			nWindowSize=The size of the window (N) for median filter
			nPaddingOption=Pads the area outside the borders in one of the following ways
				nPaddingOption=0 -- pads with zeroes 
				nPaddingOption=1 -- pads with values from adjacent cells
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::ApplyFilter
	*/
	BOOL	MedianFilter(int nWindowSize, int nPaddingOption = 0); // Median filter.

	/**
			Takes an N x N filter (or mask) matrix and places it centered over
			each pixel in this image (or matrix). For each cell in the filter/mask
			it computes the product of the filter/mask element with the overlayed
			cell of the original image (matrix), sums all of the products,
			normalizes to the weight of the filter/mask (if specified to do so),
			and then replaces the pixel in the original image with the weighted
			average.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	0	0	0	0
			0	2	0	0	0
			2	1	2	0	0
			0	2	0	0	0
			0	0	0	0	0
			
			// Matrix1 after running Example program
			0	0.8	0	0	0
			1.2	0.6	0.8	0	0
			0.8	1.8	0.6	0.4	0
			1.2	0.6	0.8	0	0
			0	0.8	0	0	0
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			matrix mfilter(3,3);
			mfilter = 1;       // mfilter
			mfilter[0][0] = 0; // 0 1 0
			mfilter[2][0] = 0; // 1 1 1
			mfilter[0][2] = 0; // 0 1 0
			mfilter[2][2] = 0;
			ASSERT( mat[2][1] == 1 ); // Before filter
			// Use mfilter as mask/filter for Matrix1 padding outside borders with adjacent cells and weighting to mfilter
			mat.ApplyFilter(mfilter,1);
			ASSERT( mat[2][1] == 1.8 ); // After filter: (0*0+1*2+0*0+1*2+1*1+1*2+0*0+1*2+0*0)/(0+1+0+1+1+1+0+1+0)=9/5=1.8
		Parameters:
			matfilter=An N x N filter/mask matrix used by Applyfilter
			nPaddingOption=Pads the area outside the borders in one of the following ways
				nPaddingOption=0 -- pads with zeroes 
				nPaddingOption=1 -- pads with values from adjacent cells
			bNormalize=Normalize replacement value with weight of mask/filter if TRUE
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::MedianFilter
	*/ 
	BOOL	ApplyFilter(matrix &mfilter, int nPaddingOption = 0, BOOL bNormalize = TRUE); // Apply filter.

 	/**
			 Horizontally flips this matrixbase derived object about a vertical
			 axis through the center of the matrix. For the example below, the 
			 first column will contain all 5's and the last column will contain
			 all 1's after the flip. 
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			1	2	3	4	5
			1	2	3	4	5
			1	2	3	4	5
			1	2	3	4	5
			1	2	3	4	5
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.FlipHorizontal();
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::FlipVertical, matrixbase::Rotate, matrixbase::Reorder, matrixbase::Transpose
	*/
	BOOL	FlipHorizontal(); // Horizontally flips this matrixbase derived object.
	
	/**
			 Vertically flips this matrixbase derived object about a horizontal
			 axis through the center of the matrix. For the example below, the 
			 first row will contain all 5's and the last row will contain
			 all 1's after the flip.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			1	1	1	1	1
			2	2	2	2	2
			3	3	3	3	3
			4	4	4	4	4
			5	5	5	5	5
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.FlipVertical();
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::FlipHorizontal, matrixbase::Rotate, matrixbase::Reorder, matrixbase::Transpose
	*/
	BOOL	FlipVertical(); // Vertically flips this matrixbase derived object.

 	/**
			Rotates the matrix counter-clockwize by the specified angle. Angles must
			be multiples of 90 degrees but can be negative. Rotating a matrix by 90
			degrees has the simultaneous effect of making the first row become the
			last column, the last column becomes the last row in reverse order, the
			last row becomes the first column, and the first column becomes the first
			row in reverse order.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
			
			// Matrix1 after running     Matrix1 after running
			// Example program once      Example program twice
			4	5	6	7	8            8	7	6	5	4
			3	4	5	6	7            7	6	5	4	3
			2	3	4	5	6            6	5	4	3	2
			1	2	3	4	5            5	4	3	2	1
			0	1	2	3	4            4	3	2	1	0
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.Rotate(90);
		Parameters:
			nAngleDegree=The rotation angle in degrees, can be negative but must be a multiple
				of 90 otherwise the closest multiple is used
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::FlipHorizontal, matrixbase::FlipVertical, matrixbase::Reorder, matrixbase::Transpose
  	*/
	BOOL	Rotate(int nAngleDegree = 90 ); // Rotates the matrix counter-clockwize by the specified angle.

	/**
			Replace all cell values less than dThresholdVal with dReplaceVal.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
			
			// Matrix1 after running Example program
			0	0	0	0	4
			0	0	0	4	5
			0	0	4	5	6
			0	4	5	6	7
			4	5	6	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.ReplaceLessThan(4,0);
		Parameters:
			dThresholdVal=Condition or threshold value 
			dReplaceVal=Replacement value
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::Replace, matrixbase::ReplaceGreaterThan
	*/
	BOOL	ReplaceLessThan(double dThresholdVal, double dReplaceVal); // Replace all cell values less than dThresholdVal with dReplaceVal.

	/**
			Replace all cell values greater than dThresholdVal with dReplaceVal.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
			
			// Matrix1 after running Example program
			0	1	2	3	4
			1	2	3	4	0
			2	3	4	0	0
			3	4	0	0	0
			4	0	0	0	0
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.ReplaceGreaterThan(4,0);
		Parameters:
			dThresholdVal=Condition or threshold value 
			dReplaceVal=Replacement value
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::Replace, matrixbase::ReplaceLessThan
	*/
	BOOL	ReplaceGreaterThan(double dThresholdVal, double dReplaceVal); // Replace all cell values greater than dThresholdVal with dReplaceVal.

	/**
			Set the values of a matrix column equal to the values of a vector. The
			column is specified by a 0 based column index. If the matrix column and
			vector do not have the same size then the maximum number of elements
			possible are assigned from the vector to the matrix column.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
			
			// Matrix1 after running Example program
			0	1	-99	3	4
			1	2	-99	4	5
			2	3	-99	5	6
			3	4	-99	6	7
			4	5	-99	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			vector v = {-99,-99,-99,-99,-99};
			mat.SetColumn( v, 2);
		Parameters:
			vb=Vector whose values are assigned to the column
			nIndexCol=Specifies the 0 based offset or column index of the column in the matrix
		Return:
			 Returns 0 if successful and the vector size matches the matrix column size, 
			 otherwise returns the size of the matrix column minus the size of the vector.
		SeeAlso:
			matrixbase::GetColumn, matrixbase::SetRow, matrixbase::GetRow, matrixbase::GetAsVector, matrixbase::SetByVector
	*/
	int		SetColumn(vectorbase &vb, UINT wIndexCol); // Set the values of a matrix column equal to the values of a vector.

	/**
			Set the values of a matrix row equal to the values of a vector. The
			row is specified by a 0 based row index. If the matrix row and vector
			do not have the same size then the maximum number of elements possible
			are assigned from the vector to the matrix row.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
			
			// Matrix1 after running Example program
			0	1	2	3	4
			1	2	3	4	5
			-99 -99 -99 -99 -99
			3	4	5	6	7
			4	5	6	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			vector v = {-99,-99,-99,-99,-99};
			mat.SetRow( v, 2);
		Parameters:
			vb=Vector whose values are assigned to the row
			nIndexRow=Specifies the 0 based offset or row index of the row in the matrix
		Return:
			 Returns 0 if successful and the vector size matches the matrix row size, 
			 otherwise returns the size of the matrix row minus the size of the vector.
		SeeAlso:
			matrixbase::GetRow, matrixbase::SetColumn, matrixbase::GetColumn, matrixbase::GetAsVector, matrixbase::SetByVector
	*/
	int		SetRow(vectorbase &vb, UINT wIndexRow); // Set the values of a matrix row equal to the values of a vector.

	/**
			Get the values of a matrix column and assign them to a vector. The
			column is specified by a 0 based column index. If the matrix column
			and vector do not have the same size then the vector is dynamically
			resized.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			vector v1;
			mat.GetColumn( v1, 2); // v1 = {2,3,4,5,6}
		Parameters:
			vb=Vector used to get the matrix column values
			nIndexCol=Specifies the 0 based offset or column index of the column in the matrix 
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::SetColumn, matrixbase::GetRow, matrixbase::SetRow, matrixbase::GetAsVector, matrixbase::SetByVector
	*/
	BOOL	GetColumn(vectorbase &vb, UINT wIndexCol); // Get the values of a matrix column and assign them to a vector.

	/**
			Get the values of a matrix row and assign them to a vector. The row
			is specified by a 0 based row index. If the matrix row and vector
			do not have the same size then the vector is dynamically resized.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			vector v1;
			mat.GetRow( v1, 4); // v1 = {4,5,6,7,8}
		Parameters:
			vb=Vector used to get the matrix row values
			nIndexRow=Specifies the 0 based offset or row index of the row in the matrix 
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::SetRow, matrixbase::GetColumn, matrixbase::SetColumn, matrixbase::GetAsVector, matrixbase::SetByVector
	*/
	BOOL	GetRow(vectorbase &vb, UINT wIndexRow); // Get the values of a matrix row and assign them to a vector.

	/**
			Get the values of an entire matrix and assign them to a vector. If
			the matrix and vector do not have the number of elements then the
			vector is dynamically resized.
		Sample Data:
			// Matrix1 is 5 x 5 with following data
			0	1	2	3	4
			1	2	3	4	5
			2	3	4	5	6
			3	4	5	6	7
			4	5	6	7	8
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			vector v1;
			mat.GetAsVector( v1, 4); // v1 = {0,1,2,3,4,1,2,3,4,5,2,3,4,5,6,3,4,5,6,7,4,5,6,7,8}
		Parameters:
			vb=Vector used to get the matrix values
			bByRow=Use Row order if TRUE otherwise use Column order 
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::SetByVector, matrixbase::GetRow, matrixbase::SetRow, matrixbase::GetColumn, matrixbase::SetColumn
	*/
	BOOL	GetAsVector(vectorbase &vb, BOOL bByRow = TRUE); // Get the values of an entire matrix and assign them to a vector.

	/**
			Set the values of a matrix equal to the values of a vector. If the
			matrix has more elements than the vector then vector values are
			assigned until they are exausted and the remaining matrix values
			are left untouched. If the vector has more elements than the matrix
			then vector values are assigned to the last element of the matrix
			and the remaining elements of the vector are ignored.
		Example:
			// Assumes 5 x 5 Matrix1 window in Origin 
			Matrix mat("Matrix1");
			vector v1 = {0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4};
			mat.SetByVector( v1, FALSE); // Use Column order
			// Results in Matrix1
			// 0	0	0	0	0
			// 1	1	1	1	1
			// 2	2	2	2	2
			// 3	3	3	3	3
			// 4	4	4	4	4
		Parameters:
			vb=Vector used to set the matrix values
			bByRow=Use Row order if TRUE otherwise use Column order 
		Return:
			0 if successful and the number of elements in the vector is the same as the number of elements 
			in the matrix otherwise the number of elements in the matrix minus the number of elements in the
			vector is returned.
		SeeAlso:
			matrixbase::GetAsVector, matrixbase::SetRow, matrixbase::GetRow, matrixbase::SetColumn, matrixbase::GetColumn
	*/
	int		SetByVector(vectorbase &vb, BOOL bByRow = TRUE); // Set the values of a matrix equal to the values of a vector.

															 /**
			Re-order a matrix from Column order to Row order or from Row order
			to Column order.
		Sample Data:
			// Matrix1 is 5 x 3 with following data
			1	2	3
			1	2	3
			1	2	3
			1	2	3
			1	2	3

			// Matrix1 after running Example program
			1	1	1
			1	1	2
			2	2	2
			2	3	3
			3	3	3
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.Reorder();
		Parameters:
			bRowOrder=If TRUE re-order to Row order and if FALSE re-order to Column order
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::FlipHorizontal, matrixbase::FlipVertical, matrixbase::Rotate, matrixbase::Transpose
	*/
	BOOL	Reorder(BOOL bRowOrder = TRUE); // Re-order a matrix from Column order to Row order or from Row order to Column order.

	/**
			Transpose a matrix. Rows become columns and columns become rows.
		Sample Data:
			// Matrix1 is 5 x 3 with following data
			1	2	3
			1	2	3
			1	2	3
			1	2	3
			1	2	3

			// Matrix1 after running Example program
			1	1	1	1	1
			2	2	2	2	2
			3	3	3	3	3
		Example:
			// Assumes Matrix1 window in Origin with Sample Data 
			Matrix mat("Matrix1");
			mat.Transpose();
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			matrixbase::FlipHorizontal, matrixbase::FlipVertical, matrixbase::Rotate, matrixbase::Transpose
	*/
	BOOL	Transpose(); // Transpose a matrix.
	
	/**
			Multiply two matrices element by element placing the result in this
			matrix. The underlying base type of the matrix passed as an argument
			must be "less than or equal" to the underlying base type of this matrix.
			The matrices must have the same size.  
		Example:
			matrix<double> m1(2,2) = {{0,1},{2,3}}, m2(2,2) = {{4,5},{6,7}};
			m2.DotMultiply( m1 );
			printf( "m2[0][0]=%g\tm2[0][1]=%g\n", m2[0][0], m2[0][1] );
			printf( "m2[1][0]=%g\tm2[1][1]=%g\n", m2[1][0], m2[1][1] );
		Parameters:
			mb=Input matrix which is multiplied with this matrix.
		Return:
			Returns TRUE on success and FALSE on Failure.
		SeeAlso:
			matrixbase::DotDivide, matrixbase::DotPower, matrixbase::Cross
	*/
	BOOL	DotMultiply(matrixbase &mb); // Multiply two matrices element by element.

	/**
			Divide this matrix by another matrix on an element by element basis
			placing the result in this matrix. The underlying base type of the
			matrix passed as an argument must be "less than or equal" to the underlying
			base type of this matrix. The matrices must have the same size.  
		Example:
			matrix<double> m2(2,2) = {{15,12},{9,6}}, m1(2,2) = {{5,4},{3,2}};
			m2.DotDivide( m1 );
			printf( "m2[0][0]=%g\tm2[0][1]=%g\n", m2[0][0], m2[0][1] );
			printf( "m2[1][0]=%g\tm2[1][1]=%g\n", m2[1][0], m2[1][1] );
		Parameters:
			mb=The input divisor matrix which is divided into this matrix
		Return:
			Returns TRUE on success and FALSE on Failure.
		SeeAlso:
			matrixbase::DotMultiply, matrixbase::DotPower, matrixbase::Cross
	*/
	BOOL	DotDivide(matrixbase &mb); // Divide this matrix by another matrix.

	/**
			Raise this matrix to the power of another matrix on an element by element
			basis placing the result in this matrix. The underlying base type of the
			matrix passed as an argument must be "less than or equal" to the underlying
			base type of this matrix. The matrices must have the same size.  
		Example:
			matrix<double> m2(2,2) = {{16,32},{2,3}}, m1(2,2) = {{0.5,0.6},{3,2}};
			m2.DotPower( m1 );
			printf( "m2[0][0]=%g\tm2[0][1]=%g\n", m2[0][0], m2[0][1] );
			printf( "m2[1][0]=%g\tm2[1][1]=%g\n", m2[1][0], m2[1][1] );
		Parameters:
			mb=Input matrix to which this matrix is raised (the exponents)
		Return:
			Returns TRUE on success and FALSE on Failure.
		SeeAlso:
			matrixbase::DotDivide, matrixbase::DotMultiply, matrixbase::Cross
	*/
	BOOL	DotPower(matrixbase &mb); // Raise this matrix to the power of another matrix.

	/**
			Sort a matrix in row order (across rows from top/left to bottom/right). The matrix
			1  5  9									 1  2  3
			2  6 10									 4  5  6
			3  7 11									 7  8  9
			4  8 12		would become the matrix 	10 11 12 	after sorting. This function does not
			maintain row wise integrity.
		Example:
			// Assumes Matrix1 window in Origin with unsorted data 
			Matrix mat("Matrix1");
			mat.Sort();
		Parameters:
			bAscending=Sort in ascending order if TRUE otherwise sort in descending order
	*/
	void	Sort(BOOL bAscending = TRUE);

	/**
			Get the maximum cell value in the matrix (as a double).
		Example:
			// Assumes Matrix1 window in Origin
			double dMax;
			Matrix mat("Matrix1");
			dMax = mat.GetMax();
		Return:
			Returns the maximum cell value in the matrix (as a double).
		SeeAlso:
			matrixbase::GetMin, matrixbase::GetMean, matrixbase::GetMedian
	*/
	double	GetMax(); // Returns the maximum cell value in the matrix.

	/**
			Get the minimum cell value in the matrix (as a double).
		Example:
			// Assumes Matrix1 window in Origin
			double dMin;
			Matrix mat("Matrix1");
			dMin = mat.GetMin();
		Return:
			Returns the minimum cell value in the matrix (as a double).
		SeeAlso:
			matrixbase::GetMax, matrixbase::GetMean, matrixbase::GetMedian
	*/
	double	GetMin();

	/**
			Get the median cell value of the matrix (as a double). If there are an even
			number N of cells in the matrix the average of the N/2 and (N+1)/2 sorted
			cell values is returned.
		Example:
			// Assumes Matrix1 window in Origin
			double dMedian;
			Matrix mat("Matrix1");
			dMedian = mat.GetMedian();
		Return:
			Returns the median cell value of the matrix (as a double).
		SeeAlso:
			matrixbase::GetMean, matrixbase::GetMin, matrixbase::GetMax
	*/
	double	GetMedian();

	/**
			Get the mean cell value of the matrix (as a double).
		Example:
			// Assumes Matrix1 window in Origin
			double dMean;
			Matrix mat("Matrix1");
			dMean = mat.GetMean();
		Return:
			Returns the mean cell value of the matrix (as a double).
		SeeAlso:
			matrixbase::GetMedian, matrixbase::GetMin, matrixbase::GetMax
	*/
	double	GetMean();

	/**
			Remove any row in the matrix that consists entirely of missing values
			(i.e. remove empty rows). Optionally remove any row that contains one
			or more missing values. This function is useful for removing missing
			values from data and for determining whether or not analysis can
			logically proceed on data that is paired row wise.
		Example:
			// Assumes Matrix1 window in Origin
			int nRowIndex;
			Matrix mat("Matrix1");
			nRowIndex = mat.RemoveEmptyRows();
		Parameters:
			bOnlyRemoveEmptyRows=When TRUE only remove rows consisting entirely of missing values. When FALSE
				remove all rows containing one or more missing values
		Returns:
			Returns -1 * the row number (1 based offset) of the first row that contains a missing value but that
			does not consist entirely of missing values (the first row that contains a missing value but that is not
			empty) otherwise the number of rows removed is returned.
	*/
	int		RemoveEmptyRows(BOOL bOnlyRemoveEmptyRows = TRUE);

	/**
 			Shrink this matrix by averaging cell values together according to the
 			column and row shrink factors. This is similar to the LabTalk mat.Shrink() method.
		Example:
			 matrix m1;
			 m1.SetSize( 15, 12 );
			 m1.Shrink( 3, 5 );
			 ASSERT( m1.GetNumCols()==4 );
			 ASSERT( m1.GetNumRows()==3 );
		Parameters:
			 dColShrinkFactor=column shrink factor
			 dRowShrinkFactor=row shrink factor
		Returns:
			 Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	Shrink( int nColShrinkFactor, int nRowShrinkFactor );

	/**
			Get a subset of this matrix specified by 0 based column and row indices.
		Example:
			matrix m1, m2;
			m1.SetSize( 10, 10 );
			m1.GetSubMatrix( m2, 5, -1, 5 ); // Copy lower right quarter of matrix m1 into matrix m2
			ASSERT( m2.GetNumCols()==5 );
			ASSERT( m2.GetNumRows()==5 );
		Parameters: 
			mbTarget=Matixbase derived object containing returned matrixbase subset
			c1=Begining column index, default is 0 (0 based offset) 
			c2=Ending column index, (inclusive) default -1 is GetNumCols -1 (0 based offset) 
			r1=Begining row index, default is 0 (0 based offset) 
			r2=Ending row index, (inclusive) default -1 is GetNumRows -1 (0 based offset)
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	GetSubMatrix( matrixbase& mbTarget, int c1 = 0, int c2 = -1, int r1 = 0, int r2 = -1); // -1 means to last col/row

	/**
			Set a subset of this matrix specified by 0 based column and row indices. The source
			and target matrices can have different types and different dimensions but the target
			matrix is never resized even if the source matrix is larger than the target.
		Example:
			Matrix mat1("Matrix1");
			Matrix mat2("Matrix2");			
			mat2.SetSubMatrix(mat1, 10, 10);
			
			matrix<double> mtxSrc = { {1.1,2.1}, {3.1,4.2} };
			matrix<int> mtxDest = 	 { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };
									   
			mtxDest.SetSubMatrix(mtxSrc, 0, 0);
		
			ASSERT(mtxDest[0][0] == 1);
			ASSERT(mtxDest[0][1] == 2);
			ASSERT(mtxDest[0][2] == 0);
			ASSERT(mtxDest[0][3] == 0);
			
			ASSERT(mtxDest[1][0] == 3);
			ASSERT(mtxDest[1][1] == 4);
			ASSERT(mtxDest[1][2] == 0);
			ASSERT(mtxDest[1][3] == 0);
		
			ASSERT(mtxDest[2][0] == 0);
			ASSERT(mtxDest[2][1] == 0);
			ASSERT(mtxDest[2][2] == 0);
			ASSERT(mtxDest[2][3] == 0);
		
			ASSERT(mtxDest[3][0] == 0);
			ASSERT(mtxDest[3][1] == 0);
			ASSERT(mtxDest[3][2] == 0);
			ASSERT(mtxDest[3][3] == 0);
		Parameters: 
			mbSource = matixbase oject containing the subset to set
			c1 = Begining column index in the target matrix, default is 0 (0 based offset) 
			r1 = Begining row index in the target matrix, default is 0 (0 based offset) 
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	SetSubMatrix(matrixbase& mbSource, int c1 = 0, int r1 = 0);
	
	/**
			Copies a specified range from a worksheet to a matrix dynamically
			resizing the matrix as needed.
		Example:
			// Assumes Data1 worksheet and Matrix1 matrix exist in Origin
			Worksheet wks("Data1");
			Matrix mat1("Matrix1");
			BOOL bRet = TRUE;
			if(mat1 && wks)
				bRet = mat1.CopyFromWks(wks); //Copies the whole wks to m1
		Parameters: 
			wksSource=Source worksheet from which data is copied
			c1=Begining column index, default is 0 (0 based offset) 
			c2=Ending column index, (inclusive) default -1 is GetNumCols -1 (0 based offset) 
			r1=Begining row index, default is 0 (0 based offset) 
			r2=Ending row index, (inclusive) default -1 is GetNumRows -1 (0 based offset)
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	CopyFromWks(Worksheet & wksSource, int c1 = 0, int c2 = -1, int r1 = 0, int r2 = -1); // Copies a specified range from a worksheet to a matrix.

	
	
	
	/**
			Threshold replace for a matrix.
		Example:
			// Assumes Matrix1 exists in Origin and contains some missing values (NANUM)
			Matrix mat1("Matrix1");
			// Change all missing values (NANUM) in Matrix1 to 0 and all other values to missing values
			mat1.Replace( NANUM, 0, MATREPL_TEST_EQUAL | MATREPL_SET_TO_MISSING_VALUE_WHEN_TEST_RESULT_IS_FALSE );
		Parameters: 
			dThresholdVal=Threshold value to compare to cells in matrix
			dReplaceVal=Replacement value to use when decision passes
			wBitwiseOption=Combination of the following bits
				Bit Value Meaning 	                              Group
				0    1    Use Less Than in testing                TEST
				1    2    Use Equal in testing                    TEST
				2    4    Use Greater Than in testing             TEST
				3    8    Use Absolute values in testing          TEST
				4    16   Keep original sign when test is TRUE    ACTION
				5    32   Set to missing value when test is FALSE ACTION
			
			The following are also defined in the header file \OriginC\system\OC_const.h
					MATREPL_TEST_LESSTHAN	= 1,
					MATREPL_TEST_EQUAL		= 2,
					MATREPL_TEST_GREATER	= 4,
					MATREPL_USE_ABSOLUTE_VALUE_IN_TEST	= 8,
					MATREPL_KEEP_ORIGINAL_SIGN_WHEN_TEST_RESULT_IS_TRUE		= 16,
					MATREPL_SET_TO_MISSING_VALUE_WHEN_TEST_RESULT_IS_FALSE	= 32
		Return:
			Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	Replace( double dThresholdVal, double dReplaceVal = 0, uint wBitwiseOption = 0 );

	/**
			Get the Real part of a Complex matrix. Causes a runtime error if the
			underlying base type of the matrix is not Complex.
		Examples:
			matrix<complex> mComplex = { 1+2i, 3+4i };
			matrix mReal1, mReal2;
			mComplex.GetReal( mReal1 );  // mReal1 = { 1, 3 };
			printf( "mReal1[0][0]=%g\nmReal1[0][1]=%g", mReal1[0][0], mReal1[0][1] );
			mReal1.GetReal( mReal2 );    // Causes runtime error
		Parameters:
			mReal=Output matrix containing the Real part of this Complex matrix
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			matrixbase::GetImaginary, matrixbase::GetPhase, matrixbase::GetAmplitude, matrixbase::Conjugate, matrixbase::Cross, matrixbase::Inverse, matrixbase::MakeComplex 
	*/
	BOOL	GetReal( matrix &mReal ); // Get the Real part of a Complex matrix.

	/**
			Get the Imaginary part of a Complex matrix. Causes a runtime error if
			the underlying base type of the matrix is not Complex.
		Examples:
			matrix<complex> mComplex = { 1+2i, 3+4i };
			matrix mImag1, mImag2;
			mComplex.GetImaginary( mImag1 );      // mImag1 = { 2, 4 };
			printf( "mImag1[0][0]=%g\nmImag1[0][1]=%g", mImag1[0][0], mImag1[0][1] );
			mImag1.GetImaginary( mImag2 );        // Causes runtime error
		Parameters:
			mImag=Output matrix containing the Imaginary part of this Complex matrix
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			matrixbase::GetReal, matrixbase::GetPhase, matrixbase::GetAmplitude, matrixbase::Conjugate, matrixbase::Cross, matrixbase::Inverse, matrixbase::MakeComplex
	*/
	BOOL	GetImaginary( matrix &mImag ); // Get the Imaginary part of a Complex matrix. 
	
	/**
			Get the phase angle matrix, in radians, of the Complex matrix. Causes
			a runtime error if the underlying base type of the matrix is not Complex.
		Examples:
			matrix<complex> mComplex = { 1+2i, 3+4i };
			matrix mPhase1, mPhase2, mReal = { 1, 3 };
			mComplex.GetPhase( mPhase1 );
			printf( "mPhase1[0][0]=%g\nmPhase1[0][1]=%g", mPhase1[0][0], mPhase1[0][1] );
			mReal.GetPhase( mPhase2 ); // Causes runtime error
		Parameters:
			mPhase=Output matrix containing the phase angle matrix for this Complex matrix
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			matrixbase::GetReal, matrixbase::GetImaginary, matrixbase::GetAmplitude, matrixbase::Conjugate, matrixbase::Cross, matrixbase::Inverse, matrixbase::MakeComplex
	*/
	BOOL	GetPhase( matrix& mPhase ); // Get the phase angle matrix, in radians, of the Complex matrix.

	/**
			Get the amplitude(modulus) of the Complex matrix. Causes a runtime
			error if the underlying base type of the matrix is not Complex.
		Examples:
			matrix<complex> mComplex = { 1+2i, 3+4i };
			matrix mAmplitude1, mAmplitude2, mReal = { 1, 3 };
			mComplex.GetAmplitude( mAmplitude1 );
			printf( "mAmplitude1[0][0]=%g\nmAmplitude1[0][1]=%g", mAmplitude1[0][0], mAmplitude1[0][1] );
			mReal.GetAmplitude( mAmplitude2 ); // Causes runtime error
		Parameters:
			mAmplitude=Output matrix containing amplitude(modulus) matrix for this Complex matrix
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			matrixbase::GetReal, matrixbase::GetImaginary, matrixbase::GetPhase, matrixbase::Conjugate, matrixbase::Cross, matrixbase::Inverse, matrixbase::MakeComplex
	*/
	BOOL	GetAmplitude( matrix& mAmplitude ); // Get the amplitude(modulus) of the Complex matrix.

	/**
			Replace this matrix with the Inverse of this matrix. An error is 
			returned if the underlying base type of the matrix is not double.
		Example:
			matrix<double> mA(2,2), mB(2,2), mI(2,2);
			mA[0][0]= 3; mA[0][1]=-2;
			mA[1][0]=-1; mA[1][1]= 1;
			mB = mA;

			mA.Inverse();
		
			// Show mA x mB = mI = | 1 0 |
			//                     | 0 1 |
			mI[0][0]=mA[0][0]*mB[0][0]+mA[0][1]*mB[1][0];
			mI[0][1]=mA[0][0]*mB[0][1]+mA[0][1]*mB[1][1];
			mI[1][0]=mA[1][0]*mB[0][0]+mA[1][1]*mB[1][0];
			mI[1][1]=mA[1][0]*mB[0][1]+mA[1][1]*mB[1][1];
			
			printf( "mA\t\tx\t\tmB\t\t=\t\tmI\n" );
			printf( "| %g %g |\t\t\t| %g %g |\t\t\t| %g %g |\n", mA[0][0], mA[0][1], mB[0][0], mB[0][1], mI[0][0], mI[0][1] );
			printf( "| %g %g |\t\t\t| %g %g |\t\t\t| %g %g |\n", mA[1][0], mA[1][1], mB[1][0], mB[1][1], mI[1][0], mI[1][1] );
		Return:
			Returns 0 on success or one of the following error codes on failure:
				-1=Matrix is not N x N
				-2=Underlying type of matrix is not double
				-3=Can not find the function in the Nag DLL
			Nag Errors:
				11=The column or row size of the matrix is less than 1
				73=System failed to allocate memory
				357=Matrix is singular (it has no inverse)
		SeeAlso:
			matrixbase::GetReal, matrixbase::GetImaginary, matrixbase::GetPhase, matrixbase::GetAmplitude, matrixbase::Conjugate, matrixbase::Cross, matrixbase::MakeComplex
	*/
	int		Inverse(); // Replace this matrix with the Inverse of this matrix.

	/**
			Replace this matrix with the Conjugate of this matrix. A runtime error 
			occurs if the underlying base type of this matrix is not double or Complex.
		Example:
			matrix<complex> mA(2,2);
			mA[0][0] = 1+2i; mA[0][1] = 3;
			mA[1][0] = 4-1i; mA[1][1] = -2+2i;
			mA.Conjugate();
			for(int ii = 0; ii < 2; ii++)
			{
				for(int jj = 0; jj < 2; jj++)
					printf("%g + %gi, ",mA[ii][jj].m_re, mA[ii][jj].m_im);
				printf("\n");
				
			}
		Return:
			Returns 0 on success and -1 on failure which occurs if the matrix is empty.	
		SeeAlso:
			matrixbase::GetReal, matrixbase::GetImaginary, matrixbase::GetPhase, matrixbase::GetAmplitude, matrixbase::Cross, matrixbase::Inverse, matrixbase::MakeComplex
	*/
	int		Conjugate(); // Replace this matrix with the Conjugate of this matrix.

	/**
			Make a Complex matrix from two Real matrices (which must have the same
			dimensions).
		Example:
			matrix mA(2,2), mB(2,2);
			matrix<complex> mC(2,2);

			mA[0][0] = 1;			mB[0][0] = -2;
			mA[0][1] = -3;			mB[0][1] = 1;
			mA[1][0] = 4;			mB[1][0] =2;
			mA[1][1] = 5;			mB[1][1] = -3;

			mC.MakeComplex(mA,mB);

			for(int ii = 0; ii < 2; ii++)
				for(int jj = 0; jj < 2; jj++)
					printf("%g + %gi\n",mC[ii][jj].m_re,mC[ii][jj].m_im);
		Parameters:
			mbReal=The matrix containing the Real part
			mbImag=The matrix containing the Imaginary part
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			matrixbase::CastToInteger, matrixbase::CastToDouble, matrixbase::GetReal, matrixbase::GetImaginary, matrixbase::GetPhase, matrixbase::GetAmplitude, matrixbase::Conjugate, matrixbase::Cross, matrixbase::Inverse
	*/
	int		MakeComplex(matrixbase & mbReal, matrixbase & mbImag); // Make a Complex matrix from two Real matrices.

	/**
			Sum the columns of this matrix placing the result in a vector. The
			underlying base type of the vector must not be less than the underlying
			base type of the matrix.
		Example:
			matrix<complex> mC = { {1+2i,2+1i,3-5i},
			                       {1+2i,2+2i,7-3i} };
			vector<complex> vC(2);
			mC.SumColumns(vC);
			for(int ii = 0; ii < 3; ii++)
				printf("\t%g+%gi",vC[ii].m_re,vC[ii].m_im);
		Parameters:
			vbSum=Output vector containing the summed columns
		Return:
			Returns 0 on success and -1 on failure.
	*/	    
	int		SumColumns(vectorbase & vbSum); // Sum the columns of this matrix placing the result in a vector.
   
	/**
			Concatenate a matrix to this matrix placing the results in a third
			matrix. Matrices can be concatenated row wise or column wise. All
			three matrices must have the same underlying base type or a runtime
			error will be generated.
		Example:
			int ii, jj, nCols, nRows;
			matrix mSource1 = { {1,2,3}, {4,5,6}, {7,8,9} };
			matrix mSource2 = { {10,11,12}, {12,14,15} };
			matrix mSource3 = { {1,2}, {1,2}, {1,2} };
			matrix mResult;

			mSource1.Concatenate( 1, mSource2, mResult );

			nCols = mResult.GetNumCols();
			nRows = mResult.GetNumRows();
			for(ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t", mResult[ii][jj]);
				printf("\n");
			}
			printf("\n\n");
			
			mSource1.Concatenate( 2, mSource3, mResult);

			nCols = mResult.GetNumCols();
			nRows = mResult.GetNumRows();
			for(ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t", mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			nDim=Specifies whether the matrices are concatenated row wise (nDim=1) or column wise (nDim=2)
			mSource=Source matrix that is concatenated to this matrix
			mResult=The matrix resulting from the concatenation
		Return:
			Returns 0 on success or one of the following error codes on failure.
				-1=nDim is not 1 or 2
				-2=The source matrices do not have the same number of columns (when concatenating row wise)
					or rows (when concatenating column wise)
	*/
	int		Concatenate(int nDim, matrixbase & mSource, matrixbase & mResult ); // Concatenate a matrix to this matrix placing the results in a third matrix. 

	/**
			Shift this matrix placing the result in the matrix passed as an argument.
			Shifts can occur row wise or relative to the first dimension (nDim=1),
			column wise or relative to the second dimension (nDim=2), or relative
			to both or the first dimension and then the second dimension (nDim=-1
			default). The result matrix and this matrix can be the same
			(i.e. m1.FFTShift(m1);).
		Example:
			matrix mSource = {{1,2,3},{4,5,6},{7,8,9}};
			matrix mShifted;
			int ii, jj;
			printf("Before shifting:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.FFTShift(mShifted);
			printf("After shifting for FFT:\n");
			for(ii = 0; ii < mShifted.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mShifted.GetNumCols(); jj++)
					printf("%g\t",mShifted[ii][jj]);
				printf("\n");
			}

			mSource.FFTShift(mShifted, 1);
			printf("After shifting relative to first dimension:\n");
			for(ii = 0; ii < mShifted.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mShifted.GetNumCols(); jj++)
					printf("%g\t",mShifted[ii][jj]);
				printf("\n");
			}

			mSource.FFTShift(mShifted, 2);
			printf("After shifting relative to second dimension:\n");
			for(ii = 0; ii < mShifted.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mShifted.GetNumCols(); jj++)
					printf("%g\t",mShifted[ii][jj]);
				printf("\n");
			}
		Parameter:
			mbShifted=The output matrix in which the shifted matrix is returned 
			nDim=Shifts can occur row wise (relative to the first dimension when nDim=1), column wise (relative
				to the second dimension when nDim=2), or relative to both or the first dimension and then the second
				dimension (when nDim=-1 default)	 
		Return:
			Returns 0 on success and a non-zero error code on failure:
				-1=nDim is not -1, 1, or 2
				-2=Internal casting error
		SeeAlso:
			matrixbase::IFFTShift
	*/
	int		FFTShift(matrixbase & mbShifted,  int nDim = -1); // Shift this matrix placing the result in the matrix passed as an argument.

	/**
			Inverse FFTShift. Inverse FFTShifts can occur row wise or relative to the
			first dimension (nDim=1), column wise or relative to the second dimension
			(nDim=2), or relative to both or the first dimension and then the second
			dimension (nDim=-1 default). The result matrix and this matrix can be the
			same (i.e m1.IFFTShift(m1);).
		Example:
			matrix mSource = {{1,2,3},{4,5,6},{7,8,9}};
			matrix mShifted;
			int ii, jj;
			printf("Before shifting:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.FFTShift(mShifted);
			printf("After shifting for FFT:\n");
			for(ii = 0; ii < mShifted.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mShifted.GetNumCols(); jj++)
					printf("%g\t",mShifted[ii][jj]);
				printf("\n");
			}

			mShifted.IFFTShift(mShifted);
			printf("After un-shifting (IFFTShift) for FFT:\n");
			for(ii = 0; ii < mShifted.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mShifted.GetNumCols(); jj++)
					printf("%g\t",mShifted[ii][jj]);
				printf("\n");
			}
		Parameter:
			mbShifted=The output matrix in which the un-shifted matrix is returned 
			nDim=Inverse FFTShifts can occur row wise (relative to the first dimension when nDim=1), column wise (relative
				to the second dimension when nDim=2), or relative to both or the first dimension and then the second
				dimension (when nDim=-1 default)	 
		Return:
			Returns 0 on success and a non-zero error code on failure:
				-1=nDim is not -1, 1, or 2
				-2=Internal casting error
		SeeAlso:
			matrixbase::FFTShift
	*/
	int		IFFTShift(matrixbase & mbShifted,  int nDim = -1); // Inverse FFTShift.

	/**
			Round each cell of this matrix to the nearest integer less than
			the current cell value (toward minus infinity).			.
		Example:
			int ii, jj,	nRows, nCols;
			matrix mResult;
			matrix mSource = {{1.001,2.009,-3.99999,4.0005,-5.999},
			                  {-6.2000,7.345,8.9999,-9.0001,10.0001}};

			printf("The source data:\n");
			nCols = mSource.GetNumCols();
			nRows = mSource.GetNumRows();
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
				printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.Floor(mResult);

			printf("After Floor function:\n");
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
				printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbFloor=Output matrix containing the results
		Return:
			Returns 0 on success and a non-zero error code on failure. 
		SeeAlso:
			matrixbase::Fix, matrixbase::Round, matrixbase::Ceil
	*/
	int		Floor(matrixbase & mbFloor); // Round each cell of this matrix to the nearest integer less than the current cell value (toward minus infinity).

	/**
			Round each cell of this matrix to the nearest integer (toward zero).			.
		Example:
			int ii, jj,	nRows, nCols;
			matrix mResult;
			matrix mSource = {{1.001,2.009,-3.99999,4.0005,-5.999},
			                  {-6.2000,7.345,8.9999,-9.0001,10.0001}};

			printf("The source data:\n");
			nCols = mSource.GetNumCols();
			nRows = mSource.GetNumRows();
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.Fix(mResult);

			printf("After Fix function:\n");
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbFix=Output matrix containing the results
		Return:
			Returns 0 on success and a non-zero error code on failure. 
		SeeAlso:
			matrixbase::Floor, matrixbase::Round, matrixbase::Ceil
	*/
	int		Fix(matrixbase & mbFix); // Round each cell of this matrix to the nearest integer (toward zero).

	/**
			Round each cell of this matrix to the nearest integer (absolute nearest).			.
		Example:
			int ii, jj,	nRows, nCols;
			matrix mResult;
			matrix mSource = {{1.001,2.009,-3.99999,4.0005,-5.999},
			                  {-6.2000,7.345,8.9999,-9.0001,10.0001}};

			printf("The source data:\n");
			nCols = mSource.GetNumCols();
			nRows = mSource.GetNumRows();
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.Round(mResult);

			printf("After Round function:\n");
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbRound=Output matrix containing the results
		Return:
			Returns 0 on success and a non-zero error code on failure. 
		SeeAlso:
			matrixbase::Floor, matrixbase::Fix, matrixbase::Ceil
	*/
	int		Round(matrixbase & mbRound); // und each cell of this matrix to the nearest integer (absolute nearest).
	
	/**
			Round each cell of this matrix to the nearest integer greater than the
			current cell value (toward positive infinity).			.
		Example:
			int ii, jj,	nRows, nCols;
			matrix mResult;
			matrix mSource = {{1.001,2.009,-3.99999,4.0005,-5.999},
			                  {-6.2000,7.345,8.9999,-9.0001,10.0001}};

			printf("The source data:\n");
			nCols = mSource.GetNumCols();
			nRows = mSource.GetNumRows();
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			mSource.Ceil(mResult);

			printf("After Ceil function:\n");
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbCeil=Output matrix containing the results
		Return:
			Returns 0 on success and a non-zero error code on failure. 
		SeeAlso:
			matrixbase::Floor, matrixbase::Fix, matrixbase::Round
	*/
	int		Ceil(matrixbase & mbCeil); // Round each cell of this matrix to the nearest integer greater than the current cell value (toward positive infinity).

	/**
			Make this matrix an N x N identity matrix or an M x N rectangular matrix
			with 1's on the diagonal and zeros elsewhere.
		Example:
			int ii, jj,	nRows, nCols;
			matrix mIdentity;
		
			mIdentity.MakeIdentity(4);
			nCols = mIdentity.GetNumCols();
			nRows = mIdentity.GetNumRows();
			for( ii = 0; ii < nRows; ii++)
			{
				for(jj = 0; jj < nCols; jj++)
					printf("%g\t",mIdentity[ii][jj]);
				printf("\n");
			}
		Parameter:
			mNumRows=Number of rows in the result matrix
			nNumCols=Number of columns of the result matrix (default -1 means mNumRows = nNumCols)
		Return:
			Returns 0 on success or an error code on failure:
				-1=nNumCols and mNumRows are not positive integers (nNumCols can be -1)
		SeeAlso:
			matrixbase::GetLowerTriangular, matrixbase::GetUpperTriangular
	*/
	int		MakeIdentity(int mNumRows, int nNumCols = -1);

	/**
			Copy this matrix and cast the underlying base type to double. 
		Example:
			int ii, jj;
			matrix<int> mInts = {{1,2,3},{4,5,6},{7,8,9}};
			mInts *= 1.1;
						
			printf("Intergers:\n");
			for(ii = 0; ii < mInts.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mInts.GetNumCols(); jj++)
					printf("%d\t",mInts[ii][jj]);
				printf("\n");
			}

			matrix<double> mDoubles;
			mInts.CastToDouble(mDoubles);
			mDoubles *= 1.1;
			
			printf("Doubles:\n");
			for(ii = 0; ii < mDoubles.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mDoubles.GetNumCols(); jj++)
					printf("%g\t",mDoubles[ii][jj]);
				printf("\n");
			}
		Parameters:
			mDouble=The result matrix having an underlying base type of double
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::MakeComplex, matrixbase:CastToInteger
	*/
	int		CastToDouble(matrix & mDouble); // Copy this matrix casting the underlying base type to double.

	/**
			Round this matrix placing the results in a matrix having an underlying
			base type of int. The input matrix must have an underlying base type of
			float or double or a run time error is generated. 
		Example:
			int ii, jj;
			
			matrix<double> mDoubles = {{1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}};
			printf("Doubles:\n");
			for(ii = 0; ii < mDoubles.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mDoubles.GetNumCols(); jj++)
					printf("%g\t",mDoubles[ii][jj]);
				printf("\n");
			}
			
			matrix<int> mInts; 
			mDoubles.CastToInteger(mInts);
						
			printf("Intergers:\n");
			for(ii = 0; ii < mInts.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mInts.GetNumCols(); jj++)
					printf("%d\t",mInts[ii][jj]);
				printf("\n");
			}
		Parameters:
			mInteger=The result matrix having an underlying base type of int
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::MakeComplex, matrixbase::CastToDouble
	*/
	int		CastToInteger(matrix<int> & mInteger); // Round this matrix placing the results in a matrix having an underlying base type of int.

	/**
			Get a lower triangular matrix from this matrix. This matrix and the
			result matrix may be the same.
		Example:
			int ii, jj;

			matrix mSource = {{1,2,3},{4,5,6},{7,8,9}};
			printf("Source:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}
			
			matrix mResult; 
			mSource.GetLowerTriangular(mResult);
						
			printf("Lower Triangular:\n");
			for(ii = 0; ii < mResult.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mResult.GetNumCols(); jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbResult=The result matrix containing only the lower part 
			nNumDiagonal=Default 0 is the main diagonal, > 0 is above the
				main diagonal, and < 0 is below the main diagonal.
		Return:
			Returns 0 on success and a non-zero error code on failure.
		   		-1=Internal cast error.
		SeeAlso:
			matrixbase::GetUpperTriangular, matrixbase::MakeIdentity, matrixbase::SetDiagonal, matrixbase::GetDiagonal
	*/
	int		GetLowerTriangular(matrixbase & mbResult, int nNumDiagonal = 0); // Get a lower triangular matrix from this matrix.

	/**
			Get an upper triangular matrix from this matrix. This matrix and 
			the result matrix may be the same.
		Example:
			int ii, jj;

			matrix mSource = {{1,2,3},{4,5,6},{7,8,9}};
			printf("Source:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}
			
			matrix mResult; 
			mSource.GetUpperTriangular(mResult);
						
			printf("Upper Triangular:\n");
			for(ii = 0; ii < mResult.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mResult.GetNumCols(); jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbResult=The result matrix containing only the lower part 
			nNthDiagonal=The number specifying N-th diagonal, default 0 is the main diagonal, > 0 is above
				the main diagonal, and < 0 is below the main diagonal.
		Return:
			Returns 0 on success and a non-zero error code on failure.
		   		-1=Internal cast error.
		SeeAlso:
			matrixbase::GetLowerTriangular, matrixbase::MakeIdentity, matrixbase::SetDiagonal, matrixbase::GetDiagonal
	*/
	int		GetUpperTriangular(matrixbase & mbResult, int nNthDiagonal = 0); // Get an upper triangular matrix from this matrix. 

	/**
			Get the diagonal or N-th diagonal of this matrix and place the result
			in a vector. The result vector and this matrix must have the same underlying
			base type or a run time error will be generated.
		Example:
			int ii, jj;

			matrix mSource = {{1,2,3},{4,5,6},{7,8,9}};
			printf("Source:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}
			
			vector vResult; 
			mSource.GetDiagonal(vResult);
			printf("Diagonal:\n");
			for(ii = 0; ii < vResult.GetSize(); ii++)
				printf("%g\t",vResult[ii]);
			printf("\n");
			
			mSource.GetDiagonal(vResult,-1);
			printf("-1th Diagonal:\n");
			for(ii = 0; ii < vResult.GetSize(); ii++)
				printf("%g\t",vResult[ii]);
			printf("\n");
		Parameters:
			vbDiagonal=The result vector containing the (N-th) diagonal
			nNthDiagonal=The number specifying the N-th diagonal, default 0 is the main diagonal, > 0 is above
				the main diagonal, and < 0 is below the main diagonal.
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::SetDiagonal, matrixbase::GetLowerTriangular, matrixbase::GetUpperTriangular, matrixbase::MakeIdentity
	*/
	int		GetDiagonal(vectorbase & vbDiagonal, int nNthDiagonal = 0); // Get the diagonal or N-th diagonal of this matrix.

	/**
			Set the diagonal or N-th diagonal of this matrix from a vector and set all
			other elements to 0. The source vector and this matrix must have the same
			underlying base type or a run time error will be generated.
		Example:
			int ii, jj;

			matrix mResult = {{1,2,3},{4,5,6},{7,8,9}};
			printf("Result:\n");
			for(ii = 0; ii < mResult.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mResult.GetNumCols(); jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
			
			vector vSource = {1,1}; 
			mResult.SetDiagonal(vSource,1);
			printf("Result after diagonal is set to 0:\n");
			for(ii = 0; ii < mResult.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mResult.GetNumCols(); jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			vbDiagonal=The source vector containing the (N-th) diagonal
			nNthDiagonal=The number specifying the N-th diagonal, default 0 is the main diagonal, > 0 is above
				the main diagonal, and < 0 is below the main diagonal.
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::GetDiagonal, matrixbase::GetLowerTriangular, matrixbase::GetUpperTriangular, matrixbase::MakeIdentity
	*/
	int		SetDiagonal(vectorbase & vbDiagonal, int nNthDiagonal = 0); // Set the diagonal or N-th diagonal of this matrix.

	/**
			Cross product of this matrix and the source matrix along the dimension identified by iDim. The iDim
			dimension of both matrices must be three and the underlying base type of the source matrix must be
			less than or equal to the underlying base type of this matrix.
		Example:
			int ii, jj;
			matrix mA = {{1,2,3},{4,5,6}};
			matrix<int> mB = {{1,1,1},{1,1,1}} ;

			mA.Cross(mB,1);
			printf("mA x mB:\n");
			for(ii = 0; ii < mA.GetNumRows();  ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbSource=The source matrix
			nDim=Cross product can occur row wise (relative to the first dimension when nDim=1) or column wise (relative
				to the second dimension when nDim=2)
		Returns:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::DotMultiply, matrixbase::DotDivide, matrixbase::DotPower
	*/
	int		Cross(matrixbase & mbSource, int nDim = 1);

	/**
			Indicates whether or not an entire row or column of this matrix is comprised
			of all non-zero elements. For matrices having an underlying base type of double
			or complex a specified tolerance is used to determine whether or not each element
			is zero.
		Example:
			int ii, jj;

			matrix mA = {{0,2,3},{0,0,6},{7,8,9}};
			vector<BOOL> vRowIsAllNonZeros; 

			mA.AllNonZero(vRowIsAllNonZeros);

			printf("mA:\t\tAll non-zero\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("%d\n",vRowIsAllNonZeros[ii]);
			}
		Parameter:
			vAllNonZero=The result vector
			nDim=The AllNonZero test can occur row wise (relative to the first dimension when nDim=1) or 
				column wise (relative to the second dimension when nDim=2)
			dTol=The tolerance used to decide whether or not an element is zero (if abs(element) < dTol
				then the element is considered to be zero)
		Return:
 			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::AnyNonZero

	*/
	int		AllNonZero(vector<BOOL>  & vAllNonZero, int nDim  = 1, double dTol = DEFAULT_TOLERANCE); // Indicates whether or not an entire row or column of this matrix is comprised of all non-zero elements.

	/**
			Indicates whether or not each row or column of this matrix contains any
			(one or more) non-zero elements. For matrices having an underlying base
			type of double or complex the machine based precision is used to determine
			whether or not any element is zero.
		Example:
			int ii, jj;

			matrix mA = {{0,2,0},{0,0,6},{0,8,0}};
			vector<BOOL> vColumnHasAnyNonZeros; 

			mA.AnyNonZero(vColumnHasAnyNonZeros,2);

			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}
			
			printf("Any non-zero:\n");
			for(ii = 0; ii < mA.GetNumCols(); ii++)
				printf("%d\t",vColumnHasAnyNonZeros[ii]);
			printf("\n");
		Parameter:
			vAnyNonZero=The result vector
			nDim=The AnyNonZero test can occur row wise (relative to the first dimension when nDim=1) or 
				column wise (relative to the second dimension when nDim=2)
			dTol=The tolerance used to decide whether or not an element is zero (if abs(element) < dTol
				then the element is considered to be zero)
		Return:
 			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			matrixbase::AllNonZero
	*/
	int		AnyNonZero(vector<BOOL> & vAnyNonZero, int nDim = 1, double dTol = DEFAULT_TOLERANCE); // Indicates whether or not each row or column of this matrix contains any non-zero elements.

	/**
			Compute the cumulative product of this matrix. The underlying base type
			of this matrix must be less than or equal to the underlying base type of
			the result matrix. Currently only the double and complex types are supported
			for the result matrix.
		Example:	
			int ii, jj;

			matrix mA = {{1,2,3},{4,5,6},{7,8,9}}, mB;

			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}
			
			mA.CumulativeProduct(mB);
			
			printf("mB = Cumulative product of mA:\n");
			for(ii = 0; ii < mB.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mB.GetNumCols(); jj++)
					printf("%g\t",mB[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbProduct=The result matrix containing the cumulative product
			nDim=The CumulativeProduct function can operate row wise (relative to the first dimension when nDim=1) or 
				column wise (relative to the second dimension when nDim=2)
		Returns:
 			Returns 0 on success and a non-zero error code on failure.
 		SeeAlso:
 			matrixbase::CumulativeSum
	*/
	int		CumulativeProduct(matrixbase & mbProduct, int nDim = 1); 

	/**
			Compute the cumulative sum of this matrix. The underlying base type of this
			matrix must be less than or equal to the underlying base type of the result
			matrix. Currently only the double and complex types are supported for the
			result matrix.
		Example:	
			int ii, jj;

			matrix mA = {{1,2,3},{4,5,6},{7,8,9}}, mB;

			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}

			mA.CumulativeSum(mB);

			printf("mB = Cumulative sum of mA:\n");
			for(ii = 0; ii < mB.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mB.GetNumCols(); jj++)
					printf("%g\t",mB[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbSum=The result matrix containing the cumulative sum
			nDim=The CumulativeSum function can operate row wise (relative to the first dimension when nDim=1) or 
				column wise (relative to the second dimension when nDim=2)
		Returns:
 			Returns 0 on success and a non-zero error code on failure.
 		SeeAlso:
 			matrixbase::CumulativeProduct
	*/
	int		CumulativeSum(matrixbase & mbSum, int nDim = 1);

	/**
			Compute the N-th order row wise or column wise difference of the elements in this
			matrix. The difference matrix is computed by replacing the current element with
			the current element minus the previous element along the dimension specified by
			nDim. The N-th order difference approximates the N-th order derivative. If nOrder
			is greater than or equal to the size of the dimension identified by nDim than an
			empty matrix is returned. The underlying base type of this matrix and the result
			matrix must be the same.
		Example:
			int ii, jj;
			matrix mSource = {{8,2,5,4,2},{1,7,11,9,3}};

			printf("The source matrix:\n");
			for(ii = 0; ii < mSource.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mSource.GetNumCols(); jj++)
					printf("%g\t",mSource[ii][jj]);
				printf("\n");
			}

			matrix mResult;
			mSource.Difference(mResult);


			printf("The result matrix:\n");
			for(ii = 0; ii < mResult.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mResult.GetNumCols(); jj++)
					printf("%g\t",mResult[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbDifference=The result matrix containing the difference
			nOrder=The order of difference to compute, default is 1
			nDim=The Difference function can operate row wise (relative to the first dimension when nDim=1) or 
				column wise (relative to the second dimension when nDim=2), default is 1 or row wise
		Return:
			 Returns 0 on success and a non-zero error code on failure.
	*/
	int		Difference(matrixbase & mbDifference, int nOrder = 1, int nDim = 1); // Compute the N-th order row wise or column wise difference of the elements in this matrix.
	
	/**
			Wrap around elements.
		Parameters:
			when the value is 0, no wrap, when value less than zero, do left_wrap, other wise do right_wrap.
		Examples:
			matrix mat = {{1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}};
			mat.Wrap(0, 2);
			==> {{3,4,5,1,2}, {8,9,10,6,7}, {13,14,15,11,12}}
			mat.Wrap(2, 0);
			==> {{11,12,13,14,15}, {1,2,3,4,5}, {6,7,8,9,10}}
	*/
	BOOL Wrap(int nRowNum=0, int nColNum =0); 


#if  _OC_VER > 0x0703


#ifdef	ORIGIN_COM_SUPPORT
	/**#
		Set matrix elements from variant encountered in LabView's data.
	Parameters:
		v=variant that is VT_ARRAY|VT_VARIANT type and subvariants are of VT_ARRAY|<numeric> type.
	Examples:
		matrix		mat;        
		
		_VARIANT	var00, var01, var10, var11;
		var00 = 11, var01 = 12;
		var10 = 21, var11 = 22;
		
		_VARIANT	var0, var1;
		var0.CreateAsArray( VT_VARIANT, 2 );
		var0.SetOneVariantInArray( var00, 0 );
		var0.SetOneVariantInArray( var10, 1 );
		var1.CreateAsArray( VT_VARIANT, 2 );
		var1.SetOneVariantInArray( var01, 0 );
		var1.SetOneVariantInArray( var11, 1 );
	
		_VARIANT	var;
		var.CreateAsArray( VT_VARIANT, 2 );
		var.SetOneVariantInArray( var0, 0 );
		var.SetOneVariantInArray( var1, 1 );
		
		BOOL	bRet = mat.SetByArrayInVariant( var );
		ASSERT(bRet);
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
		*/
	BOOL SetByArrayInVariant(_VARIANT v);

	/**#
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	*/
	_VARIANT	GetAs2DArray();

#endif //	ORIGIN_COM_SUPPORT



	/**#
		Function to find all instances of a value in a matrix
	Parameters:
		vecR, vecC = indices of all cells in matData where value was found.
		dLower = the lower bound for the value to be found. Set this to exact value when you just want to search for a single value and not use bounds.
		dUpper = the upper bound for the value to be found. Leave it as default (_ONAN) if searching for only a single value.
		nPrecision = sets the level of precision to be used in the search. This parameter will be ignored if dUpper isn't the default one.
		r1, c1 = indices of cell in matData from where to start the search - leave as 0 to start from the first cell
		r2, c2 = indices of cell in matData up to which the search should be done - leave as -1 to search to last cell
	Examples:
		matrix<double> mtx = {{0.01, 0.02, 0.04}, {0.04, 0.05, 0.06}, {0.07, 0.08, 0.09}};
		vector<uint> vr;
		vector<uint> vc;
		mtx.Find(vr, vc, 0.04);
		ASSERT( 0 == vr[0]);
		ASSERT( 2 == vc[0]);
		ASSERT( 1 == vr[1]);
		ASSERT( 0 == vc[1]);
		ASSERT( 2 == vr.GetSize());
		ASSERT( 2 == vc.GetSize());
	Return:
		Return -1 if no values were found, otherwise return "n" where n is the number of values found.
	*/
	int Find(vector<uint> &vecR, vector<uint> &vecC, double dLower, double dUpper = _ONAN, int nPrecision = 8, int r1 = 0, int c1 = 0,int r2 = -1,int c2 = -1);

	/**#
			Copy a subset of this matrix specified by 0 based column and row indices to a worksheet object
		Example:
			matrix<int> m1;
			m1.SetSize( 10, 10 );
			for(int jj = 0; jj < 10; jj++)
				for(int ii = 0; ii < 10; ii++)
					m1[ii][jj] = ii*jj;
			
			
			Worksheet wks("data1");
			m1.CopyTo( wks, 5, 5, 6, 6); 
			ASSERT(wks.Cell(0, 0) == 25);
			ASSERT(wks.Cell(0, 1) == 30);
			ASSERT(wks.Cell(1, 0) == 30);
			ASSERT(wks.Cell(1, 1) == 36);
		Parameters: 
			wksTarget= worksheet object to receive result 
			r1=Begining row index, default is 0 (0 based offset) 
			c1=Begining column index, default is 0 (0 based offset) 
			r2=Ending row index, (inclusive) default -1 is GetNumRows -1 (0 based offset)
			c2=Ending column index, (inclusive) default -1 is GetNumCols -1 (0 based offset) 
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	CopyTo(Worksheet& wksTarget, int r1 = 0, int c1 = 0, int r2 = -1, int c2 = -1);

	
	/**#
			Copy a subset of this matrix specified by 0 based column and row indices to a specified matrix
		Example:
			matrix<int> m1;
			m1.SetSize( 10, 10 );
			for(int jj = 0; jj < 10; jj++)
				for(int ii = 0; ii < 10; ii++)
					m1[ii][jj] = ii*jj;
			
			matrix m2;

			m1.CopyTo( m2, 5, 5); 
			ASSERT( m2.GetNumCols() == 5 );
			ASSERT( m2.GetNumRows() == 5 );
			
			m1.CopyTo( m2, 5, 5, 6, 6); 
			ASSERT( m2.GetNumCols() == 2 );
			ASSERT( m2.GetNumRows() == 2 );	

			ASSERT(m2[0][0] == 25);
			ASSERT(m2[0][1] == 30);
			ASSERT(m2[1][0] == 30);
			ASSERT(m2[1][1] == 36);
		Parameters: 
			r1=Begining row index, default is 0 (0 based offset) 
			c1=Begining column index, default is 0 (0 based offset) 
			r2=Ending row index, (inclusive) default -1 is GetNumRows -1 (0 based offset)
			c2=Ending column index, (inclusive) default -1 is GetNumCols -1 (0 based offset) 
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	CopyTo(matrixbase& matTarget, int r1 = 0, int c1 = 0, int r2 = -1, int c2 = -1);

	/**#
			Copies a specified range from a worksheet to a matrix dynamically
			resizing the matrix as needed.
		Example:
			// Assumes Data1 worksheet and Matrix1 matrix exist in Origin
			Worksheet wks("Data1");
			Matrix mat1("Matrix1");
			BOOL bRet = TRUE;
			if(mat1 && wks)
				bRet = mat1.CopyFrom(wks); //Copies the whole wks to m1
		Parameters: 
			wksSource=Source worksheet from which data is copied
			r1=Begining row index, default is 0 (0 based offset) 
			c1=Begining column index, default is 0 (0 based offset) 
			r2=Ending row index, (inclusive) default -1 is GetNumRows -1 (0 based offset)
			c2=Ending column index, (inclusive) default -1 is GetNumCols -1 (0 based offset) 
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	CopyFrom(Worksheet & wksSource, int r1 = 0, int c1 = 0, int r2 = -1, int c2 = -1); 
	
	/**#
			Set this matrix by another one specified by 0 based column and row indices.
			The source and target matrices need to have the same data type, otherwise,
			this method will return false.
		Example:
			Matrix mat1("Matrix1");
			Matrix mat2("Matrix2");			
			mat2.CopyFrom(mat1, 10, 10);
		Parameters: 
			mbSource = matixbase oject containing the subset to set
			r1 = Begining row index in the target matrix, default is 0 (0 based offset) 
			c1 = Begining column index in the target matrix, default is 0 (0 based offset) 
		Return:
		 	Returns TRUE on successful exit and FALSE on failure.
	*/
	BOOL	CopyFrom(matrixbase& mbSource, int r1 = 0, int c1 = 0);



#endif //  _OC_VER > 0x0703
	/**
	  rearrange the matrix according to the given indeces
	  Example: 	   
		vector<UINT> vn = {2,1,0};
	    matrix<int> mm1 = {{1,1},{2,2},{3,3}};
	    mm1.ReorderRowWise(vn, 0);
	    // result mm1 = {{3,3},{2,2},{1,1}};
	  Parameters:
	    vnIndeces = array or row index to reorder a column
	    nC1 = 1st Column index to reorder
	    nC2 = last Column index to reorder, use -1 to indicate the last column in matrix
	        
	*/
	BOOL ReorderRowWise(const vector<UINT>& vnIndeces, int nC1 = 0, int nC2 = -1 );


};

/////////////////////////////////////////////////////////////////////////
// matrix (with lower case m) object
/** >Composite Data Types
		An Origin C matrix (lower case m) is a dynamically allocated and sized two
		dimensional array that is not tied to an internal Origin matrix allowing
		a greater degree of flexibility. matrix is a template class with a default
		type of double but a matrix of any basic data type (including char, byte,
		short, word, int, and uint but not string) can be constructed using the
		syntax matrix<type>. The matrix class is derived from the matrixbase class
		from which it inherits methods and properties.
	Example:
		int ii, jj;
		matrix<int> mInts = {{1,2,3},{4,5,6},{7,8,9}};
		printf("mInts:\n");
		for(ii = 0; ii < mInts.GetNumRows(); ii++)
		{
			for(jj = 0; jj < mInts.GetNumCols(); jj++)
				printf("%d\t",mInts[ii][jj]);
			printf("\n");
		}

		matrix mDoublesByDefault = {{1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}};
		printf("mDoublesByDefault:\n");
		for(ii = 0; ii < mDoublesByDefault.GetNumRows(); ii++)
		{
			for(jj = 0; jj < mDoublesByDefault.GetNumCols(); jj++)
				printf("%g\t",mDoublesByDefault[ii][jj]);
			printf("\n");
		}
*/
class matrix : public matrixbase
{

public:
	
	/**
			Default constructor for matrix class.
		Example:
			int ii, jj;
			matrix<int> mInts = {{1,2,3},{4,5,6},{7,8,9}};
			printf("mInts:\n");
			for(ii = 0; ii < mInts.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mInts.GetNumCols(); jj++)
					printf("%d\t",mInts[ii][jj]);
				printf("\n");
			}

			matrix mDoublesByDefault = {{1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}};
			printf("mDoublesByDefault:\n");
			for(ii = 0; ii < mDoublesByDefault.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mDoublesByDefault.GetNumCols(); jj++)
					printf("%g\t",mDoublesByDefault[ii][jj]);
				printf("\n");
			}
	*/
	matrix(); // Default constructor for matrix class.

	/**
			Copy constructor for matrix class.
		Example:
			int ii, jj;
			matrix mA = {{1,2,3},{4,5,6},{7,8,9}};
			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}

			matrix mB( mA );
			printf("mB Copy of mA:\n");
			for(ii = 0; ii < mB.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mB.GetNumCols(); jj++)
					printf("%g\t",mB[ii][jj]);
				printf("\n");
			}
		Parameters:
			mbOriginal=Matrix that is copied
	*/
	matrix(matrixbase & mbOriginal); // Copy constructor for matrix class.

	/**
			Constructor for matrix class that constructs a matrix object from a Dataset object.
		Example:
			// Assumes Data1_A data set with 9 elements exists in Origin
			int ii, jj;
			Dataset dsA("Data1_A");
			matrix mA( dsA ); // Construct a matrix from Data1_A
			mA.SetSize(3,3);
			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
					printf("%g\t",mA[ii][jj]);
				printf("\n");
			}
		Parameters:
			dsDataset=Dataset object from which a matrix object is created
	*/
	matrix(Dataset dsDataset); // Constructor for matrix class that constructs a matrix object from a Dataset object.
	
	/**
			Constructor for matrix class that constructs a matrix having a specific size.
		Example:
			int ii, jj;
			matrix mA(4,5); // Construct an empty 4 x 5 matrix

			printf("mA:\n");
			for(ii = 0; ii < mA.GetNumRows(); ii++)
			{
				for(jj = 0; jj < mA.GetNumCols(); jj++)
				{
					mA[ii][jj] = ii + jj;	
					printf("%g\t",mA[ii][jj]);
				}
				printf("\n");
			}
		Parameters:
			nNumRows=Number of rows in constructed matrix
			nNumCols=Number of columns in constructed matrix 
	*/
	matrix(UINT nNumRows, UINT nNumCols); // Constructor for matrix class that constructs a matrix having a specific size.

#if  _OC_VER > 0x0703
	/**
			Initialize the matrix by copying the data from the source Matrix associated with
			the MatrixObject mo. If bWriteback, on exiting the scope in which the matrix object was declared,
			if writes back the values into the source Matrix. The originla size of the source matrix can be
			retrieved using the method GetSourceDim().
		Example:
			// Have a matrix with the name "Matrix1" in the project, with some values.
			// After the function executes, the matrix will contain new values set inside
			// the nested for-loops.
			void	test_matrixobj_writeback()
			{
				MatrixObject		mo("Matrix1", 0);
			
				matrix				m(mo, TRUE);
				
				
				int					nRows, nCols;
				if (m.GetSourceDim(nRows, nCols))
					printf("rows = %d\tcols=%d\n", nRows, nCols);
					
				// Change the size and set new values:
				m.SetSize(7, 9);
				for (int row = 0; row < m.GetNumRows(); row++)
				{
					for (int col = 0; col < m.GetNumCols(); col++)
					{
						m[row][col] = (row + 1) * (col + 1);
					}
				}
				
			}
		Parameters:
			mo=the source Matrix object
			bWriteback=if TRUE, it will write back the new values into the source on exiting the scope.
	*/
	matrix(MatrixObject &mo,  BOOL bWriteback = FALSE);
	
	/**
			It returns the dimensions of the source Matrix used by the constructor
			matrix(MatrixObject &mo,  BOOL bWriteback = FALSE)
			if bWriteback is TRUE.
			See that constructor and the accompanying example for more details.
		Parameters:
			nRows=it receives the number of rows of the source.
			nCols=it receives the number of columns of the source.
		Return:
			TRUE if bWriteback was TRUE when calling the constructor, otherwise FALSE. 
			
	*/
	bool	GetSourceDim(int &nRows, int &nCols);
#endif //#if  _OC_VER > 0x0703

};

/////////////////////////////////////////////////////////////////////////
// Matrix (with upper case M) object
/** >Composite Data Types
		An Origin C Matrix (upper case M) is a dynamically allocated and sized two
		dimensional array that is tied to an internal Origin matrix window. Matrix
		is a template class with a default type of double but a Matrix of any basic
		data type (including char, byte, short, word, int, and uint but not string)
		can be constructed using the syntax Matrix<type>. The Origin C Matrix class
		is used to access the data in an internal Origin matrix while the Origin C
		MatrixObject class is used for style related control of the matrix. Thus,
		the MatrixObject class has the same relationship with the Matrix class as
		the Column class has with the Dataset class. That is, an internal Origin
		matrix object (accessed by the MatrixObject class) holds a matrix data set
		(accessed by the Matrix class) just as a worksheet column (accessed by the
		Column class) holds a data set (accessed by the Dataset class). The data
		values displayed in the cells of an Origin matrix (referenced by a Matrix
		object) are typically referred to as Z values whose associated X values are
		linearly mapped to the columns of the matrix and whose associated Y values
		are linearly mapped to the rows of the matrix. The Matrix class is derived
		from the matrix and matrixbase classes from which it inherits methods and
		properties. 
	Example:
		// Assumes Matrix1 exists in Origin
		double dMean;
		Matrix matA;             // Declare OC Matrix object
		matA.Attach("Matrix1");  // Attach OC object to internal Origin matrix
		dMean = matA.GetMean();  // Use matrixbase::GetMean function
		printf("Mean of Matrix1: %g\n", dMean ); // Print out mean
*/ 
class Matrix : public matrix
{

public:
	
	/**
			Default constructor for Matrix class.
		Example:
			// Assumes Matrix1 exists in Origin
			double dMean;
			Matrix matA;             // Declare OC Matrix object
			matA.Attach("Matrix1");  // Attach OC object to internal Origin matrix
			dMean = matA.GetMean();  // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean ); // Print out mean
		SeeAlso:
			Matrix::Attach, Matrix::Detach, Matrix::IsValid
	*/
	Matrix(); // Default constructor for Matrix class.
	
	/**
			Constructor for Matrix class that attaches to an internal Origin matrix by name.
		Example:
			// Assumes Matrix1 exists in Origin
			double dMean;
			Matrix matA("Matrix1");  // Declare OC Matrix object and attach it to Matrix1
			dMean = matA.GetMean();  // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean ); // Print out mean
		Parameters:
			lpcszMatrixName=Input name of matrix in Origin to attach to
		SeeAlso:
			Matrix::Attach, Matrix::Detach, Matrix::IsValid
	*/
	Matrix(LPCSTR lpcszMatrixName); // Constructor for Matrix class that attaches to an internal Origin matrix by name.
	
	/**
			Constructor for Matrix class that attaches to an internal Origin matrix by a 
			MatrixLayer object.
		Example:
			// Assumes Matrix1 is active window in Origin
			double dMean;
			MatrixLayer ml;                           // Declare OC MatrixLayer object
			ml = (MatrixLayer) Project.ActiveLayer(); // Get active MatrixLayer from OC Project object 
			Matrix matA(ml);                          // Declare OC Matrix object and attach it to Matrix1
			dMean = matA.GetMean();                   // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean );    // Print out mean
		Parameters:
			mlMatLayer=Input MatrixLayer object
		SeeAlso:
			Matrix::Attach, Matrix::Detach, Matrix::IsValid
	*/
	Matrix(MatrixLayer& mlMatLayer); // Constructor for Matrix class that attaches to an internal Origin matrix by a MatrixLayer object.
 
	/**
			Attach a Matrix object to an internal Origin matrix by name.
		Example:
			// Assumes Matrix1 exists in Origin
			double dMean;
			Matrix matA;             // Declare OC Matrix object
			matA.Attach("Matrix1");  // Attach OC object to internal Origin matrix
			dMean = matA.GetMean();  // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean ); // Print out mean
		Parameters:
			lpcszMatrixName=Input name of matrix in Origin to attach to
		Return:
			Returns TRUE if attachment is successful and FALSE if unsuccessful.
		SeeAlso:
			Matrix::Detach, Matrix::IsValid, Matrix::Matrix
	*/
	BOOL	Attach(LPCSTR lpcszMatrixName); // Attach matrix object to internal Origin matrix
	
	/**
			Attach a Matrix object to an internal Origin matrix by a MatrixLayer object.
		Example:
			// Assumes Matrix1 is active window in Origin
			double dMean;
			Matrix matA;                              // Declare OC Matrix object
			MatrixLayer ml;                           // Declare OC MatrixLayer object
			ml = (MatrixLayer) Project.ActiveLayer(); // Get active MatrixLayer from OC Project object 
			matA.Attach(ml);                          // Attach OC object to Matrix1
			dMean = matA.GetMean();                   // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean );    // Print out mean
		Parameters:
			mlMatLayer=Input MatrixLayer object
		Return:
			Returns TRUE if attachment is successful and FALSE if unsuccessful.
		SeeAlso:
			Matrix::Detach, Matrix::IsValid, Matrix::Matrix
	*/
	BOOL	Attach(MatrixLayer& mlMatLayer); // Attach a Matrix object to an internal Origin matrix by a MatrixLayer object.

	/**
			Detach a Matrix object from an internal Origin matrix.
		Example:
			// Assumes Matrix1 and Matrix2 exist in Origin
			double dMean;
			Matrix matA;             // Declare OC Matrix object
			matA.Attach("Matrix1");  // Attach OC object to internal Origin matrix Matrix1
			dMean = matA.GetMean();  // Use matrixbase::GetMean function
			printf("Mean of Matrix1: %g\n", dMean ); // Print out mean
			matA.Detach();           // Detach OC Object from internal Origin matrix			
			matA.Attach("Matrix2");  // Attach OC object to internal Origin matrix Matrix2
			dMean = matA.GetMean();  // Use matrixbase::GetMean function
			printf("Mean of Matrix2: %g\n", dMean ); // Print out mean
		Return:
			Returns TRUE if detachment is successful and FALSE if unsuccessful.
		SeeAlso:
			Matrix::Attach, Matrix::IsValid, Matrix::Matrix
	*/
	BOOL	Detach(); // Detach a Matrix object from an internal Origin matrix.
	
	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetXMin function gets the X coordinate associated with the left
			most column of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dXMin;
			Matrix matA("Matrix1");   // Declare OC Matrix object and attach it to Matrix1
			dXMin = matA.GetXMin();   // Use GetXMin to get X coordinate of left most column
			printf("X Coordinate of left most column: %g\n", dXMin); // Print out coordinate
		Return:
			Returns the X coordinate associated with the left most column of the matrix.
		SeeAlso:
			Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::SetXMin, Matrix::SetYMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	double	GetXMin() const; // Get the X coordinate associated with the leftmost column of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetXMax function gets the X coordinate associated with the right
			most column of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dXMax;
			Matrix matA("Matrix1");   // Declare OC Matrix object and attach it to Matrix1
			dXMax = matA.GetXMax();   // Use GetXMax to get X coordinate of right most column
			printf("X Coordinate of right most column: %g\n", dXMax); // Print out coordinate
		Return:
			Returns the X coordinate associated with the right most column of the matrix.
		SeeAlso:
			Matrix::GetXMin, Matrix::GetYMin, Matrix::GetYMax, Matrix::SetXMin, Matrix::SetYMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	double	GetXMax() const; // Get the X coordinate associated with the right most column of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetYMin function gets the Y coordinate associated with the first
			row of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dYMin;
			Matrix matA("Matrix1");   // Declare OC Matrix object and attach it to Matrix1
			dYMin = matA.GetYMin();   // Use GetYMin to get Y coordinate of first row
			printf("Y Coordinate of first row: %g\n", dYMin); // Print out coordinate
		Return:
			Returns the Y coordinate associated with the first row of the matrix.
		SeeAlso:
			Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMax, Matrix::SetXMin, Matrix::SetYMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	double	GetYMin() const; // Get the Y coordinate associated with the first row of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetYMax function gets the Y coordinate associated with the last
			row of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dYMax;
			Matrix matA("Matrix1");   // Declare OC Matrix object and attach it to Matrix1
			dYMax = matA.GetYMax();   // Use GetYMax to get Y coordinate of last row
			printf("Y Coordinate of last row: %g\n", dYMax); // Print out coordinate
		Return:
			Returns the Y coordinate associated with the last row of the matrix.
		SeeAlso:
			Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::SetXMin, Matrix::SetYMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	double	GetYMax() const; // Get the Y coordinate associated with the last row of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The SetXMin function sets the X coordinate associated with the left
			most column of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dXMin;
			Matrix matA("Matrix1");    // Declare OC Matrix object and attach it to Matrix1
			dXMin = matA.GetXMin();    // Use GetXMin to get X coordinate of left most column
			printf("X Coordinate of left most column: %g\n", dXMin); // Print out coordinate
			matA.SetXMin( dXMin*10 );  // Use SetXMin to set new X coordinate of left most column
			dXMin = matA.GetXMin();    // Use GetXMin to get new X coordinate of left most column
			printf("New X Coordinate of left most column: %g\n", dXMin); // Print out coordinate
		Parameters:
			dXMin=Input X coordinate of left most column
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			Matrix::SetYMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	BOOL    SetXMin(double dXMin); // Set the X coordinate associated with the left most column of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The SetYMin function sets the Y coordinate associated with the first
			row of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dYMin;
			Matrix matA("Matrix1");    // Declare OC Matrix object and attach it to Matrix1
			dYMin = matA.GetYMin();    // Use GetYMin to get Y coordinate of first row
			printf("Y Coordinate of first row: %g\n", dYMin); // Print out coordinate
			matA.SetYMin( dYMin*10 );  // Use SetYMin to set new Y coordinate of first row
			dYMin = matA.GetYMin();    // Use GetYMin to get new Y coordinate of first row
			printf("New Y Coordinate of first row: %g\n", dYMin); // Print out coordinate
		Parameters:
			dYMin=Input Y coordinate of first row
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			Matrix::SetXMin, Matrix::SetXMax, Matrix::SetYMax, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	BOOL    SetYMin(double dYMin); // Set the Y coordinate associated with the first row of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The SetXMax function sets the X coordinate associated with the right
			most column of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dXMax;
			Matrix matA("Matrix1");    // Declare OC Matrix object and attach it to Matrix1
			dXMax = matA.GetXMax();    // Use GetXMax to get X coordinate of right most column
			printf("X Coordinate of right most column: %g\n", dXMax); // Print out coordinate
			matA.SetXMax( dXMax*10 );  // Use SetXMax to set new X coordinate of right most column
			dXMax = matA.GetXMax();    // Use GetXMax to get new X coordinate of right most column
			printf("New X Coordinate of right most column: %g\n", dXMax); // Print out coordinate
		Parameters:
			dXMax=Input X coordinate of right most column
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			Matrix::SetXMin, Matrix::SetYMin, Matrix::SetYMax, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	BOOL    SetXMax(double dXMax); // Set the X coordinate associated with the right most column of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The SetYMax function sets the Y coordinate associated with the last
			row of the matrix.
		Example:
			// Assumes Matrix1 exists in Origin
			double dYMax;
			Matrix matA("Matrix1");    // Declare OC Matrix object and attach it to Matrix1
			dYMax = matA.GetYMax();    // Use GetYMax to get Y coordinate of last row
			printf("Y Coordinate of last row: %g\n", dYMax); // Print out coordinate
			matA.SetYMax( dYMax*10 );  // Use SetYMax to set new Y coordinate of last row
			dYMax = matA.GetYMax();    // Use GetYMax to get new Y coordinate of last row
			printf("New Y Coordinate of last row: %g\n", dYMax); // Print out coordinate
		Parameters:
			dYMax=Input Y coordinate of last row
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			Matrix::SetXMin, Matrix::SetYMin, Matrix::SetXMax, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::GetXValue, Matrix::GetYValue
	*/
	BOOL    SetYMax(double dYMax); // Set the Y coordinate associated with the last row of the matrix.

	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetXValue function gets the X coordinate associated with the
			specified column of the matrix. An error will result if the matrix coordinate map or column
			number is not valid.
		Example:
			// Assumes Matrix1 exists in Origin and has at least 20 columns 
			double dXValue;
			Matrix matA("Matrix1");       // Declare OC Matrix object and attach it to Matrix1
			dXValue = matA.GetXValue(21); // Use GetXValue to get X coordinate of 20th column
			printf("X Coordinate of 22th column: %g\n", dXValue); // Print out coordinate
		Parameters:
			iColumn=Input column number (0 based offset)
		Return:
			Returns the X coordinate value of the specified column on success and NANUM on failure.
		SeeAlso:
			Matrix::GetYValue, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::SetXMin, Matrix::SetXMax, Matrix::SetYMin, Matrix::SetYMax
	*/
	double	GetXValue(int iColumn); // Get the X coordinate associated with the specified column of the matrix.
	
	/**
			In addition to the values displayed in the cells of an internal Origin matrix (nominally Z
			values), Origin matrices map X coordinate values to the columns and Y coordinate values to
			the rows of the matrix. The GetYValue function gets the Y coordinate associated with the
			specified row of the matrix. An error will result if the matrix coordinate map or row number
			is not valid.
		Example:
			// Assumes Matrix1 exists in Origin and has at least 20 rows 
			double dYValue;
			Matrix matA("Matrix1");       // Declare OC Matrix object and attach it to Matrix1
			dYValue = matA.GetYValue(21); // Use GetYValue to get Y coordinate of 20th row
			printf("Y Coordinate of 22th row: %g\n", dYValue); // Print out coordinate
		Parameters:
			iRow=Input row number (0 based offset)
		Return:
			Returns the Y coordinate value of the specified row on success and NANUM on failure.
		SeeAlso:
			Matrix::GetXValue, Matrix::GetXMin, Matrix::GetXMax, Matrix::GetYMin, Matrix::GetYMax, Matrix::SetXMin, Matrix::SetXMax, Matrix::SetYMin, Matrix::SetYMax
	*/
	double	GetYValue(int iRow); // Get the Y coordinate associated with the specified row of the matrix.

	/**
			Set the value of the cell nearest the specified X and Y coordinates.
		Example:
			// To setup assumptions of function:
			// 1. Click the New Project button on the Standard toolbar in Origin.
			// 2. Click the New Matrix button on the Standard toolbar in Origin.
			// 3. Run function below.
			Matrix mat("Matrix1");
			mat.SetCellValue(2.0,2.0,-999); // Note Cell(5,5)==-999
		Parameters:
			x=The input x coordinate
			y=The input y coordinate	
			dValue=The new cell value
		Return:
		   	Returns TRUE on success and FALSE on failure.
		SeeAlso:
			Matrix::GetCellValue
	*/
	BOOL	SetCellValue(double x, double y, double dValue); // Set the value of the cell nearest the specified X and Y coordinates.
	
	/**
			Get the value of the cell nearest the specified X and Y coordinates.
		Example:
			// To setup function assumptions:
			// 1. Click the New Project button on the Standard toolbar in Origin.
			// 2. Click the New Matrix button on the Standard toolbar in Origin.
			// 3. Select the Matrix:Set Values menu item, set Cell(i,j) = x+y, click OK.
			// 4. Run function below.
			double dValue;
			Matrix mat("Matrix1");
			dValue = mat.GetCellValue(2.0,2.0);
			printf("dValue = %g\n",dValue);
		Parameters:
			x=The input x coordinate
			y=The input y coordinate
		Return:
			Returns the value of the cell nearest the specified X and Y coordinates.
		SeeAlso:
			Matrix::SetCellValue
	*/
	double	GetCellValue(double x, double y); // Get the value of the cell nearest the specified X and Y coordinates.

	/**
			Checks the validity of this Matrix. Matrix objects not attached to an internal
			Origin matrix object are not valid.
		Example:
			// Assumes Matrix1 exists in Origin
			Matrix mat;
			mat.Attach("Matrix1");
			if(mat.IsValid())
				out_str("After attaching mat object is valid!");
			else			
				out_str("After attaching mat object is not valid!");
			mat.Detach();
			if(mat.IsValid())
				out_str("After detaching mat object is valid!");
			else			
				out_str("After detaching mat object is not valid!");
		Return:
			Returns TRUE if this Matrix is valid and FALSE if this Matrix is not valid.
		SeeAlso:
			Matrix::Attach, Matrix::Detach, Matrix::Matrix
	*/
	BOOL	IsValid(); // Checks the validity of this Matrix.

	/**
			Enable (default) or disable the automatic dynamic range (Z range) update when
			Matrix data is changed. Each Matrix keeps track of the range of the data in the
			Matrix. Whenever data in the Matrix is changed the internal cache of the dynamic
			range should be recalculated. Since this recalculation needs to scan the entire
			matrix the operation can be time consuming. There are some situations when the
			Origin C programmer can determine that the data range in the matrix will not be
			changed after an operation on the matrix and thus there is no need to do the
			rescanning.
		Example:
			// Assumes Matrix1 exists in Origin
			Matrix mat1("Matrix1");
			mat1.SetZRangeUpdate(FALSE); // Turn off automatic Z range scanning
			mat1.Transpose();
		Parameters:
			bSet = TRUE (default) performs update when class deconstructor is called, FALSE will disable update
		SeeAlso:
			Matrix::SetZRange, Matrix::GetZRange
	*/
	void SetZRangeUpdate(BOOL bSet = TRUE); // Enable or disable the automatic dynamic range (Z) update when Matrix data is changed.
	
	/**
			Set the dynamic range of this Matrix (Z1, Z2) that is used in data to image conversion.
			This method calls SetZRangeUpdate(FALSE) as there is no need to recalculate the Z range
			from the Matrix data when explicitly setting it.
		Example:
			// Assumes Matrix1 exists in Origin
			Matrix mat1("Matrix1");
			double v1, v2;
			// We will reduce the dynamic range to half of the original
			if( mat1.GetZRange(v1, v2) )
			{
				double range = v2 - v1;
				mat1.SetZRange(v1+range/4, v2-range/4);
			}
		Parameters:
			z1=Lower bound of the matrix data to be mapped in converting to an image, all data below z1 are treated as z1
			z2=Upper bound of the matrix data to be mapped in converting to an image, all data above z2 are treated as z2
			bRound=TRUE to use 256 to round the z1 z2 values, FALSE (default) will use values as they are without rounding
		Return:
 			Returns FALSE if z1 and z2 are not valid for setting the dynamic range otherwise returns TRUE.
		SeeAlso:
			Matrix::SetZRangeUpdate, Matrix::GetZRange
	*/
	BOOL SetZRange(double z1, double z2, BOOL bRound=FALSE); // Set the dynamic range of this Matrix (Z1, Z2) that is used in data to image conversion.

	/**
			Get the dynamic range (Z1, Z2) that is used in data to image conversion.
		Example:
			// Assumes Matrix1 exists in Origin
			Matrix mat1("Matrix1");
			double v1, v2;
			//we will reduce the dynamic range to half of the original
			if(mat1.GetZRange(v1, v2))
			{
				double range = v2-v1;
				mat1.SetZRange(v1+range/4, v2-range/4);
			}
		Parameters:
			z1=Lower bound of the matrix data to be mapped in converting to an image, all data below z1 are treated as z1
			z2=Upper bound of the matrix data to be mapped in converting to an image, all data above z2 are treated as z2
		Return:
	 		Returns FALSE if z range is not available and returns TRUE if Z range is available.
		SeeAlso:
			Matrix::SetZRangeUpdate, Matrix::SetZRange
	*/
	BOOL GetZRange(double& z1, double& z2); // Get the dynamic range (Z1, Z2) that is used in the data to image conversion.

	/**
			Update an Origin C Matrix object when the matrix data in Origin is changed or update
			the matrix in Origin before exiting from the current program scope.
		Example:
			// Both Examples assume Matrix1 window is active in Origin
			// Update Origin C Matrix object from Origin when matrix dimension is changed
			// Also works if data is changed in Origin
			Matrix mat1("Matrix1");
			mat1.SetSize(10,10);
			ASSERT(mat1.GetNumCols()==10);
			LT_execute("Matrix -ps DIM 20 20"); // Origin (via LabTalk) has changed the matrix dimensions
			ASSERT(mat1.GetNumCols()==10);
			mat1.Update(TRUE);                  // Update from Origin
			ASSERT(mat1.GetNumCols()==20);
			
			// This example shows how to update Origin from inside Origin C program before returning
			Matrix mat1("Matrix1");
			mat1 = -999;
			MessageBox(GetWindow(),"OC mat1 object set to -999 but Origin Matrix1 not yet updated, click OK update");
			mat1.Update(FALSE);
			MessageBox(GetWindow(),"Origin Matrix1 has now been updated from OC mat1 object, click OK to set to 0 and update on return");
			mat1 = 0;
		Parameters:
			bFromOrigin=TRUE updates an Origin C Matrix object from an Origin matrix, FALSE updates an Origin matrix 
				from an Origin C Matrix object
			mode=Matrix update mode, used only if bFromOrigin=FALSE. Supported values (enumerated in OC_const.h) are
				REDRAW_NONE				Perform update
				REDRAW_REFRESH			Perform a simple refresh of the data
				REDRAW_REALTIME_SCOPE	Perform real time drawing for the entire range of data.
										To see effect in plots, must set dataplots to animate mode.
		SeeAlso:
			Dataset::Update
	*/
	void	Update(BOOL bFromOrigin, int mode = REDRAW_REFRESH); // Update an Origin C Matrix object from an Origin matrix or vice-versa. 

	/**
			Get the name of the internal Origin matrix attached to this Origin C Matrix object.
		Example:
			MatrixLayer ml = Project.ActiveLayer();
			if(ml)
			{
				Matrix mat1(ml);
				printf("Matrix %s:[%d x %d]\n",mat1.GetName(), mat1.GetNumRows(), mat1.GetNumCols());
			}
			else
				out_str("No active matrix");
		Return:
			Returns the name of an internal Origin Matrix.
	*/
	string  GetName(); // Get the name of an internal Origin Matrix.

	/*				
		  	Get intensity values over the course of a user defined path through this Matrix.
		Example:
			// Assumes Matrix1 matrix exists in Origin, it contains values,
			// and that X and Y coordinates are from at least 1 to 10
			Matrix mat1("Matrix1");
			vector<fpoint> vPoints;
			vector<fpoint> vCalPoints;
			vector<double> vIntensity;
			int ii, nCols;

			vPoints.SetSize(3);
			vPoints[0].x = 1;
			vPoints[0].y = 1;
			vPoints[1].x = 3;
			vPoints[1].y = 4;
			vPoints[2].x = 5;
			vPoints[2].y = 8;

			mat1.ImageLinesProfile(vPoints, vCalPoints, vIntensity, -1, INTERPOLATE_BICUBIC);

			nCols = vCalPoints.GetSize();
			for(ii = 0; ii < nCols; ii++)
    			printf("For (x,y) = (%g,%g) the Intensity = %g\n", vCalPoints[ii].x, vCalPoints[ii].y, vIntensity[ii]);
		Parameters:
			vPathVertices=Input fpoint vector specifying the spatial coordinates (x,y) of the endpoints of the line segments
				making up the user defined path through the Matrix
			vCalPoints=Output fpoint vector containing fpoints used in calculation
			vIntensity=Output vector holding the intensity of the corresponding points in vCalPoints
			iPointNumber=The number of points used to calculate the profile lines (default -1 uses 1 point for each
				pixel that is traversed by path)
			iMethod=Determines interpolation method. An enumerated value from the system header file OC_const.h including the values INTERPOLATE_NEAREST, 
	  			INTERPOLATE_BILINEAR, INTERPOLATE_BICUBIC, INTERPOLATE_2DSPLINE, and INTERPOLATE_VERTICINTERPOL
		Return:
			Returns 0 on success and a non-zero error code on failure.\
		SeeAlso:
			Matrix::GetInterpolatedValue
	*/
	int		ImageLinesProfile(vector<fpoint>& vPathVertices, vector<fpoint>& vCalPoints, vectorbase & vIntensity,
			int iPointNumber = -1, int iMethod = INTERPOLATE_NEAREST); // Get intensity values over the course of a user defined path through this Matrix.

	/**
			Get an interpolated Z value from an internal Origin matrix using the specified interpolation method
			and interpolating in two dimensions for the specified x and y coordinates.
		Example:
			// Assumes Matrix1 with Data exists in Origin
			Matrix matTemp("Matrix1");
			double x = 5.5;
			double y = 4.5;
			double z;
			int nError;
			z = matTemp.GetInterpolatedValue(x, y, INTERPOLATE_BILINEAR, &nError );
		Parameters:
			dX=The X coordinate value
			dY=The Y coordinate value
			nMethod=Determines interpolation method. An enumerated value from the system header file OC_const.h including the values INTERPOLATE_NEAREST, 
	  			INTERPOLATE_BILINEAR, INTERPOLATE_BICUBIC, INTERPOLATE_2DSPLINE, and INTERPOLATE_VERTICINTERPOL
			pnError=A pointer to an error code
		Return:
			Returns the interpolated Z value on success or NANUM and an error code on failure.
			Possible values for *pnError include:
			-1=Complex matrix not supported
			-5=Interpolate method does not exist
			-6=dX or dY value is out of range
			-7=ONAG DLL can not be loaded
			-8=The matrix must be at least 2*2 for bilinear method
			-9=The matrix must be at least 3*3 for bicubic method
			-10=The matrix must be at least 4*4 for 2D spline method
			73=Memory allocation failed
			243=Data is too ill conditioned to compute the B spline
		SeeAlso:
			Matrix::ImageLinesProfile
	*/
	double	  GetInterpolatedValue(double dX, double dY, int nMethod = INTERPOLATE_NEAREST, int* pnError = NULL); // Get an interpolated Z value from an internal Origin matrix.
};

#endif //_MATRIXDATA_H
