/*------------------------------------------------------------------------------*
 * File Name: statEx_utils.c 													*
 * Purpose: Purpose: Advanced Statistics Functions							   	*
 * Creation: 11/23/2005, Max													*
 * Copyright (c) OriginLab Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009	*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/
 
#include <Origin.h>
#include <statEx_utils.h>


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
//
//				Repeated Measure ANOVA Functions									
//
/////////////////////////////////////////////////////////////////////////////////

static bool _check_level_equality(const vector<int> &vData)
{
	vector<int> vcount;
	
	if (vData.GetSize() < 2)
		return false;
	int ncount = 1;
	for(int ii= 0; ii < vData.GetSize() - 1; ii++)
	{
		if(vData[ii] == vData[ii+1])
		{	
			ncount++;
			if (ii == vData.GetSize() - 2)
				vcount.Add(ncount);
		}
		else
		{	
			vcount.Add(ncount);
			if (ii == vData.GetSize() - 2)
				vcount.Add(1);
			ncount = 1;
		}

	}
	
	if (vcount.GetSize() < 2)
		return false;
	for(ii= 0; ii < vcount.GetSize() - 1; ii++)
	{
		for(int jj= ii+1; jj < vcount.GetSize() ; jj++)
			if (vcount[jj] != vcount[ii])
				return false;
	}
	
	return true;
}



/**

*/

int  stats_rm_anova_one_way(const MeanCompMethod& nIntervalType,
							const vector &vData,
				  			int nSizeSubject,
							int nGroupSize,
							double dAlpha, 
							int ncntrl,
							RMANOVADescStats* pDescStats, uint nSizeDescStat,
							RMANOVAOneWay *RMANOVATable, 
							MeanCompStats *pMeanCompStats, uint nSizeMeanComp,
							MultiTestTable *RVMultiStats,
							SphericityStats *RVSphericStats,
							EpsilonStats *RVEpsilonStats)
							
{
	// Terminate if error setting
	if (nSizeSubject < 1 || vData.GetSize() < 1)
		return STATS_ERROR_TOO_FEW_DATA_PTS;

	if (nGroupSize < 2)
		return STATS_ERROR_TOO_FEW_GROUPS;
	
	if (dAlpha <= 0 || dAlpha >= 1)
		return STATS_ERROR_INVALID_CONF_LEVEL;

	/*
	if (nIntervalType < 1 || nIntervalType > MEANS_COMPARISON_METHODS_NUMBER)
		return STATS_ERROR_BAD_PARAM;
	*/
	
	if ((ncntrl < 1 || ncntrl > nGroupSize) && nIntervalType.DUNNETT)
		return STATS_ERROR_SETTING;
	
	int nMissing = ocmath_count(NANUM, vData.GetSize(), vData);

	
	if (vData.GetSize() != nSizeSubject * nGroupSize || nMissing > 0)
		return STATS_ERROR_UNBALANCED_DESIGN;

	int nRet = ocStatEx_rm_anova_one_way(&nIntervalType,
										vData, vData.GetSize(),
				  			  			nSizeSubject,
							  			nGroupSize,
								  		dAlpha, 
									 	ncntrl,
									 	pDescStats, nSizeDescStat,
									 	RMANOVATable, 
									 	pMeanCompStats, nSizeMeanComp,
									 	RVMultiStats,
									 	RVSphericStats,
									 	RVEpsilonStats);
	
	return nRet;	
}


/**

*/						
int stats_rm_anova_two_way_one_rv(const MeanCompMethod& nIntervalType,
							int iInteraction,
							const vector &vData,
							const vector<int> &vNonRVData,
							int nSizeSubject,
							int nRVGroupSize,
							int nNonRVGroupSize,
							double dAlpha, 
							int ncntrl1,
							int ncntrl2,
							RMANOVADescStats* pRVDescStats, uint nSizeRVDescStat,
							RMANOVADescStats* pNonRVDescStats, uint nSizeNonRVDescStat,
							RMANOVADescStats* pInterDescStats, uint nSizeInterDescStat,
							RMANOVATwoWayOneRV *RMANOVATable, 
							MeanCompStats *pRVMeanCompStats, uint nSizeRVMeanComp,
							MeanCompStats *pNonRVMeanCompStats, uint nSizeNonRVMeanComp,
							MeanCompStats *pFixNonRVMeanCompStats, uint nSizeFixNonRVMeanComp,
							MeanCompStats *pFixRVMeanCompStats, uint nSizeFixRVMeanComp,
							MultiTestTable *RVMultiStats,
							MultiTestTable *InterMultiStats,
							SphericityStats *RVSphericStats,
							EpsilonStats *RVEpsilonStats)
{
	// Terminate if error setting
	if (iInteraction != 0 && iInteraction != 1)
		return STATS_ERROR_SETTING;
	
	if (nSizeSubject < 1 || vData.GetSize() <1 || vNonRVData.GetSize() <1)
		return STATS_ERROR_TOO_FEW_DATA_PTS;

	if (nRVGroupSize < 2 || nNonRVGroupSize < 2)
		return STATS_ERROR_TOO_FEW_GROUPS;
	
	if (dAlpha <= 0 || dAlpha >= 1)
		return STATS_ERROR_INVALID_CONF_LEVEL;

	/*
	if (nIntervalType < 1 || nIntervalType > MEANS_COMPARISON_METHODS_NUMBER)
		return STATS_ERROR_BAD_PARAM;
	*/
	
	if (nNonRVGroupSize > nSizeSubject)
		return STATS_ERROR_SETTING;

	if (((ncntrl1 < 1 || ncntrl1 > nRVGroupSize) || (ncntrl2 < 1 || ncntrl2 > nNonRVGroupSize)) && nIntervalType.DUNNETT)
		return STATS_ERROR_SETTING;
	
	bool bEqual = _check_level_equality(vNonRVData);
	
	int nMissing = ocmath_count(NANUM, vData.GetSize(), vData);
	
	if (vData.GetSize() != nSizeSubject * nRVGroupSize || nSizeSubject != vNonRVData.GetSize() || nMissing > 0 || bEqual == false)
		return STATS_ERROR_UNBALANCED_DESIGN;
	
	for (int ii = 0; ii< vNonRVData.GetSize(); ii++)
	{
		if (vNonRVData[ii] > nNonRVGroupSize)
			return STATS_ERROR_SETTING;
	}
	
	int nRet = ocStatEx_rm_anova_two_way_one_rv(&nIntervalType,
												iInteraction,
												vData, vData.GetSize(),
												vNonRVData, vNonRVData.GetSize(),
												nSizeSubject,
												nRVGroupSize,
												nNonRVGroupSize,
												dAlpha, 
												ncntrl1,
												ncntrl2,
												pRVDescStats, nSizeRVDescStat,
												pNonRVDescStats, nSizeNonRVDescStat,
												pInterDescStats, nSizeInterDescStat,
												RMANOVATable, 
												pRVMeanCompStats, nSizeRVMeanComp,
												pNonRVMeanCompStats, nSizeNonRVMeanComp,
												pFixNonRVMeanCompStats, nSizeFixNonRVMeanComp,
												pFixRVMeanCompStats, nSizeFixRVMeanComp,
												RVMultiStats,
												InterMultiStats,
												RVSphericStats,
												RVEpsilonStats);
	
	return nRet;	
}


