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

#ifndef _VECTOR_H
#define _VECTOR_H

#include <common.h>

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

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

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


// SeeAlso vectorbase::GetSize and vectorbase::SetSize methods 
#define  GetUpperIndex	   GetUpperBound
#define  GetLowerIndex	   GetLowerBound
#define  SetUpperIndex	   SetUpperBound
#define	 SetLowerIndex	   SetLowerBound

enum {
	RECT_WINDOW = 0
};

// Please note: Origin C is not yet a fully implmemnted C++ language. Only internal
//	 classes can be declared as C++ classes. User defined C++ classes can only be
//   supported via user supplied DLLs.

/** >Composite Data Types
		The Origin C vectorbase class is an abstract base class used for polymorphic handling
		of vector and Dataset related template class types. Consequently, Origin C objects of
		type vectorbase can not be constructed. Derived classes, such as vector and Dataset,
		inherit vectorbase class methods and should be used instead.    
*/
class vectorbase
{

protected:

	/**# 
			Objects of type vectorbase can not be constructed in Origin C. vectorbase is an
			abstract class used for polymorphic handling of vector and Dataset template
			class types which inherit vectorbase class methods.
	*/
	vectorbase(); // Vectorbase default constructor, for internal use only.
	
public:

	/**
			Dynamically set the size of (number of elements in) a vectorbase derived object.
		Example:
			vector vV;
			vV.SetSize( 361 );
			for( int ii = 0; ii < 361; ii++ )
			{
				vV[ii] = cos(ii*PI/180);
			}
		Parameters:
			nSize=Number of elements in re-sized vectorbase derived object 
			nGrowBy=Currently not used, users should omit from call to pass default -1
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Dataset::SetUpperBound
	*/
	BOOL	SetSize(UINT nSize, int nGrowBy = -1); // Set the size of a vectorbase derived object.

	/**
			Get the size of (number of elements in) a vectorbase derived object.
		Example:
			vector vV;
			vV.SetSize( 99 );
			ASSERT( vV.GetSize() == 99 );
		Return:
			Returns the size of the vectorbase derived object.
		SeeAlso:
			vectorbase::GetUpperBound
	*/
	UINT	GetSize() const; // Get the size of a vectorbase derived object.

	/**
			Get the upper index of the vectorbase range. Index values returned
			are 0 based offsets. SetUpperBound is supported only for Datasets
			(not vectors) while GetUpperBound is supported for all vectorbase
			derived objects. This allows for creation of more general purpose
			functions that can take vectorbase objects as arguments in place
			of Dataset objects. Essentially, the upper bound can be read but
			not written for vectors. Please note that GetUpperBound is always
			GetSize - 1. GetUpperIndex is a synonym for GetUpperBound.  
		Example:
			// Worksheet column Data1_A must exist prior to execution
			int ii, jj, kk;
			Dataset	dsA("Data1_A");
			double dSumA = 0;
			jj = dsA.GetLowerBound();
			kk = dsA.GetUpperBound();
			for(ii = jj; ii <= kk; ii++)
				dSumA += dsA[ii];
			ASSERT( dsA.GetUpperIndex() == dsA.GetUpperBound() );
		Return:
			The upper display index of the vector (0 based offset)
		SeeAlso:
			 Dataset::SetUpperBound, vectorbase::GetSize, vectorbase::SetSize, vectorbase::GetLowerBound, Dataset::SetLowerBound
	*/
	int 	GetUpperBound(); // Get the upper index of the Dataset display range.

	/**
			Get the lower index of the vectorbase range. Index values returned
			are 0 based offsets. SetLowerBound is supported only for Datasets
			(not vectors) while GetLowerBound is supported for all vectorbase
			derived objects. This allows for creation of more general purpose
			functions that can take vectorbase objects as arguments in place
			of Dataset objects. Essentially, the lower bound can be read but
			not written for vectors. If the vectorbase object is not a Dataset
			then GetLowerBound should always return 0. GetLowerIndex is a synonym
			for GetLowerBound.  
		Example:
			// Worksheet column Data1_A must exist prior to execution
			int ii, jj, kk;
			Dataset	dsA("Data1_A");
			double dSumA = 0;
			jj = dsA.GetLowerBound();
			kk = dsA.GetUpperBound();
			for(ii = jj; ii <= kk; ii++)
				dSumA += dsA[ii];
			ASSERT( dsA.GetLowerIndex() == dsA.GetLowerBound() );
		Return:
			The lower display index of the Dataset (0 based offset)
		SeeAlso:
			 Dataset::SetLowerBound, vectorbase::GetSize, vectorbase::SetSize, vectorbase::GetUpperBound, Dataset::SetUpperBound
	*/
	int 	GetLowerBound(); // Get the lower index of the Dataset display range.

	/**
			Sort the elements of the vectorbase derived object. Not yet implemented for complex
			
		Example:
			vector<string> vV;
			vV.SetSize(5);
			vV[0]="-1";
			vV[1]="5";
			vV[2]="Hello";
			vV[3]="";
			vV[4]="GoodeBye";
			vV.Sort();// sort Text
			
			// here is a example to show to sort col(a) and put into col(b)
			Worksheet wks("Data1");
			Column colA(wks, 0);
			vector va(colA); // copy data, skip all missing values on both ends
			va.Sort(); // sort numeric
			Dataset dsB(wks, 1);
			dsB = va;
			
		Parameters:
			wOrder = Default value SORT_ASCENDING sorts in ascending order, SORT_DESCENDING sorts in descending order
			bMissingValuesSmall = Input flag specifies whether missing values are considered to be the smallest
                           or largest possible value
	*/
#if  _OC_VER <= 0x0703
	BOOL Sort(BOOL wOption = SORT_ASCENDING, BOOL bMissingValuesSmall = TRUE);
#endif
	/**
			Sort the elements of the vectorbase derived object and retrive the original indeces. Not yet implemented for complex
		
		Example:
		    vector<uint> vnIndeces;
			vector<double> vdWeight = {0, 0.1, 0.4, 0, 0.2};
			vdWeight[0] = NANUM;
			vdWeight[3] = NANUM;
		    vdWeight.Sort(SORT_ASCENDING, FALSE, vnIndeces);
		    //result vdWeight = 0.1 0.2 0.4 NANUM NANUM
		    //result vnIndeces = 1 4 2 0 3
		    
		Parameters:
			wOrder = Default value SORT_ASCENDING sorts in ascending order, SORT_DESCENDING sorts in descending order
			bMissingValuesSmall = Input flag specifies whether missing values are considered to be the smallest
                           or largest possible value
			vnIndeces = Optional array to retrive the original indeces that corresponds to the sorted values
		SeeAlso:
			Reorder
	*/
#if  _OC_VER > 0x0703
	BOOL Sort(BOOL wOption = SORT_ASCENDING, BOOL bMissingValuesSmall = TRUE, vector<uint>& vnIndeces = NULL);
	
	/**
	  		Rearrange the vector according to the given indeces
		Parameters:
			vnIndeces = 0 offset indeces to reorder vector. The indeces must be all unique and include all of the indeces in current vector 	
		Example: 
			vector<uint> vn = {0,2,1};
		    vector<string> vs1 = {"AA", "BB", "CC"};
		    vs1.Reorder(vn);
		    // result vs1 = AA CC BB
		    
		    // the following code sort one vector based on another
		    vector<uint> vnIndeces;
		    vector<string> vs1 = {"AA", "BB", "CC"};
		    vector<double> vdWeight = {0.1, 0.4, 0.2};
		    vdWeight.Sort(SORT_ASCENDING, TRUE, vnIndeces);
		    vs1.Reorder(vnIndeces);
		    // result vs1 = AA CC BB
		    
	*/
	BOOL Reorder(const vector<uint>& vnIndeces);
#endif //_OC_VER > 0x0703
	
	/**
			Get the differences of a vector.
		Example:
			vector<int>	vv;
			vv.SetSize(4);
			vv[0] = 23;
			vv[1] = 12;
			vv[2] = 7;
			vv[3] = 28;
			
			vector<int> vr;
			BOOL bRet = vv.Difference(vr);
			ASSERT(bRet);
			ASSERT(vr[0] == vv[1] - vv[0]);
			ASSERT(vr[1] == vv[2] - vv[1]);
			ASSERT(vr[2] == vv[3] - vv[2]);
		Parameters:
			vecDiff will have the differences of target vector, 
			The length of vecDiff will be n-1 ,n is the length of target vector.
		Returns:
			Returns TRUE on successful exit and FALSE on error.
	*/
	BOOL	Difference(vectorbase &vecDiff ); 

	/**
			Append data from a vectorbase derived object to this vectorbase derived object.
		Example:
			vector		vV;             // Initialize variables
			Dataset		dsB("Data1_B"); // Dataset Data1_B must exist in Origin
		
			dsB.SetSize(10);            // Initialize dataset
			for(int ii = 0; ii < 10; ii++)
			{
				dsB[ii] = 1000 * ii;
			}
	
			vV.SetSize(5);              // Initalize vector
			for(ii = 0; ii < 5; ii++)
			{
				vV[ii] = 10 * ii;
			}

			dsB.Append(vV);             // Append vector to dataset
		Parameters:
			vV=vector or Dataset to append
		Returns:
			Returns TRUE on successful exit and FALSE on error.
	*/
	BOOL	Append(vectorbase &vv); // Append data to a vectobase derived object.

	/**
			Compute a sum of all the elements in this vector. The argument type must be
			greater than or equal to the underlying base type of the vector.
		Example:
			int ii, nSum;
			vector<short> vShort = {1,2,3,4,5};
			printf("vShort:\n");
			for(ii = 0; ii < vShort.GetSize(); ii++)
				printf("%d\t",vShort[ii]);
			printf("\n\n");
			
			vShort.Sum(nSum);
			printf("Sum of vShort is %d", nSum);
		Parameters:
			nSum=Output sum of all the elements in the vector
		Return:
		 	Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			Data_sum
	*/
	int		Sum(int & nSum);

	/**
			Compute a sum of all the elements in this vector. The argument type must be
			greater than or equal to the underlying base type of the vector.
		Example:
			int ii;
			double dSum;
			vector vDouble = {1.1,2.1,3.1,4.1,5.1};
			printf("vDouble:\n");
			for(ii = 0; ii < vDouble.GetSize(); ii++)
				printf("%g\t",vDouble[ii]);
			printf("\n\n");
			
			vDouble.Sum(dSum);
			printf("Sum of vDouble is %g", dSum);
		Parameters:
			dSum=Output sum of all the elements in the vector
		Return:
		 	Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			Data_sum
	*/
	int		Sum(double & dSum);

	/**
			Compute a sum of all the elements in this vector. The argument type must be
			greater than or equal to the underlying base type of the vector.
		Example:
			int ii;
			complex cxSum;
			vector<complex> vComplex = {1+2i,2-1i,3+4i,4-3i,5+2i};
			printf("vComplex:\n");
			for(ii = 0; ii < vComplex.GetSize(); ii++)
				printf("%g+%gi\t",vComplex[ii].m_re,vComplex[ii].m_im);
			printf("\n\n");
			
			vComplex.Sum(cxSum);
			printf("Sum of vComplex is %g+%gi", cxSum.m_re, cxSum.m_im);
		Parameters:
			cxSum=Output sum of all the elements in the vector
		Return:
		 	Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			Data_sum
	*/
	int		Sum(complex & cxSum);

