void testEucQuadratic(double *M, integer dim, double *X, double *Xopt)
{
	// choose a random seed
	unsigned tt = (unsigned)time(NULL);
	std::cout << "tt:" << tt << std::endl;
	tt = 0;
	init_genrand(tt);

	// Obtain an initial iterate
	EucVariable EucX(dim, 1);
	if (X == nullptr)
	{
		EucX.RandInManifold();
	}
	else
	{
		double *EucXptr = EucX.ObtainWriteEntireData();
		for (integer i = 0; i < dim; i++)
			EucXptr[i] = X[i];
	}

	// Define the manifold
	Euclidean Domain(dim);

	// Define the problem
	EucQuadratic Prob(M, dim);
	Prob.SetDomain(&Domain);

	// test RSD
	std::cout << "********************************Check all line search algorithm in RSD*****************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		RSD *RSDsolver = new RSD(&Prob, &EucX);
		RSDsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RSDsolver->DEBUG = FINALRESULT;
		RSDsolver->CheckParams();
		RSDsolver->Run();
		delete RSDsolver;
	}
	// test RNewton
	std::cout << "********************************Check all line search algorithm in RNewton*************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		RNewton *RNewtonsolver = new RNewton(&Prob, &EucX);
		RNewtonsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RNewtonsolver->DEBUG = FINALRESULT;
		RNewtonsolver->CheckParams();
		RNewtonsolver->Run();
		delete RNewtonsolver;
	}

	// test RCG
	std::cout << "********************************Check all Formulas in RCG*************************************" << std::endl;
	for (integer i = 0; i < RCGMETHODSLENGTH; i++)
	{
		RCG *RCGsolver = new RCG(&Prob, &EucX);
		RCGsolver->RCGmethod = static_cast<RCGmethods> (i);
		RCGsolver->LineSearch_LS = STRONGWOLFE;
		RCGsolver->LS_beta = 0.1;
		RCGsolver->DEBUG = FINALRESULT;
		RCGsolver->CheckParams();
		RCGsolver->Run();
		delete RCGsolver;
	}

	// test RBroydenFamily
	std::cout << "********************************Check all line search algorithm in RBroydenFamily*************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		RBroydenFamily *RBroydenFamilysolver = new RBroydenFamily(&Prob, &EucX);
		RBroydenFamilysolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RBroydenFamilysolver->DEBUG = FINALRESULT;
		RBroydenFamilysolver->CheckParams();
		RBroydenFamilysolver->Run();
		delete RBroydenFamilysolver;
	}

	// test RWRBFGS
	std::cout << "********************************Check all line search algorithm in RWRBFGS*************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		RWRBFGS *RWRBFGSsolver = new RWRBFGS(&Prob, &EucX);
		RWRBFGSsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RWRBFGSsolver->DEBUG = FINALRESULT;
		RWRBFGSsolver->CheckParams();
		RWRBFGSsolver->Run();
		delete RWRBFGSsolver;
	}

	// test RBFGS
	std::cout << "********************************Check all line search algorithm in RBFGS*************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		RBFGS *RBFGSsolver = new RBFGS(&Prob, &EucX);
		RBFGSsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RBFGSsolver->DEBUG = FINALRESULT;
		RBFGSsolver->CheckParams();
		RBFGSsolver->Run();
		delete RBFGSsolver;
	}

	// test LRBFGS
	std::cout << "********************************Check all line search algorithm in LRBFGS*************************************" << std::endl;
	for (integer i = 0; i < LSALGOLENGTH; i++)
	{
		LRBFGS *LRBFGSsolver = new LRBFGS(&Prob, &EucX);
		LRBFGSsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		LRBFGSsolver->DEBUG = FINALRESULT;
		LRBFGSsolver->CheckParams();
		LRBFGSsolver->Run();
		delete LRBFGSsolver;
	}

	std::cout << "********************************Check RTRSD*************************************" << std::endl;
	RTRSD RTRSDsolver(&Prob, &EucX);
	std::cout << std::endl;
	RTRSDsolver.DEBUG = FINALRESULT;
	RTRSDsolver.CheckParams();
	RTRSDsolver.Run();

	std::cout << "********************************Check RTRNewton*************************************" << std::endl;
	RTRNewton RTRNewtonsolver(&Prob, &EucX);
	std::cout << std::endl;
	RTRNewtonsolver.DEBUG = FINALRESULT;
	RTRNewtonsolver.CheckParams();
	RTRNewtonsolver.Run();

	std::cout << "********************************Check RTRSR1*************************************" << std::endl;
	RTRSR1 RTRSR1solver(&Prob, &EucX);
	std::cout << std::endl;
	RTRSR1solver.DEBUG = FINALRESULT;
	RTRSR1solver.CheckParams();
	RTRSR1solver.Run();

	std::cout << "********************************Check LRTRSR1*************************************" << std::endl;
	LRTRSR1 LRTRSR1solver(&Prob, &EucX);
	std::cout << std::endl;
	LRTRSR1solver.DEBUG = FINALRESULT;
	LRTRSR1solver.CheckParams();
	LRTRSR1solver.Run();

	// Check gradient and Hessian
	Prob.CheckGradHessian(&EucX);
	const Variable *xopt = RTRNewtonsolver.GetXopt();
	Prob.CheckGradHessian(xopt);
    
	if (Xopt != nullptr)
	{
		const double *xoptptr = xopt->ObtainReadData();
		for (integer i = 0; i < dim; i++)
			Xopt[i] = xoptptr[i];
	}
};
	double ShapePathStraighten::f(Variable *x) const
	{
		const double *l = x->ObtainReadData();
		const double *O = l + numP;
		const double *m = O + dim * dim;
		//double *q2_new = new double[numP*dim];
        SharedSpace *Shared_q2_new = new SharedSpace(2, numP, dim); //===================
        double *q2_new = Shared_q2_new->ObtainWriteEntireData();   //==================

    
        Apply_Oml(O, m, l, numP, dim, q2_coefs, q2_new);
		//ForDebug::Print("q2q2=============", q2_new, numP, dim);
    
		//******************************compute path_x*********************************
		//initiate
		PSCVariable PSCV(numP, dim, numC);
		PSCV.Generate(q1, q2_new);
		//PSCV.Print();
		PreShapeCurves PSCurves(numP, dim, numC);
		PreShapePathStraighten PreSPSprob(numP, dim, numC);
		PreSPSprob.SetDomain(&PSCurves);
    
		//get updated preshape geodesic
		RSD *RSDsolver = new RSD(&PreSPSprob, &PSCV);
		//RSDsolver->LineSearch_LS = static_cast<LSAlgo> (i);
		RSDsolver->Debug= NOOUTPUT;
		RSDsolver->LineSearch_LS = INPUTFUN;
		RSDsolver->LinesearchInput = &ShapePathStraiLinesearchInput;
		RSDsolver->Max_Iteration = 16;
        RSDsolver->IsPureLSInput = true;
		//RSDsolver->Stop_Criterion = GRAD_F;
	//    RSDsolver->CheckParams();
		RSDsolver->Run();
		//std::cout << "energy:" << RSDsolver->Getfinalfun() << std::endl;//--
		//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% forcout %%%%%%%%%%%%%%%%%%%%%%
    
		//store preshape geodesic to compute distance and eta
		//current preshape geodesic between q1 and q2_new stored in PreGeodesic
		PSCVariable *PreGeodesic = PSCV.ConstructEmpty();
		RSDsolver->GetXopt()->CopyTo(PreGeodesic);
    
		//PreGeodesic->Print();
    
    
		//#############################Compute Distance##############################
		  //######Compute Dalpha######
		const double *GeoPath = PreGeodesic->ObtainReadData();
		//PreGeodesic->Print("kdsjfl;akjsdlfjals;dfjal;dsjfal;dsjfl;asdjfl;asdjfl;asjd");
		double *Dalpha = new double[numP*dim*numC];
		integer stp = numC - 1;
		for (integer t = 0; t < numC; t++)
		{
			if (t != 0) {
				for (integer j = 0; j < dim; j++)
				{
					for (integer i = 0; i < numP; i++)
					{
						Dalpha[t*numP*dim+j*numP+i] = stp*(GeoPath[t*numP*dim+j*numP+i] - GeoPath[(t-1)*numP*dim+j*numP+i]);
					}
				}
			}
			//Project c(tau/numC) into T_alpha(M)
		   if (t == 0)
		   {
			   for (integer j = 0; j < dim; j++)
			   {
					for (integer i = 0; i < numP; i++)
					{
						Dalpha[j*numP+i] = 0.0;
					}
				}
			}
			else
			{
				PreShapePathStraighten::Item_2(GeoPath + t*numP*dim, numP, dim, Dalpha + t*numP*dim);
			}
		}
		//ForDebug::Print("alphaalphalphalphalphalph", Dalpha, numP, dim, numC);
    
		//#######Compute Distance#########
		double intv;
		double *temp = new double[numC];
		double distance;
    
		for (integer i = 0; i < numC; i++)
		{
			temp[i] = PreShapePathStraighten::InnerProd_Q(Dalpha+i*numP*dim, Dalpha+i*numP*dim, numP, dim);
			temp[i] = sqrt(temp[i]);
		}
		intv = 1.0/(numC-1);
		distance = ElasticCurvesRO::Trapz(temp, numC, intv);
		//x->Print("================================");
		//std::cout << "++++++++++++++++++++++++++++++++"<< "distance" << distance<<std::endl;
		//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% forcout %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
		//#############################Compute and store eta##############################
		integer NXD = numP*dim;
		double coeff;
		SharedSpace *SharedEta = new SharedSpace(2, numP, dim);
		double *eta = SharedEta->ObtainWriteEntireData();
		dcopy_(&NXD, const_cast<double *>(Dalpha+(numC-1)*numP*dim), &GLOBAL::IONE, eta, &GLOBAL::IONE);
		coeff = 1.0/std::sqrt(PreShapePathStraighten::InnerProd_Q(Dalpha+(numC-1)*numP*dim, Dalpha+(numC-1)*numP*dim, numP, dim));
		dscal_(&NXD, &coeff, eta, &GLOBAL::IONE);
		//std::cout <<"#########eta#####"<< PreShapePathStraighten::InnerProd_Q(eta, eta, numP, dim)<<std::endl;
    

		x->AddToTempData("eta", SharedEta);
        x->AddToTempData("q2_new", Shared_q2_new);
    
		//############################# Return ##############################
        

		delete RSDsolver;
		//delete [] q2_new;
		delete [] Dalpha;
		delete [] temp;
		return distance;
	}