//-----------------------------------------------------------------------------------------------------------------------------------------------------------
int IvExtractorEigenDecomposition(Config& config)
{
	String inputWorldFilename = config.getParam("inputWorldFilename");

	// label for selected frames - Only the frames associated with this label, in the label files, will be used
	bool fixedLabelSelectedFrame=true;
	String labelSelectedFrames;
	if (config.existsParam("useIdForSelectedFrame"))    // the ID of each speaker is used as labelSelectedFrame ?
		fixedLabelSelectedFrame=(config.getParam("useIdForSelectedFrame").toBool()==false);  
	if (fixedLabelSelectedFrame)                        // the label is decided by the command line and is unique for the run
		labelSelectedFrames=config.getParam("labelSelectedFrames");
 
try{
	MixtureServer ms(config);
	if (verbose) cout << "(IvExtractor) Approximate i-vector by using Eigen Decomposition"<<endl;
	if (verbose) cout << "(IvExtractor) TotalVariability - Load world model [" << inputWorldFilename<<"]"<<endl;
	MixtureGD& world = ms.loadMixtureGD(inputWorldFilename);      

	//Read the NDX file
	String ndxFilename = config.getParam("targetIdList");

	//Remove the first element of each line which is the model name
	XList tmpFileList(ndxFilename);
	XList fileList;
	for(unsigned long ll=0;ll<tmpFileList.getLineCount();ll++){
		fileList.addLine();
		for(unsigned long i=1;i<tmpFileList.getLine()->getElementCount();i++){
			fileList.getLine(fileList.getLineCount()-1).addElement(tmpFileList.getLine(ll).getElement(i));
		}
	}
	
	//Create and initialise the accumulator
	TVAcc tvAcc(fileList, config);
	Matrix<double> Q(tvAcc.getRankT(),tvAcc.getRankT());
	Matrix<double> D(tvAcc.getNDistrib(),tvAcc.getRankT());

	if(config.existsParam("loadEigenDecompositionParam") && config.getParam("loadEigenDecompositionParam").toBool()){	// Load normalized T matrix and weighted Covariance matrix if pre-computed

		//Load TotalVariability matrix
		String normTFilename = config.getParam("totalVariabilityMatrix") + "_norm";
		tvAcc.loadT(normTFilename, config);

		//Load D and Q matrices
		String dFilename = config.getParam("matrixFilesPath") + config.getParam("totalVariabilityMatrix") + "_EigDec_D" + config.getParam("loadMatrixFilesExtension");
		D.load(dFilename,config);

		String qFilename = config.getParam("matrixFilesPath") + config.getParam("totalVariabilityMatrix") + "_EigDec_Q" + config.getParam("loadMatrixFilesExtension");
		Q.load(qFilename,config);

	}
	else{
		//Load TotalVariability matrix
		tvAcc.loadT(config.getParam("totalVariabilityMatrix"), config);

		// Normalize matrix T
		tvAcc.normTMatrix();

		// Compute weighted co-variance matrix by using UBM weight coefficients
		DoubleSquareMatrix W(tvAcc.getRankT());
		W.setAllValues(0.0);
		tvAcc.getWeightedCov(W,world.getTabWeight(),config);

		// Eigen Decomposition of W to get Q
		Matrix<double> tmpW(W);
		Q.setAllValues(0.0);
		tvAcc.computeEigenProblem(tmpW,Q,tvAcc.getRankT(),config);

		// Compute D matrices (approximation of Tc'Tc matrices)
		D.setAllValues(0.0);
		tvAcc.approximateTcTc(D,Q,config);
	}

	//Load the statistics from files or compute statistics for all segments at once
	if((config.existsParam("loadAccs")) && config.getParam("loadAccs").toBool()){	//load pre-computed statistics
		cout<<"	(IvExtractor) Load Accumulators"<<endl;
		tvAcc.loadN(config);
		tvAcc.loadF_X(config);
	}
	else{															//Compute statistics if they don't exists
		tvAcc.computeAndAccumulateTVStat(config);
		tvAcc.saveAccs(config);
	}

	// Then load the meanEstimate computed by minDiv if required
	DoubleVector meanEstimate = tvAcc.getUbmMeans();
	if(config.existsParam("minDivergence")&& config.getParam("minDivergence").toBool()){
		String minDivName = config.getParam("matrixFilesPath") + config.getParam("meanEstimate") + config.getParam("loadMatrixFilesExtension");
		Matrix<double> tmpMean(minDivName,config);
		for(unsigned long i=0;i<meanEstimate.size();i++){
			meanEstimate[i] = tmpMean(0,i);
		}
	}
	//Update the mean Estimate
	cout<<"	(IvExtractor) Load Mean Estimate"<<endl;
	tvAcc.loadMeanEstimate(meanEstimate);

	//Substract mean from the statistics and normalize co-variance
	tvAcc.normStatistics(config);

	// Estimate I-Vectors
	tvAcc.estimateWEigenDecomposition(D,Q,config);

	cout<<"--------- save IV by File --------"<<endl;
	tvAcc.saveWbyFile(config);
	cout<<"--------- end of process --------"<<endl;


} // fin try
catch (Exception& e) {cout << e.toString().c_str() << endl;}
return 0;
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------
int IvExtractor(Config& config)
{
	String inputWorldFilename = config.getParam("inputWorldFilename");

	// label for selected frames - Only the frames associated with this label, in the label files, will be used
	bool fixedLabelSelectedFrame=true;
	String labelSelectedFrames;
	if (config.existsParam("useIdForSelectedFrame"))    // the ID of each speaker is used as labelSelectedFrame ?
		fixedLabelSelectedFrame=(config.getParam("useIdForSelectedFrame").toBool()==false);  
	if (fixedLabelSelectedFrame)                        // the label is decided by the command line and is unique for the run
		labelSelectedFrames=config.getParam("labelSelectedFrames");
 
try{
	MixtureServer ms(config);
	if (verbose) cout << "(IvExtractor) TotalVariability - Load world model [" << inputWorldFilename<<"]"<<endl;
	MixtureGD& world = ms.loadMixtureGD(inputWorldFilename);      
	
	//Load the statistics from files or compute statistics for all segments at once
	//Read the NDX file
	String ndxFilename = config.getParam("targetIdList");

	//Remove the first element of each line which is the model name
	XList tmpFileList(ndxFilename);
	XList fileList;
	for(unsigned long ll=0;ll<tmpFileList.getLineCount();ll++){
		fileList.addLine();
		for(unsigned long i=1;i<tmpFileList.getLine()->getElementCount();i++){
			fileList.getLine(fileList.getLineCount()-1).addElement(tmpFileList.getLine(ll).getElement(i));
		}
	}

	//Create and initialise the accumulator
	TVAcc tvAcc(fileList, config);

	//Load TotalVariability matrix
	tvAcc.loadT(config.getParam("totalVariabilityMatrix"), config);

	//Statistics
	if((config.existsParam("loadAccs")) && config.getParam("loadAccs").toBool()){	//load pre-computed statistics
		cout<<"	(IvExtractor) Load Accumulators"<<endl;
		tvAcc.loadN(config);
		tvAcc.loadF_X(config);
	}
	else{															//Compute statistics if they don't exists
		tvAcc.computeAndAccumulateTVStat(config);
		tvAcc.saveAccs(config);
	}

	// Then load the meanEstimate computed by minDiv if required
	DoubleVector meanEstimate = tvAcc.getUbmMeans();
	if(config.existsParam("minDivergence")&& config.getParam("minDivergence").toBool()){
		String minDivName = config.getParam("matrixFilesPath") + config.getParam("meanEstimate") + config.getParam("loadMatrixFilesExtension");
		Matrix<double> tmpMean(minDivName,config);
		for(unsigned long i=0;i<meanEstimate.size();i++){
			meanEstimate[i] = tmpMean(0,i);
		}
	}
	//Update the mean Estimate
	cout<<"	(IvExtractor) Load Mean Estimate"<<endl;
	tvAcc.loadMeanEstimate(meanEstimate);

	//Substract mean from the statistics
	tvAcc.substractM(config);

	//Compute vEvT for each session
	tvAcc.estimateTETt(config);

	// Estimate I-Vectors
	tvAcc.estimateW(config);

	cout<<"--------- save IV by File --------"<<endl;
	tvAcc.saveWbyFile(config);
	cout<<"--------- end of process --------"<<endl;

} // fin try
catch (Exception& e) {cout << e.toString().c_str() << endl;}
return 0;
}