	/**
			Get min and max values and associated indecies of current vector. For complex, the amplitude will be calculated.
		Example:
			vector<int> vTarget = { 5, 6 ,1, 2, 3, 4 };
			double dbMin, dbMax;
			uint nIndexMin;
			uint nIndexMax;
			uint nCountNonMissingValue = vTarget.GetMinMax(dbMin, dbMax, &nIndexMin, &nIndexMax);
			ASSERT(dbMin == 1.0);
			ASSERT(dbMax == 6.0);
			ASSERT(nIndexMin == 2);
			ASSERT(nIndexMax == 1);
			ASSERT(nCountNonMissingValue == 6);
			// here is another example, which shows how to use this in a worksheet
			void show_wks_min_max(string strWks = "Data1")
			{
				Worksheet wks(strWks);
				
				foreach(Column cc in wks.Columns)
				{
					vector vv(cc, 0, cc.GetNumRows()-1); // copy col data into a vector of double
					double min, max;
					uint imin, imax;
					vv.GetMinMax(min, max, &imin, &imax);
					// show index in LabTalk convention of 1-offset
					printf("Col(%s): max[%d] = %f, min[%d] = %f\n", cc.GetName(), imax+1, max, imin+1, min);
				}
			}

		Return:
			The total number of none-missing values in the vector. For complex, 
			if either of real and imaginary part is missing value, the amplitude will be a missing value.
		SeeAlso:
			None.
	*/
	int		GetMinMax(double& min, double& max, uint* pIndexMin = NULL, uint* pIndexMax = NULL);

	/**
			Compute a frequency count of the elements in a vector binning from dMin
			to dMax with a bin size of dInc. Values that fall on the lower edge of a bin
			are included in that bin and values that fall on the upper edge of a bin are
			included in the next higher bin.
		Example:
			// Data1_A (with data between 0 and 1) and Data1_B must exist
			Dataset dsA("Data1_A"), dsB("Data1_B");
			vector  vA(dsA);
			vector<int> vCounts;
			vA.FrequencyCount(0,1,0.05,vCounts);
			dsB = vCounts;
		Parameters:
			dMin=The minimum value of the range
			dMax=The maximum value of the range
			dInc=The bin increment
			vCounts=The result vector containing frequency counts
			wIncludeOutliers=Flag indicating whether or not to include outliers in 
				first and last bins
					0=Don't include outliers (default)
					1=Include outliers < dMin in first bin
					2=Include outliers >= dMax in last bin
					3=Combination of 1 and 2 above
		Return:
			Returns 0 on success and a non-zero error code on failure:
				1=dInc is zero
				2=dInc is greater than (dMax - dMin)
	*/	
	int     FrequencyCount(double dMin, double dMax, double dInc, vector<int>&  vCounts, int wIncludeOutliers = FAB_NOT_INCLUDE_OUTLIERS); // Compute a frequency count of elements in a vector.

	/**
			Copy the elements of this vector into an internal buffer.
		Example:
			vector<int> vTemp = {1,2,3,4,5};
			vector<byte> vResult;
			vTemp.GetBytes(vResult);
			int iSize = vResult.GetSize();
			ASSERT(iSize == 4 * vTemp.GetSize());
		Parameters:
			vStream=Output vector or internal buffer containing bytes copied from this vector
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			vectorbase::SetBytes
	*/
 	int     GetBytes(vector<byte>& vStream); // Copy the elements of this vector into an internal buffer.

	/**
			Set the elements of this vector from an internal buffer.
		Example:
			vector<int> vTemp1 = {1,2,3,4,5}, vTemp2;
			vector<byte> vResult;
			vTemp1.GetBytes(vResult);
			int iSize = vResult.GetSize();
			ASSERT(iSize == 4 * vTemp1.GetSize());
			vTemp2.SetSize(vTemp1.GetSize());
			vTemp2.SetBytes(vResult);
		Parameters:
			vStream=Input vector or internal buffer containing bytes copied to this vector
		Return:
			Returns 0 on success and a non-zero error code on failure.
		SeeAlso:
			vectorbase::GetBytes
	*/
 	int     SetBytes(vector<byte>& vStream); // Set the elements of this vector from an internal buffer.

	/**
			Assigns a LabTalk vector to an Origin C vector.
		Example:
			vector<string> vsColumns;
			if( vsColumns.GetLabTalkVectorValue("wks.cname"))
			{
				for(int ii = 0; ii < vsColumns.GetSize(); ii++)
				{
					printf("Column (%d) : %s\n", ii, vsColumns[ii]);
				}
			}
			else
				printf("Could not find wks.cname$\n");
		Parameters:
			lpcszLabTalkVector=Input name of LabTalk vector
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			vectorbase::SetLabTalkVectorValue
	*/
	BOOL	GetLabTalkVectorValue(LPCTSTR lpcszLabTalkVector); // Assigns a LabTalk vector to an Origin C vector.

	/**
			Assigns an Origin C vector to a LabTalk vector.
		Example:
			vector<string> vsExt = {"OPJ", "TXT"};
			vector<string> vsExtSave;
			string strExt;
			
			BOOL bSaved = vsExtSave.GetLabTalkVectorValue("FDlog.Type"); //Save the Current settings
			
			if(vsExt.SetLabTalkVectorValue("FDlog.Type"))
			{
				for(int ii = 0; ii < vsExt.GetSize(); ii++)
				{
					strExt = LabTalk.FDlog.Type$(ii+1)$;
					printf("FDLog Type (%d) : %s\n", ii, strExt);
				}
			}
			else
				printf("Could not find FDlog.Type$\n");
			if(bSaved)
				vsExtSave.SetLabTalkVectorValue("FDlog.Type"); //Restore the older settings
		Parameters:
			lpcszLabTalkVector=Input name of LabTalk vector
		Return:
			Returns TRUE on success and FALSE on failure.
		SeeAlso:
			vectorbase::GetLabTalkVectorValue
	*/
	BOOL	SetLabTalkVectorValue(LPCTSTR lpcszLabTalkVector); // Assigns an Origin C vector to a LabTalk vector.


#ifdef	ORIGIN_COM_SUPPORT
	/**
			Append data from an object of type _VARIANT to a vectorbase derived object.
			_VARIANT is a universal type that exists in COM to hold various types of
			data. It is used to set or get the values of properties of COM objects.
			It can represent individual values of int, double, etc., as well as arrays
			and other composite types.
		Parameters:
			var=A COM data object of type _VARIANT
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	*/
	BOOL	Append(_VARIANT& var); // Append a COM object of type _VARIANT to a vector or Dataset.

	/**#
			Assigning a vector or Dataset to a COM object of type _VARIANT generally
			creates a two dimensional array where the second dimension is 1 (vectors
			and Datasets are one dimensional so second dimension of _VARIANT is set to
			1). This is what Excel expects when assigning a _VARIANT to a "Range" object.
			However, some COM objects require one dimensional arrays of type _VARIANT.
			GetDataAsOneDimensionalArray returns a one dimensional array from a vector
			or Dataset. _VARIANT is a universal type that exists in COM to hold various
			types of data. It is used to get the values of properties of COM objects. It
			can represent individual values of int, double, etc., as well as arrays and
			other composite types.
		Example:
			vector<float> v;
			v.SetSize(262);
			for( int ii=0; ii < 262; ii++ )
				v[ii] = sin(ii);
			_VARIANT varYData;
			varYData = v.GetDataAsOneDimensionalArray(); // Put data into one dimensional _VARIANT object
		Parameters:
			lowerBound=The lowest index value in the array (default is 0)
		Returns:
			Returns a one dimensional array of type _VARIANT containg a copy of the data in a vector or Dataset.
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	*/
	_VARIANT	GetDataAsOneDimensionalArray(int lowerBound = 0); // Return a copy of a vector or Dataset as a one dimensional array of type _VARIANT.

	/**
		Remarks:
			Assigning a vector or Dataset to a COM object of type _VARIANT generally
			creates a two dimensional array where the second dimension is 1 (vectors
			and Datasets are one dimensional so second dimension of _VARIANT is set to
			1). This is what Excel expects when assigning a _VARIANT to a "Range" object.
			However, some COM objects require one dimensional arrays of type _VARIANT.
			GetAs1DArray returns a one dimensional array from a vector
			or Dataset.
		Example:
			Dataset aa("data1_a");
			Object CW2DGraph = MyDlg.GetItem(IDC_CWGRAPH1).GetActiveXControl();
			CW2DGraph.PlotY(aa.GetAs1DArray());
			
		Returns:
			Returns a one dimensional array of type _VARIANT containg a copy of the data in a vector
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	*/
	_VARIANT	GetAs1DArray(); // Return a copy of a vector or Dataset as a one dimensional array of type _VARIANT.


#endif //#ifdef	ORIGIN_COM_SUPPORT

	/**
			Get the internal or underlying base data type of a vectorbase derived object.
		Examples:
			vector vDouble;
			vector<char> vChar;
			vector<int> vInt;
			int nType;
			nType = vDouble.GetInternalDataType(); // Return FSI_DOUBLE
			printf( "nType for double = %d\n", nType ); 
			nType = vChar.GetInternalDataType(); // Return FSI_CHAR
			printf( "nType for char = %d\n", nType ); 
			nType = vInt.GetInternalDataType(); // Return FSI_LONG
			printf( "nType for int = %d\n", nType ); 
		Return:
			Returns FSI_DOUBLE, FSI_REAL, FSI_SHORT, FSI_LONG, FSI_CHAR, FSI_TEXT, FSI_MIXED, FSI_BYTE, FSI_USHORT,
			FSI_ULONG, or FSI_COMPLEX which are enumerated in OC_const.h.
	*/	
	int 	GetInternalDataType(); // Get the internal or underlying base data type of a vectorbase derived object.

	// vectorbase::Data CPY 9/21/02 v7.0403 QA70-3015, need Origin 7 SR3 or later
	/**
		Generate data values in a vector. This function is similar to the LabTalk function
		Data(min, max, inc). The vector will be automatically resized and populated with data
		values such that the first element in the vector will be dStartVal and the last element
		in the vector will be most close data to dEndVal. If dIncVal is passed in as zero
		the function will fail. To set all elements in a vector to the same scalar value first
		set the vector size and then make a scalar assignment using the desired value.
	Example:
		vector vData;
		vData.Data(1,10); // Generate 1,2,... 10 
		ASSERT(vData.GetSize() == 10);
	Parameters:
		dStartVal=Input value assigned to the first element in the vector
		dEndVal=Input value generated for the last element in the vector
		dIncVal=Input increment value used to calculate successive values in the vector
	Return:
		Returns TRUE on success and FALSE on Failure.
	*/
	BOOL	Data(double dStartVal, double dEndVal, double dIncVal = 1.0); // Generate data values in a vector.

#if _OC_VER >= 0x0800
	/**#
	Generate integer values in a vector
	Remark:
	The vector will be automatically resized and populated with data values such that the first element in the vector will be nStartVal and the last element in the vector will be greater than or equal to nEndVal. If nIncVal is passed in as zero the function will fail.    Example:
	       vector<int> vData;
	       vData.Data(1,10); // Generate 1,2,... 10 
	       ASSERT(vData.GetSize() == 10);
	   Parameters:
	       nStartVal= [in]value assigned to the first element in the vector
	       nEndVal= [in] value generated for the last element in the vector
	       nIncVal= in] increment value used to calculate successive values in the vector
	Return:
	   Returns TRUE on success and FALSE on Failure.
	*/
	BOOL    Data(int nStartVal, int nEndVal, int nIncVal = 1);
#endif //_OC_VER >= 0x0800
	
#if  _OC_VER > 0x0703
	/**
		fill the vector with pseudorandom values between 0 and 1 from a uniform distribution.
	Parameters:
	  nSize = number of values
	  nSeed = seed of the random sequence. Using a value of 0 will generate a different seuqence each time this function is called, while using the same seed will generate the same sequence
	Return:
	   Returns TRUE on success and FALSE on Failure.
	Remarks:
		This method is similar to the LabTalk Uniform function. If this method is used on an integer vector, then the resulting vecter will be filled with 0s and 1s.
	Example:
		void run_Uniform()
		{
			vector  vv;
			vv.SetSize(20);
			BOOL bRet = vv.Uniform(vv.GetSize());
			for(int ii=0; ii<vv.GetSize(); ii++)
			{
				out_double("",vv[ii]);
			}	
		}
	*/
	BOOL Uniform(int nSize, int nSeed = 0);
	