/**

*/
int stats_rm_anova_two_way_two_rv(const MeanCompMethod& nIntervalType,
							int iInteraction,
							const vector &vData,
							int nSizeSubject,
							int nGroupSize,
							int nRV1Levels,
							int nRV2Levels,
							double dAlpha, 
							int ncntrl1,
							int ncntrl2,
							RMANOVADescStats* pRV1DescStats, uint nSizeRV1DescStat,
							RMANOVADescStats* pRV2DescStats, uint nSizeRV2DescStat,
							RMANOVADescStats* pInterDescStats, uint nSizeInterDescStat,
							RMANOVATwoWayTwoRV *RMANOVATable, 
							MeanCompStats *pRV1MeanCompStats, uint nSizeRV1MeanComp,
							MeanCompStats *pRV2MeanCompStats, uint nSizeRV2MeanComp,
							MeanCompStats *pFixRV2MeanCompStats, uint nSizeFixRV2MeanComp,
							MeanCompStats *pFixRV1MeanCompStats, uint nSizeFixRV1MeanComp,
							MultiTestTable *RV1MultiStats,
							MultiTestTable *RV2MultiStats,
							MultiTestTable *InterMultiStats,
							SphericityStats *RV1SphericStats,
							SphericityStats *RV2SphericStats,
							SphericityStats *InterSphericStats,
							EpsilonStats *RV1EpsilonStats,
							EpsilonStats *RV2EpsilonStats,
							EpsilonStats *InterEpsilonStats)
{
	// Terminate if error setting
	if (iInteraction != 0 && iInteraction != 1)
		return STATS_ERROR_SETTING;

	if (nSizeSubject < 1 || vData.GetSize() <1 )
		return STATS_ERROR_TOO_FEW_DATA_PTS;

	if (nGroupSize < 2 || nRV1Levels < 2 || nRV2Levels < 2)
		return STATS_ERROR_TOO_FEW_GROUPS;
	
	if (dAlpha <= 0 || dAlpha >= 1)
		return STATS_ERROR_INVALID_CONF_LEVEL;

	/*
	if (nIntervalType < 1 || nIntervalType > MEANS_COMPARISON_METHODS_NUMBER)
		return STATS_ERROR_BAD_PARAM;
	*/

	if (nGroupSize != nRV1Levels * nRV2Levels || nRV1Levels > nGroupSize || nRV2Levels > nGroupSize)
		return STATS_ERROR_SETTING;

	if (((ncntrl1 < 1 || ncntrl1 > nRV1Levels) || (ncntrl2 < 1 || ncntrl2 > nRV2Levels)) && nIntervalType.DUNNETT)
		return STATS_ERROR_SETTING;
	
	int nMissing = ocmath_count(NANUM, vData.GetSize(), vData);
	
	if (vData.GetSize() != nSizeSubject * nGroupSize || nMissing > 0)
		return STATS_ERROR_UNBALANCED_DESIGN;
	
	int nRet = ocStatEx_rm_anova_two_way_two_rv(&nIntervalType,
												iInteraction,
												vData, vData.GetSize(),
												nSizeSubject,
												nGroupSize,
												nRV1Levels,
												nRV2Levels,
												dAlpha, 
												ncntrl1,
												ncntrl2,
												pRV1DescStats, nSizeRV1DescStat,
												pRV2DescStats, nSizeRV2DescStat,
												pInterDescStats, nSizeInterDescStat,
												RMANOVATable, 
												pRV1MeanCompStats, nSizeRV1MeanComp,
												pRV2MeanCompStats, nSizeRV2MeanComp,
												pFixRV2MeanCompStats, nSizeFixRV2MeanComp,
												pFixRV1MeanCompStats, nSizeFixRV1MeanComp,
												RV1MultiStats,
												RV2MultiStats,
												InterMultiStats,
												RV1SphericStats,
												RV2SphericStats,
												InterSphericStats,
												RV1EpsilonStats,
												RV2EpsilonStats,
												InterEpsilonStats);
	
	return nRet;	
}