	/**
		fill the vector with pseudorandom values from a normal distribution with zero mean and unit standard deviation.
	Parameters:
		nSize = number of values
		nSeed = seed of the random sequence. Using a value of 0 will generate a different seuqence each time this function is called, while using the same seed will generate the same sequence
	Return:
		Returns TRUE on success and FALSE on Failure.
	Remarks:
		This method is similar to the LabTalk Normal function. 
		If this method is used on an integer vector, then the resulting vecter will be filled with nearest iintegers from the distribution which has typical values betwen -3 and 3
	Example:
		void run_Normal()
		{
			vector  vv;
			vv.SetSize(20);
			BOOL bRet = vv.Normal(vv.GetSize());
			for(int ii=0; ii<vv.GetSize(); ii++)
			{
				out_double("",vv[ii]);
			}	
		}	
	*/
	BOOL Normal(int nSize, int nSeed = 0);
#endif //_OC_VER > 0x0703

	/**
			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:
			vector vec = {1,2,3,4,5,6,7,8,9};
			vec.Wrap(4);
			==> vec = {5,6,7,8,9,1,2,3,4}
	*/
	BOOL Wrap(int nNum =0); 


	/**
			Get the Real part of a Complex vector. Causes a runtime error if the
			underlying base type of the vector is not Complex.
		Examples:
			vector<complex> vComplex = { 1+2i, 3+4i };
			vector vReal1, vReal2;
			vComplex.GetReal( vReal1 );  // vReal1 = { 1, 3 };

			printf( "vReal1[0]=%g\nvReal1[1]=%g", vReal1[0], vReal1[1] );
			vReal1.GetReal( vReal2 );    // Causes runtime error
		
		Parameters:
			vReal=Output vector containing the Real part of this Complex vector
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			vectorbase::GetImaginary, vectorbase::GetPhase, vectorbase::GetAmplitude, vectorbase::Conjugate, vectorbase::MakeComplex 
	*/
	int	GetReal( vector & vReal ); // Get the Real part of a Complex vector.
	
	/**
			Get the Imaginary part of a Complex vector. Causes a runtime error if
			the underlying base type of the vector is not Complex.
		Examples:
			vector<complex> vComplex = { 1+2i, 3+4i };
			vector vImag1, vImag2;
			vComplex.GetImaginary( vImag1 );      // vImag1 = { 2, 4 };
			printf( "vImag1[0]=%g\nmImag1[1]=%g", vImag1[0], vImag1[1] );
			vImag1.GetImaginary( vImag2 );        // Causes runtime error
		Parameters:
			vImag=Output vector containing the Imaginary part of this Complex vector
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			vectorbase::GetReal, vectorbase::GetPhase, vectorbase::GetAmplitude, vectorbase::Conjugate, vectorbase::MakeComplex
	*/
	int	GetImaginary( vector & vImag ); // Get the Imaginary part of a Complex vector. 
	
	/**
			Get the amplitude(modulus) of the Complex vector. Causes a runtime
			error if the underlying base type of the vector is not Complex.
		Examples:
			vector<complex> vComplex = { 1+2i, 3+4i };
			vector vAmplitude1, vAmplitude2, vReal = { 1, 3 };
			vComplex.GetAmplitude( vAmplitude1 );
			printf( "vAmplitude1[0]=%g\nvAmplitude1[1]=%g", vAmplitude1[0], vAmplitude1[1] );
			vReal.GetAmplitude( vAmplitude2 ); // Causes runtime error
		Parameters:
			vAmplitude=Output vector containing amplitude(modulus) vector for this Complex vector
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			vectorbase::GetReal, vectorbase::GetImaginary, vectorbase::GetPhase, vectorbase::Conjugate, vectorbase::MakeComplex
	*/
	int	GetAmplitude( vector & vAmplitude ); // Get the amplitude(modulus) of the Complex vector.

	/**
			Get the phase angle vector, in radians, of the Complex vector. Causes
			a runtime error if the underlying base type of the vector is not Complex.
		Examples:
			vector<complex> vComplex = { 1+2i, 3+4i };
			vector vPhase1, vPhase2, vReal = { 1, 3 };
			vComplex.GetPhase( vPhase1 );
			printf( "vPhase1[0]=%g\nvPhase1[1]=%g", vPhase1[0], vPhase1[1] );
			vReal.GetPhase( vPhase2 ); // Causes runtime error
		Parameters:
			vPhase=Output vector containing the phase angle vector for this Complex vector
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			vectorbase::GetReal, vectorbase::GetImaginary, vectorbase::GetAmplitude, vectorbase::Conjugate, vectorbase::MakeComplex
	*/
	int	GetPhase( vector & vPhase ); // Get the phase angle vector, in radians, of the Complex vector.
	/**
			Replace this vector with the Conjugate of this vector. A runtime error 
			occurs if the underlying base type of this vector is not double or Complex.
		Example:
			vector<complex> vA(2);
			vA[0] = 1+2i; vA[1] = 3;
			vA.Conjugate();
			for(int ii = 0; ii < 2; ii++)
					printf("%g + %gi, ",vA[ii].m_re, vA[ii].m_im);
				printf("\n");		
		Return:
			Returns 0 on success and -1 on failure which occurs if the vector is empty.	
		SeeAlso:
			vectorbase::GetReal, vectorbase::GetImaginary, vectorbase::GetPhase, vectorbase::GetAmplitude, vectorbase::MakeComplex
	*/
	int		Conjugate(); // Replace this vector with the Conjugate of this vector.

	/**
			Make a Complex vector from two Real vectors (which must have the same
			dimensions).
		Example:
			vector vA(2), vB(2);
			vector<complex> vC(2);

			vA[0] = 1;			vB[0] = -2;
			vA[1] = -3;			vB[1] = 1;

			vC.MakeComplex(vA,vB);

			for(int ii = 0; ii < 2; ii++)
					printf("%g + %gi\n",vC[ii].m_re,vC[ii].m_im);
		Parameters:
			vbReal=The vector containing the Real part
			vbImag=The vector containing the Imaginary part
		Return:
			Returns 0 on success and -1 on failure.
		SeeAlso:
			vectorbase::GetReal, vectorbase::GetImaginary, vectorbase::GetPhase, vectorbase::GetAmplitude, vectorbase::Conjugate
	*/
	int		MakeComplex(vectorbase & vbReal, vectorbase & vbImag); // Make a Complex vector from two Real vectors.

#if  _OC_VER > 0x0703
	/**#
			Get a subset of this vector specified by 0 based element indices.
		Example:
			vector<double> v1, v2;
			v2.SetSize(10);
			for(int ii = 0; ii < 10; ii++ )
				v2[ii] = 0.01*ii;
			v2.GetSubVector(v1, 5, -1); // Copy half part of vector v2 into vector v1
			ASSERT(v1.GetSize()==5);
			ASSERT(is_equal(round(v1[0],2), 0.05));
			ASSERT(is_equal(round(v1[1],2), 0.06));
			ASSERT(is_equal(round(v1[2],2), 0.07));
		Parameters: 
			vbTarget=vectorbase derived object containing returned vectorbase subset
			c1=Begining element index, default is 0 (0 based offset) 
			c2=Ending element index, (inclusive) default -1 is GetSize() -1 (0 based offset) 
		Return:
			Returns 0 on success and -1 on failure.
	*/
	int	GetSubVector(vectorbase& vbTarget, int c1 = 0, int c2 = -1); // -1 means to last vector element index

	/**#
			Set a subset of this vector specified by 0 based element indices. The source and target
			vectors can have different types and different dimensions but the target vector is never
			resized even if the source vector is larger than the target.
		Example:
			vector<double> vec1[3];
			vec1[1].SetSize(3);
			vec1[1][0] = 0.01;
			vec1[1][1] = 0.02;
			vec1[1][2] = 0.03;
			vector<double> vec2;
			vec2.SetSize(3);
			vec2.SetSubVector(vec1[1], 1);
			ASSERT(is_equal(round(vec2[1],2), 0.01));
			ASSERT(is_equal(round(vec2[2],2), 0.02));

			vector<double> vSrc = { 1.1, 2.1};
			vector<int> vDest = { 0, 0, 0, 0 };
			vDest.SetSubVector(vSrc, 0 );
			ASSERT(vDest[0] == 1);
			ASSERT(vDest[1] == 2);
			ASSERT(vDest[2] == 0);
			ASSERT(vDest[3] == 0);

		Parameters: 
			vbSource = vectorbase oject containing the subset to set
			c1 = Begining element index in the target vector, default is 0 (0 based offset) 
		Return:
			Returns 0 on success and -1 on failure.
	*/
	int	SetSubVector(vectorbase& vbSource, int c1 = 0);
	
	/**
			do moving average for vector.
		Parameters:
			nLength: length of average window length, if it is not larger than 0, do nothing.
			nMethod: type of moving average window, now, only support RECT_WINDOW, always set it 
			as RECT_WINDOW now.
		Examples:
			vector vv1 ={1,3,2,6,4,9,2,5,7};
			vector vv2;
			vv2.Average(vv1,3);
			==> vv2=
			  1.3333  2.0000  3.6667  4.0000  6.3333  5.0000  5.3333  4.6667  4.0000
	*/
	void Average(vectorbase &vSource, int nLength, int nMethod = RECT_WINDOW); 
	

	/**#
		Function to find all instances of a value in a vector (can be then used for dataset as well)
	Example:
		vector<double> vec = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };   
		vector<uint> vecIndex;   
		double dLower = 0.3;
		double dUpper = _ONAN; 
		int nPrecision = 5;
		int iBegin = 0;  
		int iEnd = 8;
		vec.Find(vecIndex, dLower, dUpper, nPrecision, iBegin, iEnd);
		ASSERT(vecIndex.GetSize() == 1);
		ASSERT(vecIndex[0] == 2);
		
		dUpper = 0.6;
		vec.Find(vecIndex, dLower, dUpper, nPrecision, iBegin, iEnd);
		ASSERT(vecIndex.GetSize() == 4);
		ASSERT(vecIndex[0] == 2);
		ASSERT(vecIndex[1] == 3);
		ASSERT(vecIndex[2] == 4);
		ASSERT(vecIndex[3] == 5);
		
		iBegin = 4;
		vec.Find(vecIndex, dLower, dUpper, nPrecision, iBegin, iEnd);
		ASSERT(vecIndex.GetSize() == 2);
		ASSERT(vecIndex[0] == 4);
		ASSERT(vecIndex[1] == 5);  
	Parameters: 
		vecIndex = all indices of vecData 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.
		iBegin = the index of vecData from which the search should begin - leave as 0 to start from index 0
		iEnd = the index of vecData up to which the search should be done - leave as -1 to seach to end of vecData
	Return:
		return -1 if no values were found, otherwise return "n" where n is the number of values found.
	*/
	int Find(vector<uint>& vecIndex, double dLower, double dUpper = _ONAN, int nPrecision = 8, int iBegin = 0, int iEnd = -1);
	
	/**
			Remove all missing values from the vectorbase derived object and resize acordingly shifting non-missing
			data values up.  Trim of Curve objects causes both X and Y Datasets to be trimmed.
		Example:
			Dataset ds("Data1_A"); // Containing missing values
			ds.Trim();
		Return:
			Returns true on success and false on failure.
		SeeAlso:
			vectorbase::TrimLeft, vectorbase::TrimRight, vectorbase::GetLowerBound, vector::vector
	*/
	bool Trim();

	/**
			TrimLeft removes elements having the value NANUM from the left end or beginning of the
			vectorbase derived object by advancing the lower index to the first valid numeric value.
			If bShiftLeft is TRUE cells containing NANUM are deleted from the vectorbase object and
			a lower index value of 0 is returned shifting numeric values left. bShiftLeft must be TRUE
			for vectors or this function will have no effect. When bShiftLeft is TRUE TrimLeft of Curve
			objects causes both X and Y Datasets to be trimmed.
		Example:
			// Worksheet columns Data1_A and data1_B must exist prior to execution
			Dataset	dsA("Data1",0);
			dsA.TrimLeft(TRUE);
			Curve crvAxBy("Data1_A","Data1_B");
			crvAxBy.TrimLeft(TRUE);
			LT_execute("doc -uw");
		Parameters:
			bShiftLeft=TRUE will delete cells on the left of (before) the first valid numeric value, FASLE will cause the lower bound
				or index to be adjusted upward but no cells are deleted.
		Return:
			Returns -1 on error, 0 on success, and N > 0 for number of cells deleted.
		SeeAlso:
			vectorbase::Trim, vectorbase::TrimRight, vectorbase::GetLowerBound, vector::vector
	*/
 	int		TrimLeft(BOOL bShiftLeft = FALSE); // TrimLeft removes elements having the value NANUM from the left end of a Dataset.

 	/**
			TrimRight removes elements having the value NANUM from the right end or
			bottom of vectorbase derived objects by retarding the upper index to
			the last valid numeric value. If bDelExtra is set to TRUE cells containing
			NANUM are deleted from the vectorbase object. When bDelExtra is TRUE TrimRight
			of Curve objects causes both X and Y Datasets to be trimmed.
		Example:
			// Worksheet columns Data1_A and data1_B must exist prior to execution
			Dataset	dsA("Data1",0);
			dsA.TrimRight(TRUE);
			Curve crvAxBy("Data1_A","Data1_B");
			crvAxBy.TrimRight(TRUE);
			LT_execute("doc -uw");
		Parameters:
			bDelExtra=TRUE will delete cells on the right of (after) the last valid numeric value, FASLE will cause the upper bound
				or index to be adjusted downward but no cells are deleted.
		Returns:
			Returns -1 on error, 0 on success, and N > 0 for number of cells deleted.
		SeeAlso:
			vectorbase::Trim, vectorbase::TrimLeft, vectorbase::GetUpperBound, vectorbase::GetSize, vector::vector
	*/
 	int		TrimRight(BOOL bDelExtra = FALSE); // TrimRight removes elements having the value NANUM from the right end of a Dataset.
#endif // _OC_VER > 0x0703
	/**
		Removes all elements in the vector. 
	Examples:
		vector<int> vnData = {1,2,3};
		vnData.RemoveAll();
		ASSERT(0 == vnData.GetSize());
	*/
	void RemoveAll();
};

/** >Composite Data Types
		An Origin C vector is a dynamically allocated and sized array that is not
		tied to an internal Origin data set allowing a greater degree of flexibility.
		vector is a template class with a default type of double but a vector of any
		basic data type (including char, byte, short, word, int, uint, string) can
		be constructed using the syntax vector<type>. The vector class is derived from
		the vectorbase class from which it inherits methods and properties. 
	Example:
		int imax = 10;
		vector<double> vX(imax);      // vector of doubles having imax elements
		vector vY(imax);              // vector of doubles by default
		vector<int> vI;               // vector of ints
	
		for(int ii = 0; ii < vX.GetSize(); ii++)
			vX[ii] = rnd();

		vY = 10 * vX;                 // vector arithmetic is supported
		vI = vY;                      // Cast double vector into int vector
	
		ASSERT(vI.GetSize() == imax); // Check that vectors have same size
		for(ii = 0; ii < vI.GetSize(); ii++) // Output cast elements of vectors
			printf("vI[%d]=%d after cast from %f\n",ii,vI[ii],vY[ii]);
*/
class vector : public vectorbase
{

public:

	/**
			Default constructor for vector class.
		Example:
			vector vD;         // vector of doubles
			vector<string> vS; // vector of strings
			vector<int> vI;    // vector of ints
	*/
	vector(); // Default constructor for vector class.
	
	/**
			Constructor to create a vector having size nSize.
		Example:
			vector vD(10);         // vector of 10 doubles
			vector<string> vS(10); // vector of 10 strings
			vector<int> vI(10);    // vector of 10 ints
		Parameters:
			nSize=Size of declared vector
	*/
	vector(UINT nSize); // Constructor to create a vector having size nSize.

	/**
			Constructor to create a vector copy of an Origin Dataset. Missing values may or may
			not be removed.
		Example:
			Dataset dsB("Data1_B");      // Origin data set Data1_B must exist
			dsB.SetSize(5);              // Set sizeof data set to 5          
			dsB[0]=-1;
			dsB[1]=5;
			dsB[2]=NANUM;                // Will be removed
			dsB[3]=NANUM;                // Will be removed
			dsB[4]=23;
			vector vB( dsB, TRUE );      // Copy Dataset dsD to vector vD removing missing values
			ASSERT( vB.GetSize() == 3 ); // Elements dsB[2] and dsB[3] are removed 
		Parameters:
			nSize=Size of declared vector
		SeeAlso:
			Dataset::TrimLeft, Dataset::TrimRight
	*/
	vector(Dataset &ds, BOOL bRemoveMissingValues = FALSE); // Constructor to create a vector copy of an Origin Dataset.
	
#if  _OC_VER > 0x0703
	/**#
			Constructor to create a vector from a Column. The vector is intialized by copying
			the contents of the column between nLowerIndex and nUpperIndex into the vector.
			On exit from the scope where the vector is declared, depending on the value
			of nWriteback used as construction time, the values from the vector are written
			back into the column.
		Example:
			// Have some data in the second column of worksheet "Data1" before running this example.
			int	test_column_writeback()
			{
				Column		col("Data1", 1);
				vector		v(col, 2, 5, WRITEBACK_DELETE_ON_SHRINK | WRITEBACK_INSERT_ON_EXPAND);
				
				// Dump the source range
				int			nSrcLowerIndex, nSrcUpperIndex;
				if (v.GetSourceRange(nSrcLowerIndex, nSrcUpperIndex))
					printf("nSrcLowerIndex = %ld\tnSrcUpperIndex = %ld\n", nSrcLowerIndex, nSrcUpperIndex);
				
				// Modify the vector:
				int			nNewVectorSize = 80;
				v.SetSize(nNewVectorSize);
				for (int ii = 0; ii < nNewVectorSize; ii++)
				{
					v[ii] = 100 * (ii + 1);
				}

				return 0;
			} 
		Parameters:
			cc=source column (it must be initialized properly prior to calling the constructor).
			nLowerIndex=the start index inside the column from which the copying should start;
						if -1, the constructor scans from the beginning of the dataset until it
						finds the first nonmissing value. The value is remembered and can be accessed
						using the method GetSourceRange().
			nUpperIndex=the end index inside the column where the copying should end;
						if -1, the constructor scans from the end of the dataset until it
						finds the first nonmissing value. The value is remembered and can be accessed
						using the method GetSourceRange().
			nWriteback=the combination of values from enumeration:
						enum {
							WRITEBACK_NO = 0,				// no writeback
							WRITEBACK_NO_RESIZE = 0x1,		// writes back the vector without resizing or
															// moving the data inside the column (not that both
															// the vector and the column may have been resized
															// between the construction and the writeback time).
							WRITEBACK_INSERT_ON_EXPAND = 0x2,	// not used if WRITEBACK_NO_RESIZE bit is present;
																// if the vector has increased in size after the
																// construction, on writeback the column will be
																// expanded to accomodate additional values, all of
																// which are going to be inserted after m_nSrcUpperIndex
																// and any data (if) already present in the column,
																// will be pushed to the right.
							WRITEBACK_DELETE_ON_SHRINK = 0x8,	// not used if WRITEBACK_NO_RESIZE bit is present; 
																// if the vector has decreased in size after the
																// construction, on writeback the column will be
																// shrunk for the size change, and any data (if present)
																// that were to the right of m_nSrcUpperIndex 
																// will be pushed to the left.
						};

	*/
	vector(Column& cc, int nLowerIndex = -1, int nUpperIndex = -1, int nWriteback = WRITEBACK_NO);
#endif //#if  _OC_VER > 0x0703



	/**
			Constructor to create a complex vector from two vectors - one containing the
			Real parts the other containing the Imaginary parts. The input vectors must have
			a base type of double and must have the same number of elements.
		Example:
			vector vR = { 1, 2, 3 };
			vector vI = { 4, 5, 6 };
			vector <complex> vC(vR, vI);
		Parameters:
			vR=Input vector of doubles
			vI=Input vector of doubles
		Return:
			Returns a complex vector having the same size as vR on successful exit and
			return an empty complex vector object on failure.
	*/
	vector(vector &vR, vector &vI); // Complex vector constructor.


	/**
		Adds One element at the end of the vector. 
	Parameters:
		element = The element to be added to this vector.
	Return:
		The index of the added element.
	Example:
		void test()
		{
			vector<string> vsExt = {"OPJ", "TXT"};
			vsExt.Add("SPC");

			for(int ii = 0; ii < vsExt.GetSize(); ii++)
			{
				printf("Extesion(%d) : %s\n", ii, vsExt[ii]);
			}
		}
	Remarks:
	SeeAlso:
	*/
	int Add(_TemplType element);
	
	/**
		Sets the vector element at the specified index. 
	Parameters:
		nIndex = A specified index in vector.
		element = The element to be added to this vector.
	Return:
		Always returns TRUE
	Example:
		void test()
		{
			vector<string> vsExt = {"OPJ", "TXT"};
			vsExt.SetAtGrow(0, "SPC");

			for(int ii = 0; ii < vsExt.GetSize(); ii++)
			{
				printf("Extesion(%d) : %s\n", ii, vsExt[ii]);
			}
		}
	Remarks:
	SeeAlso:
	*/
	BOOL SetAtGrow(int nIndex, _TemplType element);

	/**
		Inserts one element, or multiple copies of an element at a specified index in an vector.
		In the process, by incrementing the index, it shifts up the existing element at this index, and it shifts up all the elements above it. 
	Parameters:
		nIndex = A specified index in vector.
		element = The element to be added to this vector.
		nCount = The number of times this element should be inserted (defaults to 1).
	Return:
		Always returns TRUE
	Example:
		void test()
		{
			vector<string> vsExt = {"OPJ", "TXT"};
			vsExt.InsertAt(0, "SPC");

			for(int ii = 0; ii < vsExt.GetSize(); ii++)
			{
				printf("Extesion(%d) : %s\n", ii, vsExt[ii]);
			}
		}
	Remarks:
	SeeAlso:
	*/
	BOOL InsertAt(int nIndex, _TemplType element, int nCount = 1);

	/**
		Removes one or more elements starting at a specified index in an vector. 
		In the process, it shifts down all the elements above the removed element(s).
		It decrements the upper bound of the vector.
	Parameters:
		nIndex = A specified index in vector.
		nCount = The number of elements to remove (defaults to 1).
	Return:
		Always returns TRUE
	Example:
		void test()
		{
			vector<string> vsExt = {"OPJ", "TXT", "SPC"};
			vsExt.RemoveAt(0, 2);

			for(int ii = 0; ii < vsExt.GetSize(); ii++)
			{
				printf("Extesion(%d) : %s\n", ii, vsExt[ii]);
			}
		}
	Remarks:
		If nIndex is out of bound, or if (nIndex + nCount-1) is out of bound, then 
		runtime error will be generated.
		
	SeeAlso:
	*/
	BOOL RemoveAt( int nIndex, int nCount = 1 );


	/**
		Find a specified string in an string vector.
	Parameters:
		lpcsz = the specified string
		nStart = start index, defaults to 0.
		bCaseSensitive = 
	Return:
		Return value will be -1 if lpcsz is not found else zero based index of element position
	Example:
		void test()
		{
			vector<string> vsExt = {"OPJ", "TXT"};
			ASSERT( -1 == vsExt.Find("SPC") );
		}
	Remarks:
	SeeAlso:
	*/
	int Find(_TemplType element, int nStart = 0, bool bCaseSensitive = false);
	
	
#if  _OC_VER > 0x0703
	/**#
		gets the range inside the source  data when the constructor
		vector(Column& cc, int nLowerIndex = -1, int nUpperIndex = -1, int nWriteback = WRITEBACK_NO)
		is used. See that constructor and the accompanying example for more details.
	Parameters:
		nLower=receives the value of the lower index in used the source
		nUpper=receives the value of the upper index in used the source
	Return:
		TRUE if nWriteback was not WRITEBACK_NO when calling the constructor. 
	*/
	bool	GetSourceRange(int &nLower, int &nUpper);
#endif //#if  _OC_VER > 0x0703

};

// For testing files that are also compiled in MFC
#define INTVEC vector<int>
#define REALVEC	vector<double>
	

/** >Composite Data Types
		An Origin C Dataset is a dynamically allocated and sized array that is tied
		to an internal Origin data set. The internal Origin data set can either be
		displayed or not displayed in an Origin worksheet column. Dataset is a
		template class with a default type of double but a Dataset of any basic data
		type (including char, byte, short, word, int, and uint but not string) can be
		constructed using the syntax Dataset<type>. OVector can be used as a synonym
		for Dataset. The Dataset class is derived from the vector and vectorbase classes
		from which it inherits methods and properties.
	Example:
		// Worksheet column Data1_B must exist prior to execution
		Dataset dsB;           // Create Origin C Dataset object not attached to an Origin data set 
		dsB.Attach("Data1_B"); // Attach Origin C Dataset object dsB to Origin data set Data1_B
		dsB.SetSize(5);
		dsB = 100;
*/
class Dataset : public vector
{

public:
	
	/**
			Default constructor to create an Origin C Dataset object that is not
			attached to an internal Origin data set. The Origin C Dataset object
			can be attached to an internal Origin data set at a later time.
		Example:
			// Worksheet column Data1_B must exist prior to execution
			Dataset dsB;           // Create Origin C Dataset object not attached to an Origin data set 
			dsB.Attach("Data1_B"); // Attach Origin C Dataset object dsB to Origin data set Data1_B
			dsB.SetSize(5);
			dsB = 1;
		SeeAlso:
			Dataset::Attach, Dataset::Detach
	*/
	Dataset(); // Default constructor for Dataset class.
	
	/**
			Constructor to create an Origin C Dataset object and attach it to an internal
			Origin data set whose name is passed as an argument.
		Example:
			// Worksheet column Data1_B must exist prior to execution
			Dataset dsB("Data1_B"); // Create an Origin C Dataset object attached to an Origin data set
			dsB.SetSize(5);
			dsB = 2;
		Parameters:
			lpcszDatasetName=Name of internal Origin data set to which Origin C object is attached
		SeeAlso:
			Dataset::Attach, Dataset::Detach
	*/
	Dataset(LPCSTR lpcszDatasetName); // Constructor to create a Dataset from data set name.
	
	/**
			Constructor to create an Origin C Dataset object and attach it to an
			Origin worksheet column. Origin worksheet name and column number in worksheet
			are passed as arguments. Please note Origin C column numbers are 0 based
			offsets while internal Origin column numbers are 1 based offsets.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Dataset dsB("Data1",1); // Create an Origin C Dataset object attached to an Origin data set
			                        //   contained in column 2 of Origin worksheet Data1
			dsB.SetSize(5);
			dsB = 3;
		Parameters:
			lpcszWksName=Name of worksheet in which column resides
			nCol=Origin C column number to attach to (nCol=1 attaches to second column in worksheet) 
		SeeAlso:
			Dataset::Attach, Dataset::Detach
	*/	
	Dataset(LPCSTR lpcszWksName, int nCol); // Constructor to create a Dataset from worksheet name and column number.

	/**
			Dataset copy constructor accepts an Origin C Dataset object as an argument
			and generates a temporary Dataset which is an exact	copy (same size and 
			values as original) of the Dataset. The temporary Dataset is destroyed 
			when program control exits the scope of the temporary Dataset.
		Example:
			void Test()
			{
				Worksheet wks("Data1");
				Dataset dsA(wks,0);
				
				int nSize = 3;
				dsA.SetSize(nSize);
				for(int ii=0; ii<nSize; ii++)
				{
					dsA[ii] = ii+1;
				}
				
				Dataset dsB(dsA); // Generates a temporary dataset of size 3 having values 1,2,3
			}
		Parameters:
			dsOriginal=Origin C Dataset object to copy
	*/
	Dataset(Dataset dsOriginal); // Copy constructor for Dataset class.
	
	/**
			Constructor to create an Origin C Dataset object and attach it to an Origin
			worksheet column. An Origin C worksheet object and worksheet column number
			are passed as arguments. Please note Origin C column numbers are 0 based
			offsets while internal Origin column numbers are 1 based offsets.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Worksheet wksW("Data1"); // Create an Origin C Worksheet object attached to the Origin worksheet Data1
			Dataset dsB(wksW,1);     // Create an Origin C Dataset object attached to an Origin data set
			                         //   contained in column 2 of the Origin worksheet Data1
			dsB.SetSize(5);
			dsB = 4;
		Parameters:
			wks=Origin C worksheet object attached to an Origin worksheet
			nCol=Origin C column number to attach to (nCol=1 attaches to second column in Origin worksheet) 
		SeeAlso:
			Worksheet::Worksheet, Dataset::Attach, Dataset::Detach
	*/		
	Dataset(Worksheet &wks, int nCol); // Constructor to create a Dataset from worksheet object and column number.

	/**
			Constructor to create an Origin C Dataset object from an Origin C Column object.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Column colB("Data1",1); // Create an Origin C Column object attached to the second column
	   	                            //   in the Origin worksheet Data1
			Dataset dsB(colB);      // Create an Origin C Dataset object attached to the data set
   		                            //   contained in column 2 of the Origin worksheet Data1
			dsB.SetSize(5);
			dsB = 5;
		Parameters:
			col=Origin C column object attached to an Origin worksheet column
		SeeAlso:
			Column::Column, Dataset::Attach, Dataset::Detach
		
	*/
	Dataset(Column & col); // Constructor to create a Dataset from a Column object.

	/**
			Attach an Origin C Dataset object to an internal Origin data set whose
			name is passed as an argument. Origin C Dataset objects must be attached
			to internal Origin data sets either by constructor or by the Attach method.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Dataset	ds1;               // Create unattached Dataset object
			if(ds1.Attach("Data1_A"))  // Attach Dataset object to Origin data set Data1_A
			{
				ds1.SetSize(10);
				for(int ii = 0; ii < 10; ii++)
					ds1[ii] = ii;
			}
			if(ds1.Attach("Data1_B")) // Attaching to different dataset detaches from previous dataset 
			{                         //   and attaches to new one
				ds1.SetSize(10);
				for(int ii = 0; ii < 10; ii++)
				ds1[ii] = -ii;
			}
		Parameters:
			lpcszDatasetName=Name of Origin data set to attach to
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Dataset::Dataset, Dataset::Detach
	*/
	BOOL	Attach(LPCSTR lpcszDatasetName); // Attach Dataset object to an Origin data set identified by name.

	/**
			Attach an Origin C Dataset object to an Origin worksheet column.
			Origin worksheet name and column number are passed as arguments. Please
			note Origin C column numbers are 0 based offsets while internal Origin
			column numbers are 1 based offsets. Origin C Dataset objects must be attached
			to internal Origin data sets either by constructor or by the Attach method.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Dataset	ds1;               // Create unattached Dataset object
			if(ds1.Attach("Data1",0))  // Attach Dataset object to first column in Data1 worksheet
			{
				ds1.SetSize(10);
				for(int ii = 0; ii < 10; ii++)
					ds1[ii] = ii;
			}
			if(ds1.Attach("Data1",1)) // Attaching to different dataset detaches from previous dataset 
			{                         //   and attaches to new one
				ds1.SetSize(10);
				for(int ii = 0; ii < 10; ii++)
					ds1[ii] = -ii;
			}
		Parameters:
			lpcszWksName=Name of worksheet in which column resides
			nCol=Origin C column number to attach to (nCol=1 attaches to second column in worksheet)
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Dataset::Dataset, Dataset::Detach
	*/
	BOOL	Attach(LPCSTR lpcszWksName, int nCol); // Attach a Dataset object a worksheet column identified by worksheet name and column number.

	/**
			Attach an Origin C Dataset object to an Origin worksheet column.
			An Origin C Worksheet object and column number are passed as arguments.
			Please note Origin C column numbers are 0 based offsets while internal
			Origin column numbers are 1 based offsets. Origin C Dataset objects must
			be attached to internal Origin data sets either by constructor or by
			the Attach method.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Worksheet wksW("Data1");  // Create Origin C Worksheet object and attach to Origin Data1 worksheet		
			Dataset	ds1;              // Create unattached Dataset object
			ds1.Attach(wksW,0);       // Attach Dataset object to first column in Data1 worksheet
			ds1.Attach(wksW,1);       // Attaching to different data set detaches from previous data set 
			                          //   and attaches to new one
		Parameters:
			wks=Origin C worksheet object attached to an Origin worksheet
			nCol=Origin C column number to attach to (nCol=1 attaches to second column in worksheet)
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Worksheet::Worksheet, Dataset::Dataset, Dataset::Detach
	*/
	BOOL	Attach(Worksheet &wks, int nCol); // Attach a Dataset object to a worksheet column identified by Worksheet object and column number.

	/**
			Attach an Origin C Dataset object to an Origin worksheet column
			identified by an Origin C Column object. Origin C Dataset objects
			must be attached to internal Origin data sets either by constructor
			or by the Attach method.
		Example:
			// Worksheet columns Data1_A and Data1_B must exist prior to execution
			Column colB("Data1",1); // Create an Origin C Column object attached to the second column
	                                //   in the Origin worksheet Data1
 	       Dataset	ds1;            // Create unattached Dataset object
			ds1.Attach(colB);       // Attach Dataset object to first column in Data1 worksheet
		Parameters:
			col=Origin C column object attached to an Origin worksheet column		
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Column::Column, Dataset::Dataset, Dataset::Detach
	*/
	BOOL	Attach(Column & col); // Attach a Dataset object to a worksheet column identified by a Column object.

	/**
			Create a temporary (or permanent) Origin data set and attach the
			Dataset object to it. If Option=1 is specified and data set is not
			destroyed by calling the Dataset::Destroy method the data set will
			remain in Origin after the Origin C function completes execution. 
		Example:
			int ii;
			{
				LT_execute("list s;");
				Dataset	ds0;
				ds0.Create(3);         // Size=3 & Option=0 by default (create and attach to temporary data set)
				for(ii = 0; ii < 3; ii++)
					ds0[ii] = ii;
				LT_execute("list s;"); // Note new ds0 TEMP_ data set
			}
			LT_execute("list s;");     // Out of ds0's scope, note new ds0 TEMP_ data set is destroyed
	
			Dataset	ds1;
			ds1.Create(3,1);           // Size=3 & Option=1 (create and attach to a second data set that is not temporary)
			for(ii = 0; ii < 3; ii++)
				ds1[ii] = ii;
			LT_execute("list s;");     // Note new ds1 TEMP_ data set
			ds1.Destroy();             // Destroy ds1 TEMP_ data set (comment out this line and TEMP_ data set does not get deleted)
			LT_execute("list s;");     // Note new ds1 TEMP_ data set is destroyed (or not if above line is commented out)
		Parameters:
			Size=Size of the data set
			Option=0 (default) causes temporary Origin data set to be automatically deleted when program control exits scope
				of Dataset object, Option=1 causes data set to not be deleted unless user calls Dataset::Destroy method
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Dataset::Destroy, Dataset::Detach, Dataset::Dataset, Dataset::Attach 
	*/
	BOOL	Create(int Size, UINT Option = 0); // Create an internal Origin data set (may or may not be temporary).

	/**
			Delete (destroy) an Origin data set created using the Dataset::Create
			method. For data sets not created by the Dataset::Create method the
			Destroy method functions identically to the Dataset::Detach method.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			int ii;
			Dataset	ds1;
			ds1.Create(3,1);           // Create data set with Size=3 & Option=1 (not a temporary data set)
			for(ii = 0; ii < 3; ii++)
				ds1[ii] = ii;
			LT_execute("list s;");     // Note new ds1 TEMP_ data set
			ds1.Destroy();             // Destroy ds1 TEMP_ data set
			LT_execute("list s;");     // Note new ds1 TEMP_ data set is destroyed
		
			Dataset	ds2("Data1_A");    // Construct and attach to pre-existing Origin data set
			ds2.Destroy();             // Detaches ds2 from Data1_A but does not delete pre-existing data set from Origin
			LT_execute("list s;");     // Note ds2 is an Invalid Object but Data1_A still exists 
		SeeAlso:
			Dataset::Detach, Dataset::Attach, Dataset::Create 
	*/
	void 	Destroy(); // Detach the Origin C Dataset object and Destroy (delete) the internal Origin data set.

	/**
			Detach an Origin C Dataset object from an internal Origin data set. The
			Dataset object can only be attached to one internal Origin data set at
			a time but it may be sequentially detached and re-attached as many times
			as desired.
		Example:
			// Worksheet columns Data1_A and Data1_ B must exist prior to execution
			Dataset	dsD("Data1_A");    // Attach to Origin data set Data1_A
			vector vV(dsD);            // Copy Data1_A data set to vector
			dsD.Detach();              // Explicitly Detach dsD from Data1_A 
			dsD.Attach("Data1_B");     // Now Attach dsD to Data1_B
			dsD = vV;                  // Copy vector to data set Data1_B
			dsD.Detach();              // Detach dsD from Data1_B
		Return:
			Returns TRUE on successful exit and FALSE on error.
		SeeAlso:
			Dataset::Destroy, Dataset::Attach, Dataset::Create
	*/
	BOOL	Detach(); // Detach the Dataset object from an internal Origin data set.

	/**
			Set the text value of a cell in an Origin data set. The Origin data set
			must be of type Text & Numeric.
		Example:	
			string strTextVal;
			// Worksheet column Data1_A must exist prior to execution and must have a column type of Text & Numeric
			Dataset dsTextA("Data1_A");         // Attach to data set
			dsTextA.SetSize(3);
			for(int ii = 0; ii < 3; ii++)       // For rows 0 to 2...
			{
				strTextVal.Format("Row %d",ii); // Format text value
				dsTextA.SetText(ii,strTextVal); // Set text value of row ii
			}
		Parameters:
			nRow=Row number (O based offset) of an Origin data set whose text value is to be set  
			lpcszTextValue=Text value to set
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			Dataset::GetText, Worksheet::SetCell, Worksheet::GetCell, Worksheet::Cell, Worksheet::TCell
	*/
	BOOL	SetText(int nRow, LPCSTR lpcszTextValue); // Set the text value of a cell in an Origin data set of type Text & Numeric.

	/**
			Get the text value of a cell in an Origin data set. The Origin data set must
			be of type Text & Numeric.
		Example:	
			string strTextVal;
			// Worksheet columns Data1_A and Data1_B must exist prior to execution and must have a column type of Text & Numeric
			LT_execute("Data1_A[1]$=Row 0;");   // Use LabTalk to initialize text values
			LT_execute("Data1_A[2]$=Row 1;");   // LabTalk row numbers use 1 based offset
			LT_execute("Data1_A[3]$=Row 2;");

			Dataset dsTextA("Data1_A");
			dsTextA.SetSize(3);
			Dataset dsTextB("Data1_B");
			dsTextB.SetSize(3);
			for(int ii = 0; ii < 3; ii++)       // Origin C row numbers use 0 based offset      
			{
				dsTextA.GetText(ii,strTextVal); // Get text value in column A
				dsTextB.SetText(ii,strTextVal); // Set text value in column B
			}
		Parameters:
			nRow=Row number (O based offset) of an Origin data set whose text value is returned
			strTextVal=Returned text value 
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			Dataset::SetText, Worksheet::GetCell, Worksheet::SetCell, Worksheet::Cell, Worksheet::TCell
	*/
	BOOL	GetText(int nRow, string& strTextVal); // Get the text value of a cell in an Origin data set of type Text & Numeric.

	/**
			Get the contents (from row nRow1 to nRow2) of a Text Dataset and copy the elements into a 
			StringArray.
		Example:
			// This test function assumes a Data1 worksheet with columns A, B, and C
			// Column A should have some number of text entries
			StringArray sa1, sa2, sa3;
			BOOL bRet;
			Dataset ds1("Data1_A");
			Dataset ds2("Data1_B");
			Dataset ds3("Data1_C");
			bRet = ds1.GetStringArray(sa1, 2, 5);
			bRet = ds1.GetStringArray(sa2);
			bRet = ds2.PutStringArray(sa1, 3);
			bRet = ds3.PutStringArray(sa2);
		Parameters:
			as=Output StringArray
			nRow1=Input starting row number, default 0
			nRow2=Input ending row number, default -1 means to upper bound of Dataset
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			Dataset::PutStringArray
	*/
	BOOL GetStringArray(vector<string>& as, int nRow1=0, int nRow2=-1); // Copy the contents of a Text Dataset into a StringArray.

	/**
			Put (copy) the contents of a StringArray to a Text Dataset starting in row nRow1
			of the destination Dataset.
		Example:
			// This test function assumes a Data1 worksheet with columns A, B, and C
			// Column A should have some number of text entries
			StringArray sa1, sa2, sa3;
			BOOL bRet;
			Dataset ds1("Data1_A");
			Dataset ds2("Data1_B");
			Dataset ds3("Data1_C");
			bRet = ds1.GetStringArray(sa1, 2, 5);
			bRet = ds1.GetStringArray(sa2);
			bRet = ds2.PutStringArray(sa2, 3);
			bRet = ds3.PutStringArray(sa2);
		Parameters:
			as=Input StringArray to copy
			nRow1=Input starting row number of destination Dataset
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			Dataset::GetStringArray
	*/
	BOOL PutStringArray(vector<string>& as, int nRow1=0); // Put (copy) the contents of a StringArray to a Text Dataset.

	/**
			Set the upper display index of the Dataset range. Index values are 0 based
			offsets so use SetUpperBound(-1) to dispaly no rows. SetUpperBound is supported
			only for Datasets (not vectors) while GetUpperBound is supported for all
			vectorbase derived objects. This allows for creation of more general purpose
			functions that can take vectorbase objects as arguments in place of Dataset
			objects. Essentially, the upper bound can be read but not written for vectors.
			SetUpperIndex is a synonym for SetUpperBound. 
		Example:
			// Worksheet column Data1_A must exist prior to execution
			Dataset	dsA("Data1_A");
			dsA.SetSize(10);
			for(int ii = 0; ii < 10; ii++)
				dsA[ii] = ii;

			dsA.SetLowerBound(2);
			dsA.SetUpperBound(7);
			BasicStats bsStatVal;
			Data_sum(&dsA, &bsStatVal);
			ASSERT( bsStatVal.min == 2 );
			ASSERT( bsStatVal.max == 7 );
	
			dsA.SetLowerBound(0);
			dsA.SetUpperBound(9);
			Data_sum(&dsA, &bsStatVal);
			ASSERT( bsStatVal.min == 0 );
			ASSERT( bsStatVal.max == 9 );
		Parameters:
			nUpper=New upper display index of the Dataset
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			 vectorbase::GetUpperBound, vectorbase::GetSize, vectorbase::SetSize, vectorbase::GetLowerBound, Dataset::SetLowerBound
	*/
	BOOL 	SetUpperBound(int nUpper); // Set the upper display index of the Dataset.

		/**
			Set the lower display index of the Dataset range. Index values are 0 based
			offsets. SetLowerBound is supported only for Datasets (not vectors) while
			GetLowerBound is supported for all vectorbase derived objects. This allows
			for creation of more general purpose functions that can take vectorbase
			objects as arguments in place of Dataset objects. Essentially, the lower
			bound can be read but not written for vectors. SetLowerIndex is a synonym
			for SetLowerBound.  
		Example:
			// Worksheet column Data1_A must exist prior to execution
			Dataset	dsA("Data1_A");
			dsA.SetSize(10);
			for(int ii = 0; ii < 10; ii++)
				dsA[ii] = ii;

			dsA.SetLowerBound(2);
			dsA.SetUpperBound(7);
			BasicStats bsStatVal;
			Data_sum(&dsA, &bsStatVal);
			ASSERT( bsStatVal.min == 2 );
			ASSERT( bsStatVal.max == 7 );
	
			dsA.SetLowerBound(0);
			dsA.SetUpperBound(9);
			Data_sum(&dsA, &bsStatVal);
			ASSERT( bsStatVal.min == 0 );
			ASSERT( bsStatVal.max == 9 );
		Parameters:
			nLower=New lower display index of the Dataset
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			 vectorbase::GetLowerBound, vectorbase::GetSize, vectorbase::SetSize, vectorbase::GetUpperBound, Dataset::SetUpperBound
	*/
	BOOL 	SetLowerBound(int nLower); // Set the lower display index of the Dataset.

	/**
			Get the name of an internal Origin data set.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			string strName;
			Dataset	dsA("Data1_A");
			dsA.GetName(strName);
			out_str("Data set name is " + strName);
		Parameters:
			strName=Returned name of an internal Origin data set 
		Return:
			Returns TRUE on successful exit and FALSE on failure. Also returns the name of an internal Origin data set.
	*/
	BOOL	GetName(string& strName); // Get the name of an internal Origin data set.

	/**
			Get the name of an internal Origin data set.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			string strName;
			Dataset dsA("Data1_A");
			strName = dsA.GetName();
			out_str("Data set name is " + strName);
		Return:
			Returns the name of an internal Origin data set.
	*/
	string  GetName(); // Get the name of an internal Origin data set.

	/**
			Checks the validity of an Origin C Dataset object. Dataset objects
			are valid when they are successfully attached to an internal Origin
			data set.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			Dataset dsA;                          // Dataset is not yet attached and is not valid
			if(dsA.IsValid())
				out_str("Dataset is valid!");
			else
				out_str("Dataset is not valid!");
			dsA.Attach("Data1_A");                // Dataset is now attached and is valid
			if(dsA.IsValid())
				out_str("Dataset is valid!");
			else
				out_str("Dataset is not valid!");
		Return:
			Returns TRUE if Dataset object is valid and FALSE if not.
		SeeAlso:
			Dataset::Attach, Dataset::Detach
	*/
	BOOL	IsValid(); // Checks the validity of an Origin C Dataset object.
	
	/**
			Update an Origin C Dataset object from an Origin data set or update
			an Origin data set from an Origin C Dataset object. The number of
			elements and memory allocated are primarily affected by this method.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			void test_update_OC_when_Origin_changed()
			{
				Dataset	dsA("Data1_A");
				dsA.SetSize(10);
				dsA=1;
				LT_execute("set Data1_A -e 20;Data1_A=2;"); // Note Dataset size is not updated but Dataset values change in Local Variables windows of Debug mode 
				dsA.Update(TRUE); // Note Dataset dsA size is now updated in Local Variables windows of Debug mode
				ASSERT(dsA.GetSize()==20);
			}
			
			// Assumes Data1 worksheet with column B
			// This example shows how to update Origin from inside Origin C program before it returns
			void test_update_Origin_when_OC_data_changed()
			{
				Dataset aa("Data1_b");
				// in case column is empty
				if(aa.GetSize()<1)
				{
					aa.SetSize(10);
					aa=0;
				}
				
				aa[0]+= 1;
				aa.Update(FALSE, REDRAW_REFRESH);
				MessageBox(GetWindow(),"Data1_b increment 1, click OK to increment again");
				aa[0]+=1;
			}
			
			// Demonstrate the usage of REDRAW_REALTIME_SCOPE and REDRAW_REALTIME_WKS
			// Assumes:
			//    1) Data1_A is filled with row numbers
			//    2) Data1_A(X) vs. B(Y) is plotted as line plot
			//    3) The line plot is set to animate mode so that the effect is fully visualized
			//       (set plot active and then execute LabTalk script command "set %C -an 1")
			
			void test_realtime_update_Origin_fromOC(int imax = 20)
			{
				Dataset aa("Data1_b");
				int	nMaxRows = 10;
				if(aa.GetSize()<nMaxRows)
				{
					aa.SetSize(nMaxRows);
					aa=0;
				}
				
				int ic = 0;//current cell
			
				for(int ii = 0; ii < imax; ii++)
				{
					for(int jj = 0; jj < nMaxRows; jj++)
						aa[jj] = 1;
					
					aa[ic++] = 2;
					if(ic >= nMaxRows)
						ic = 0;
					//aa.Update(FALSE, REDRAW_REALTIME_WKS);
					aa.Update(FALSE, REDRAW_REALTIME_SCOPE);
					LT_execute("sec -w 0.1;");// hard wait 
				}
			}
		Parameters:
			bFromOrigin=TRUE updates the Origin C Dataset object from the Origin data set, FALSE updates the Origin dataset
				from an Origin C Dataset object.
			mode=Dataset update mode, used only if bFromOrigin=FALSE. Supported values are
		mode=Dataset update mode, allowed values are
			REDRAW_NONE				do update
			REDRAW_REALTIME_WKS		similar to REDRAW_REALTIME_SCOPE, but redraw the entire worksheet	
			REDRAW_REFRESH			do a simple refresh of the data
			REDRAW_REALTIME_SCOPE	this is used to do realtime drawing for the entire range of data. To see effect in plots, must set dataplots to animate mode
		SeeAlso:
			Dataset::Append
	*/
	void	Update(BOOL bFromOrigin, int mode = -1); // Update an Origin C Dataset object from an Origin data set or vice-versa. 

#ifdef _POST_ORIGIN7_
	/**#
	*/
	BOOL	Append(vectorbase& v, int iMode);
#else
	/**
			Append data from a vector or Dataset object to this Origin C Dataset
			object and update the Origin data set from this Origin C Dataset object.
		Example:
			// Assume Data1 worksheet and with A(X) vs. B(Y) plotted in graph window
			// Can test by typing "rt_add 10" into Script window with the graph active
			void rt_add(int npts)
			{
				static int nn = 1;
	
				Worksheet wks("data1");

				Dataset aa(wks,0);
				Dataset bb(wks,1);

				vector a(npts);
				vector b(npts);

				for(int ii = 0; ii < npts; ii++)
				{
					a[ii] = nn++;
					b[ii] = rnd();
				}

				aa.Append(a, REDRAW_REALTIME);
				bb.Append(b, REDRAW_REALTIME);
				return;
			}
		Parameters:
			v=vector or Dataset to append
			iMode=Dataset update mode, allowed values are
				REDRAW_NONE				do update
				REDRAW_REALTIME			graph realtime drawing, only the new added data will be drawn		
				REDRAW_REALTIME_WKS		similar to REDRAW_REALTIME_SCOPE, but redraw the entire worksheet	
				REDRAW_REFRESH			do a simple refresh of the data
				REDRAW_REALTIME_SCOPE	this is used to do realtime drawing for the entire range of data. To see effect in plots, must set dataplots to animate mode
		Return:
			Returns TRUE on successful exit and FALSE on failure.
		SeeAlso:
			vectorbase::Append, Dataset::Update
	*/
	BOOL	Append(vector& v, int iMode = REDRAW_NONE); // Append data from a vector or Dataset object to this Origin C Dataset object.
#endif //!_POST_ORIGIN7_

#if  !(_OC_VER > 0x0703)
 	/**
			TrimLeft removes elements having the value NANUM from the left end or
			beginning of the Dataset by advancing the lower index to the first
			valid numeric value. If bShiftLeft is TRUE cells containing NANUM
			are deleted from the Dataset and a lower index value of 0 is returned
			shifting numeric values left to the beginning of the Dataset. When bShiftLeft 
			is TRUE TrimLeft of Curve objects causes both X and Y Datasets to be trimmed.
		Example:
			// Worksheet columns Data1_A and data1_B must exist prior to execution
			Dataset	dsA("Data1",0);
			dsA.TrimLeft(TRUE);
			Curve crvAxBy("Data1_A","Data1_B");
			crvAxBy.TrimLeft(TRUE);
			LT_execute("doc -uw");
		Parameters:
			bShiftLeft=TRUE will delete cells on the left of (before) the first valid numeric value, FASLE will cause the lower bound
				or index to be adjusted upward but no cells are deleted.
		Returns:
			Returns -1 on error, 0 on success, and N > 0 for number of cells deleted.
		SeeAlso:
			Dataset::TrimRight, vectorbase::GetLowerBound, vector::vector
	*/
 	int		TrimLeft(BOOL bShiftLeft = FALSE); // TrimLeft removes elements having the value NANUM from the left end of a Dataset.

 	/**
			TrimRight removes elements having the value NANUM from the right end or
			bottom of the Dataset by retarding the upper index to the last valid numeric
			value. If bDelExtra is set to TRUE cells containing NANUM are deleted from
			the Dataset. When bDelExtra is TRUE TrimRight of Curve objects causes both
			X and Y Datasets to be trimmed.
		Example:
			// Worksheet columns Data1_A and data1_B must exist prior to execution
			Dataset	dsA("Data1",0);
			dsA.TrimRight(TRUE);
			Curve crvAxBy("Data1_A","Data1_B");
			crvAxBy.TrimRight(TRUE);
			LT_execute("doc -uw");
		Parameters:
			bDelExtra=TRUE will delete cells on the right of (after) the last valid numeric value, FASLE will cause the upper bound
				or index to be adjusted downward but no cells are deleted.
		Returns:
			Returns -1 on error, 0 on success, and N > 0 for number of cells deleted.
		SeeAlso:
			Dataset::TrimLeft, vectorbase::GetUpperBound, vectorbase::GetSize, vector::vector
	*/
 	int		TrimRight(BOOL bDelExtra = FALSE); // TrimRight removes elements having the value NANUM from the right end of a Dataset.
#endif  //!(_OC_VER > 0x0703)
};

// OVector is a synonym for Dataset
#define  OVector Dataset

/** >Composite Data Types
		An Origin C CategoricalMap is a dynamically allocated and sized array of text
		values that is not tied to an internal Origin data set. A CategoricalMap
		contains a set of unique and alpha-numerically sorted text values which are
		typically referenced by the elements of an associated object of type
		CategoricalData. The CategoricalMap class contains additional class methods
		and is not derived from the vector<string> class so an object of type
		CategoricalMap is not technically equivalent to an object of type vector<string>
		but the data elements of each are functionally equivalent and the types can
		be explicitly cast.
	Example:
		// Worksheet column Data1_A must exist prior to execution
		StringArray vMyCatMap;
		CategoricalData cdMyCatData("Data1_A");
		CategoricalMap cmMyCatMap;
		cmMyCatMap = cdMyCatData.Map;
		vMyCatMap = (StringArray) cmMyCatMap; // Requires explicit cast
*/
class CategoricalMap 
{
	
public:

	/**
			Default constructor to create an Origin C CategoricalMap object.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			CategoricalMap cmMyCatMap;
			cmMyCatMap = cdMyCatData.Map;
			vMyCatMap = (StringArray) cmMyCatMap; // Requires explicit cast
		SeeAlso:
			CategoricalData::CategoricalData
	*/
	CategoricalMap();
	
 	/**
			Copy constructor to create a CategoricalMap from another CategoricalMap.	
		Example:
			// Worksheet column Data1_A must exist prior to execution
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			CategoricalMap cmMyCatMap(cdMyCatData.Map);
			vMyCatMap = (StringArray) cmMyCatMap; // Requires explicit cast
		Parameters:
			cmMap=CategoricalMap object that is copied
		SeeAlso:
			CategoricalData::CategoricalData
	*/
	CategoricalMap(CategoricalMap& cmMap);
	
	/**
			Get the CategoricalMap type. Origin currently supports Ordinal maps in which items are sorted
			(ordered) alphanumerically.
		Example:
			// Worksheet column Data1_A must exist prior to execution
			int iMapType;
			CategoricalData cdMyCatData("Data1_A");
			iMapType = cdMyCatData.Map.GetMapType();
		Returns:
			The CategoricalMap type code (current possible value CMT_ORDINAL=2).
	*/
	int		GetMapType();

	/**#
			Currently not supported.
	*/
	BOOL	SetAt(LPCSTR lpcszCategory, int iValue = 0);

	/**
			Sort this CategoricalMap in ascending order.
		Example:
			// Worksheet column Data1_A must exist and contain data prior to execution
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			vMyCatMap = (StringArray) cdMyCatData.Map; // CategoricalMap is sorted in ascending order by default
			cdMyCatData.Map.ArrangeZA();               // Sort CategoricalMap in descending order
			vMyCatMap = (StringArray) cdMyCatData.Map;
			cdMyCatData.Map.ArrangeAZ();               // Sort CategoricalMap in ascending order
			vMyCatMap = (StringArray) cdMyCatData.Map;
		SeeAlso:
			CategoricalMap::ArrangeZA
	*/
	void	ArrangeAZ(); // Sort this CategoricalMap in ascending order.

	/**
			Sort this CategoricalMap in descending order.
		Example:
			// Worksheet column Data1_A must exist and contain data prior to execution
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			vMyCatMap = (StringArray) cdMyCatData.Map; // CategoricalMap is sorted in ascending order by default
			cdMyCatData.Map.ArrangeZA();               // Sort CategoricalMap in descending order
			vMyCatMap = (StringArray) cdMyCatData.Map;
			cdMyCatData.Map.ArrangeAZ();               // Sort CategoricalMap in ascending order
			vMyCatMap = (StringArray) cdMyCatData.Map;
		SeeAlso:
			CategoricalMap::ArrangeAZ
	*/
	void	ArrangeZA(); // Sort this CategoricalMap in descending order.

	/**	
			Look up a category (text value) in this CategoricalMap and return its index (1 based offset). If the
			CategoricalMap has an associated CategoricalData data set then all text data values in the CategoricalData
			data set equal to the specified category are mapped to the category's index value. For the sample data below
			the text value "ddd" is mapped to the index 5.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
			qqq
			777
			aaa
			ddd
		Example:
			// Worksheet column Data1_A must exist and contain Sample Data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			vMyCatMap = (StringArray) cdMyCatData.Map;
			int index = cdMyCatData.Map.LookUp("ddd");
			string strVal = cdMyCatData.Map.ReverseLookUp(5);
		Parameters:
			lpcszCategory=Input category to look up
		Return:
			Returns the index (1 based offset) of the category in this CategoricalMap if the category is
			found and returns -1 if it is not found.
		SeeAlso:
			CategoricalMap::ReverseLookUp
	*/
	int		LookUp(LPCSTR lpcszCategory); // Look up a category in this CategoricalMap and return its index.

	/**	 
			Reverse look up an index (1 based offset) in this CategoricalMap and return its category (or text value).
			If the CategoricalMap has an associated CategoricalData data set the mapped index values in the CategoricalData
			data set refer to the text values in this CategoricalMap. For the sample data below the index 5 refers to
			the text value "ddd".
		Sample Data:
			aaa
			bbb
			ddd
			ccc
			qqq
			777
			aaa
			ddd
		Example:
			// Worksheet column Data1_A must exist and contain Sample Data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			vMyCatMap = (StringArray) cdMyCatData.Map;
			int index = cdMyCatData.Map.LookUp("ddd");
			string strVal = cdMyCatData.Map.ReverseLookUp(5);
		Parameters:
			iVal=Input index value to reverse look up
		Return:
			Returns the category or text value in this CategoricalMap referred to by the index if found
			and returns an empty string if it is not found.
		SeeAlso:
			CategoricalMap::LookUp
	*/
	string	ReverseLookUp(int iVal); // Reverse look up an index in this CategoricalMap and return its category.
};

/** >Composite Data Types
		An Origin C CategoricalData data set is a dynamically allocated and sized
		array of integers that is tied to an internal Origin data set of type Text.
		A CategoricalData data set maps the text values in the data to categories
		referenced by an index (1 based offset). The text value to index map is
		stored in the CategoricalMap data member. Origin currently supports Ordinal
		maps in which items are sorted (ordered) alphanumerically. If a non-Text
		worksheet column in Origin is attached to it will be converted to type Text.
		When non-Text columns are converted to Text only displayed digits are
		converted thus precision may be lost if all digits are not displayed
		in the worksheet. When non-Text columns contain numeric data attaching
		a CategoricalData data set prompts with a novice dialog box asking the user
		whether or not to proceed. If the user selects "No" (do not proceed) the
		conversion to text does not occur and the resulting CategoricalData object
		is invalid. The CategoricalData class is derived from the Dataset, vector,
		and vectorbase classes from which it inherits methods and properties.
	Example:
		// Worksheet column Data1_A must exist prior to execution
		StringArray vMyCatMap;
		CategoricalData cdMyCatData("Data1_A");
		CategoricalMap cmMyCatMap;
		cmMyCatMap = cdMyCatData.Map;
		vMyCatMap = (StringArray) cmMyCatMap; // Requires explicit cast
*/
class CategoricalData : public Dataset<int>
{

public:
	
	/**	
			Default constructor to create a CategoricalData object.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
		Example:
			// Worksheet column Data1_A must exist and contain the sample data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData;
			cdMyCatData.Attach("Data1_A",CMT_ORDINAL);
			vMyCatMap = (StringArray) cdMyCatData.Map; // Requires explicit cast
		SeeAlso:
			CategoricalData::Attach
	*/
	CategoricalData(); // Default constructor to create a CategoricalData object.

	/**	
			Constructor to create a CategoricalData object and attach it to an internal Origin data
			set by name.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
		Example:
			// Worksheet column Data1_A must exist and contain the sample data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1_A");
			vMyCatMap = (StringArray) cdMyCatData.Map; // Requires explicit cast
		Parameters:
			lpcszDatasetName=Input name of internal Origin data set
			wType=Input type of CategoricalMap (only default CMT_ORDINAL is supported)
		SeeAlso:
			CategoricalData::Attach
	*/
	CategoricalData(LPCSTR lpcszDatasetName, UINT wType = CMT_ORDINAL); // Constructor to create a CategoricalData object by data set name.

 	/**
		Constructor to create a CategoricalData object and attach it to an internal Origin data
		set by worksheet name and column number.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
		Example:
			// Worksheet column Data1_A must exist and contain the sample data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData("Data1",0,CMT_ORDINAL);
			vMyCatMap = (StringArray) cdMyCatData.Map; // Requires explicit cast
		Parameters:
			lpcszWksName=Input name of internal Origin worksheet
			wColumnNumber=Input column number in worksheet
			wType=Input type of CategoricalMap (only CMT_ORDINAL is supported)
		SeeAlso:
			CategoricalData::Attach
	*/
	CategoricalData(LPCSTR lpcszWksName, UINT wColumnNumber, UINT wType); // Constructor to create a CategoricalData object by worksheet name and column number.

	/**
		Attach a CategoricalData object to an internal Origin data set by name.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
		Example:
			// Worksheet column Data1_A must exist and contain the sample data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData;
			cdMyCatData.Attach("Data1_A",CMT_ORDINAL);
			vMyCatMap = (StringArray) cdMyCatData.Map; // Requires explicit cast
		Parameters:
			lpcszDatasetName=Input name of internal Origin data set
			wType=Input type of CategoricalMap (only CMT_ORDINAL is supported)
		SeeAlso:
			CategoricalData::CategoricalData
	*/
	BOOL Attach(LPCSTR lpcszDatasetName, UINT wType); // Attach a CategoricalData object to an internal Origin data set

 	/**
		Attach a CategoricalData object to an internal Origin data set by worksheet name and 
		column number.
		Sample Data:
			aaa
			bbb
			ddd
			ccc
		Example:
			// Worksheet column Data1_A must exist and contain the sample data
			StringArray vMyCatMap;
			CategoricalData cdMyCatData;
			cdMyCatData.Attach("Data1",0,CMT_ORDINAL);
			vMyCatMap = (StringArray) cdMyCatData.Map; // Requires explicit cast
		Parameters:
			lpcszWksName=Input name of internal Origin worksheet
			wColumnNumber=Input column number in worksheet
			wType=Input type of CategoricalMap (only CMT_ORDINAL is supported)
		SeeAlso:
			CategoricalData::Attach
	*/
	BOOL Attach(LPCSTR lpcszWksName, UINT wColumnNumber, UINT wType); // Attach a CategoricalData object to an internal Origin data set by worksheet name and column number.

	/**
			The text value to index map for this CategoricalData data set. See the CategoricalMap
			class for more details.
	*/
	CategoricalMap Map;

	/**
			Sort an input vector into columns in a matrix by this CategoricalData data set. Each value in
			the input vector is sorted into the column of the matrix having the 1 based column number
			equal to its paired index value in this CategoricalData data set. The input vector and this 
			CategoricalData data set must have the same number of elements. The matrix will be dynamically
			sized having the same number of columns as there are unique index values in the CategoricalData
			data set and having as many rows as are necessary to hold the largest group of sorted values. An
			Output vector gives the number of grouped values in each column. This method is currently
			implemented only for input vectors having an underlying base type of double.
	 	Example:
			// Assumes worksheet Data1 and matrix Matrix1 exist in Origin
			// Data1_A and Data1_B should have following data
			// Data1_A = {Tic, Tic, Tac, Toe, Tic, Toe, Tac}
			// Data1_B = {1,2,3,4,5,6,7};
			CategoricalData cdMyData("Data1_A");
			Dataset dsIn("Data1_B");
			Matrix mOut("Matrix1");
			vector<int> vCounts;
			int ii;
			StringArray vMyMap;
			cdMyData.Group( dsIn, mOut, vCounts );
			vMyMap = (StringArray) cdMyData.Map;
			for( ii = 0; ii < vCounts.GetSize(); ii++ )
				printf("Column %d ('%s' group) has %d values\n", ii+1, vMyMap[ii], vCounts[ii] );	
		Parameters:
			vIn=The input data to be sorted into groups by this CategoricalData set
			mOut=The output matrix sorted into groups
			vColumnSize=Vector containing the number of data points in each group (column of the matrix)
		Return:
			Returns 0 on success and a non-zero error code on failure.
	*/
	int Group( vector& vIn, matrix& mOut, vector<int>& vColumnSize ); // Sort an input vector into columns in a matrix by this CategoricalData set.
};


#endif //_VECTOR_H
