// @(#)root/quadp:$Id$ // Author: Eddy Offermann May 2004 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ /************************************************************************* * Parts of this file are copied from the OOQP distribution and * * are subject to the following license: * * * * COPYRIGHT 2001 UNIVERSITY OF CHICAGO * * * * The copyright holder hereby grants you royalty-free rights to use, * * reproduce, prepare derivative works, and to redistribute this software* * to others, provided that any changes are clearly documented. This * * software was authored by: * * * * E. MICHAEL GERTZ gertz@mcs.anl.gov * * Mathematics and Computer Science Division * * Argonne National Laboratory * * 9700 S. Cass Avenue * * Argonne, IL 60439-4844 * * * * STEPHEN J. WRIGHT swright@cs.wisc.edu * * Computer Sciences Department * * University of Wisconsin * * 1210 West Dayton Street * * Madison, WI 53706 FAX: (608)262-9777 * * * * Any questions or comments may be directed to one of the authors. * * * * ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES OF * * ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, AND * * OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A CONTRACT * * WITH THE DEPARTMENT OF ENERGY. * *************************************************************************/ /////////////////////////////////////////////////////////////////////////// // // // Class containing the variables for the general QP formulation // // // /////////////////////////////////////////////////////////////////////////// #include "Riostream.h" #include "TQpVar.h" #include "TMatrixD.h" ClassImp(TQpVar) //______________________________________________________________________________ TQpVar::TQpVar() { // Default constructor fNx = 0; fMy = 0; fMz = 0; fNxup = 0; fNxlo = 0; fMcup = 0; fMclo = 0; fNComplementaryVariables = 0; } //______________________________________________________________________________ TQpVar::TQpVar(TVectorD &x_in,TVectorD &s_in,TVectorD &y_in,TVectorD &z_in, TVectorD &v_in,TVectorD &gamma_in,TVectorD &w_in,TVectorD &phi_in, TVectorD &t_in,TVectorD &lambda_in,TVectorD &u_in,TVectorD &pi_in, TVectorD &ixlow_in,TVectorD &ixupp_in,TVectorD &iclow_in,TVectorD &icupp_in) { // Constructor if (x_in .GetNrows() > 0) fX. Use(x_in .GetNrows(),x_in .GetMatrixArray()); if (s_in .GetNrows() > 0) fS. Use(s_in .GetNrows(),s_in .GetMatrixArray()); if (y_in .GetNrows() > 0) fY. Use(y_in .GetNrows(),y_in .GetMatrixArray()); if (z_in .GetNrows() > 0) fZ. Use(z_in .GetNrows(),z_in .GetMatrixArray()); if (v_in .GetNrows() > 0) fV. Use(v_in .GetNrows(),v_in .GetMatrixArray()); if (phi_in .GetNrows() > 0) fPhi. Use(phi_in .GetNrows(),phi_in .GetMatrixArray()); if (w_in .GetNrows() > 0) fW. Use(w_in .GetNrows(),w_in .GetMatrixArray()); if (gamma_in .GetNrows() > 0) fGamma. Use(gamma_in .GetNrows(),gamma_in .GetMatrixArray()); if (t_in .GetNrows() > 0) fT. Use(t_in .GetNrows(),t_in .GetMatrixArray()); if (lambda_in.GetNrows() > 0) fLambda. Use(lambda_in.GetNrows(),lambda_in.GetMatrixArray()); if (u_in .GetNrows() > 0) fU. Use(u_in .GetNrows(),u_in .GetMatrixArray()); if (pi_in .GetNrows() > 0) fPi. Use(pi_in .GetNrows(),pi_in .GetMatrixArray()); if (ixlow_in .GetNrows() > 0) fXloIndex.Use(ixlow_in .GetNrows(),ixlow_in .GetMatrixArray()); if (ixupp_in .GetNrows() > 0) fXupIndex.Use(ixupp_in .GetNrows(),ixupp_in .GetMatrixArray()); if (iclow_in .GetNrows() > 0) fCloIndex.Use(iclow_in .GetNrows(),iclow_in .GetMatrixArray()); if (icupp_in .GetNrows() > 0) fCupIndex.Use(icupp_in .GetNrows(),icupp_in .GetMatrixArray()); fNx = fX.GetNrows(); fMy = fY.GetNrows(); fMz = fZ.GetNrows(); R__ASSERT(fNx == fXloIndex.GetNrows() || 0 == fXloIndex.GetNrows()); R__ASSERT(fNx == fXloIndex.GetNrows() || 0 == fXloIndex.GetNrows()); R__ASSERT(fMz == fCloIndex.GetNrows() || 0 == fCloIndex.GetNrows()); R__ASSERT(fMz == fCupIndex.GetNrows() || 0 == fCupIndex.GetNrows()); fNxlo = fXloIndex.NonZeros(); fNxup = fXupIndex.NonZeros(); fMclo = fCloIndex.NonZeros(); fMcup = fCupIndex.NonZeros(); fNComplementaryVariables = fMclo+fMcup+fNxlo+fNxup; R__ASSERT(fMz == fS.GetNrows()); R__ASSERT(fNx == fV .GetNrows() || (0 == fV .GetNrows() && fNxlo == 0)); R__ASSERT(fNx == fGamma .GetNrows() || (0 == fGamma .GetNrows() && fNxlo == 0)); R__ASSERT(fNx == fW .GetNrows() || (0 == fW .GetNrows() && fNxup == 0)); R__ASSERT(fNx == fPhi .GetNrows() || (0 == fPhi .GetNrows() && fNxup == 0)); R__ASSERT(fMz == fT .GetNrows() || (0 == fT .GetNrows() && fMclo == 0)); R__ASSERT(fMz == fLambda.GetNrows() || (0 == fLambda.GetNrows() && fMclo == 0)); R__ASSERT(fMz == fU .GetNrows() || (0 == fU .GetNrows() && fMcup == 0)); R__ASSERT(fMz == fPi .GetNrows() || (0 == fPi .GetNrows() && fMcup == 0)); } //______________________________________________________________________________ TQpVar::TQpVar(Int_t nx,Int_t my,Int_t mz,TVectorD &ixlow,TVectorD &ixupp, TVectorD &iclow,TVectorD &icupp) { // Constructor R__ASSERT(nx == ixlow.GetNrows() || 0 == ixlow.GetNrows()); R__ASSERT(nx == ixlow.GetNrows() || 0 == ixlow.GetNrows()); R__ASSERT(mz == iclow.GetNrows() || 0 == iclow.GetNrows()); R__ASSERT(mz == icupp.GetNrows() || 0 == icupp.GetNrows()); fNxlo = ixlow.NonZeros(); fNxup = ixupp.NonZeros(); fMclo = iclow.NonZeros(); fMcup = icupp.NonZeros(); if (ixlow.GetNrows() > 0) fXloIndex.Use(ixlow.GetNrows(),ixlow.GetMatrixArray()); if (ixupp.GetNrows() > 0) fXupIndex.Use(ixupp.GetNrows(),ixupp.GetMatrixArray()); if (iclow.GetNrows() > 0) fCloIndex.Use(iclow.GetNrows(),iclow.GetMatrixArray()); if (icupp.GetNrows() > 0) fCupIndex.Use(icupp.GetNrows(),icupp.GetMatrixArray()); fNx = nx; fMy = my; fMz = mz; if (fMclo > 0) { fT.ResizeTo(fMz); fLambda.ResizeTo(fMz); } if (fMcup > 0) { fU.ResizeTo(fMz); fPi.ResizeTo(fMz); } if (fNxlo > 0) { fV.ResizeTo(fNx); fGamma.ResizeTo(fNx); } if (fNxup > 0) { fW.ResizeTo(fNx); fPhi.ResizeTo(fNx); } fS.ResizeTo(fMz); fX.ResizeTo(fNx); fY.ResizeTo(fMy); fZ.ResizeTo(fMz); fNComplementaryVariables = fMclo+fMcup+fNxlo+fNxup; } //______________________________________________________________________________ TQpVar::TQpVar(const TQpVar &another) : TObject(another) { // Copy constructor *this = another; } //______________________________________________________________________________ Double_t TQpVar::GetMu() { // compute complementarity gap, obtained by taking the inner product of the // complementary vectors and dividing by the total number of components // computes mu = (t'lambda +u'pi + v'gamma + w'phi)/(mclow+mcupp+nxlow+nxupp) Double_t mu = 0.0; if (fNComplementaryVariables > 0 ) { if (fMclo > 0) mu += fT*fLambda; if (fMcup > 0) mu += fU*fPi; if (fNxlo > 0) mu += fV*fGamma; if (fNxup > 0) mu += fW*fPhi; mu /= fNComplementaryVariables; } return mu; } //______________________________________________________________________________ Double_t TQpVar::MuStep(TQpVar *step,Double_t alpha) { // Compute the complementarity gap resulting from a step of length "alpha" along // direction "step" Double_t mu = 0.0; if (fNComplementaryVariables > 0) { if (fMclo > 0) mu += (fT+alpha*step->fT)*(fLambda+alpha*step->fLambda); if (fMcup > 0) mu += (fU+alpha*step->fU)*(fPi+alpha*step->fPi); if (fNxlo > 0) mu += (fV+alpha*step->fV)*(fGamma+alpha*step->fGamma); if (fNxup > 0) mu += (fW+alpha*step->fW)*(fPhi+alpha*step->fPhi); mu /= fNComplementaryVariables; } return mu; } //______________________________________________________________________________ void TQpVar::Saxpy(TQpVar *b,Double_t alpha) { // Perform a "saxpy" operation on all data vectors : x += alpha*y Add(fX,alpha,b->fX); Add(fY,alpha,b->fY); Add(fZ,alpha,b->fZ); Add(fS,alpha,b->fS); if (fMclo > 0) { R__ASSERT((b->fT) .MatchesNonZeroPattern(fCloIndex) && (b->fLambda).MatchesNonZeroPattern(fCloIndex)); Add(fT ,alpha,b->fT); Add(fLambda,alpha,b->fLambda); } if (fMcup > 0) { R__ASSERT((b->fU) .MatchesNonZeroPattern(fCupIndex) && (b->fPi).MatchesNonZeroPattern(fCupIndex)); Add(fU ,alpha,b->fU); Add(fPi,alpha,b->fPi); } if (fNxlo > 0) { R__ASSERT((b->fV) .MatchesNonZeroPattern(fXloIndex) && (b->fGamma).MatchesNonZeroPattern(fXloIndex)); Add(fV ,alpha,b->fV); Add(fGamma,alpha,b->fGamma); } if (fNxup > 0) { R__ASSERT((b->fW) .MatchesNonZeroPattern(fXupIndex) && (b->fPhi).MatchesNonZeroPattern(fXupIndex)); Add(fW ,alpha,b->fW); Add(fPhi,alpha,b->fPhi); } } //______________________________________________________________________________ void TQpVar::Negate() { // Perform a "negate" operation on all data vectors : x = -x fS *= -1.; fX *= -1.; fY *= -1.; fZ *= -1.; if (fMclo > 0) { fT *= -1.; fLambda *= -1.; } if (fMcup > 0) { fU *= -1.; fPi *= -1.; } if (fNxlo > 0) { fV *= -1.; fGamma *= -1.; } if (fNxup > 0) { fW *= -1.; fPhi *= -1.; } } //______________________________________________________________________________ Double_t TQpVar::StepBound(TQpVar *b) { // calculate the largest alpha in (0,1] such that the/ nonnegative variables stay // nonnegative in the given search direction. In the general QP problem formulation // this is the largest value of alpha such that // (t,u,v,w,lambda,pi,phi,gamma) + alpha * (b->t,b->u,b->v,b->w,b->lambda,b->pi, // b->phi,b->gamma) >= 0. Double_t maxStep = 1.0; if (fMclo > 0 ) { R__ASSERT(fT .SomePositive(fCloIndex)); R__ASSERT(fLambda.SomePositive(fCloIndex)); maxStep = this->StepBound(fT, b->fT, maxStep); maxStep = this->StepBound(fLambda,b->fLambda,maxStep); } if (fMcup > 0 ) { R__ASSERT(fU .SomePositive(fCupIndex)); R__ASSERT(fPi.SomePositive(fCupIndex)); maxStep = this->StepBound(fU, b->fU, maxStep); maxStep = this->StepBound(fPi,b->fPi,maxStep); } if (fNxlo > 0 ) { R__ASSERT(fV .SomePositive(fXloIndex)); R__ASSERT(fGamma.SomePositive(fXloIndex)); maxStep = this->StepBound(fV, b->fV, maxStep); maxStep = this->StepBound(fGamma,b->fGamma,maxStep); } if (fNxup > 0 ) { R__ASSERT(fW .SomePositive(fXupIndex)); R__ASSERT(fPhi.SomePositive(fXupIndex)); maxStep = this->StepBound(fW, b->fW, maxStep); maxStep = this->StepBound(fPhi,b->fPhi,maxStep); } return maxStep; } //______________________________________________________________________________ Double_t TQpVar::StepBound(TVectorD &v,TVectorD &dir,Double_t maxStep) { // Find the maximum stepsize of v in direction dir // before violating the nonnegativity constraints if (!AreCompatible(v,dir)) { ::Error("StepBound(TVectorD &,TVectorD &,Double_t)","vector's not compatible"); return kFALSE; } const Int_t n = v.GetNrows(); const Double_t * const pD = dir.GetMatrixArray(); const Double_t * const pV = v.GetMatrixArray(); Double_t bound = maxStep; for (Int_t i = 0; i < n; i++) { Double_t tmp = pD[i]; if ( pV[i] >= 0 && tmp < 0 ) { tmp = -pV[i]/tmp; if (tmp < bound) bound = tmp; } } return bound; } //______________________________________________________________________________ Bool_t TQpVar::IsInteriorPoint() { // Is the current position an interior point ? Bool_t interior = kTRUE; if (fMclo > 0) interior = interior && fT.SomePositive(fCloIndex) && fLambda.SomePositive(fCloIndex); if (fMcup > 0) interior = interior && fU.SomePositive(fCupIndex) && fPi.SomePositive(fCupIndex); if (fNxlo > 0) interior = interior && fV.SomePositive(fXloIndex) && fGamma.SomePositive(fXloIndex); if (fNxup > 0) interior = interior && fW.SomePositive(fXupIndex) && fPhi.SomePositive(fXupIndex); return interior; } //______________________________________________________________________________ Double_t TQpVar::FindBlocking(TQpVar *step, Double_t &primalValue, Double_t &primalStep, Double_t &dualValue, Double_t &dualStep, Int_t &fIrstOrSecond) { // Performs the same function as StepBound, and supplies additional information about // which component of the nonnegative variables is responsible for restricting alpha. // In terms of the abstract formulation, the components have the following meanings : // // primalValue : the value of the blocking component of the primal variables (u,t,v,w). // primalStep : the corresponding value of the blocking component of the primal step // variables (b->u,b->t,b->v,b->w) // dualValue : the value of the blocking component of the dual variables/ // (lambda,pi,phi,gamma). // dualStep : the corresponding value of the blocking component of the dual step // variables (b->lambda,b->pi,b->phi,b->gamma) // firstOrSecond : 1 if the primal step is blocking, // 2 if the dual step is block, // 0 if no step is blocking. fIrstOrSecond = 0; Double_t alpha = 1.0; if (fMclo > 0) alpha = FindBlocking(fT,step->fT,fLambda,step->fLambda,alpha, primalValue,primalStep,dualValue,dualStep,fIrstOrSecond); if (fMcup > 0) alpha = FindBlocking(fU,step->fU,fPi,step->fPi,alpha, primalValue,primalStep,dualValue,dualStep,fIrstOrSecond); if (fNxlo > 0) alpha = FindBlocking(fV,step->fV,fGamma,step->fGamma,alpha, primalValue,primalStep,dualValue,dualStep,fIrstOrSecond); if (fNxup > 0) alpha = FindBlocking(fW,step->fW,fPhi,step->fPhi,alpha, primalValue,primalStep,dualValue,dualStep,fIrstOrSecond); return alpha; } //______________________________________________________________________________ Double_t TQpVar::FindBlocking(TVectorD &w,TVectorD &wstep,TVectorD &u,TVectorD &ustep, Double_t maxStep,Double_t &w_elt,Double_t &wstep_elt,Double_t &u_elt, Double_t &ustep_elt,int& fIrst_or_second) { // See other FindBlocking function return FindBlockingSub(w.GetNrows(), w.GetMatrixArray(), 1, wstep.GetMatrixArray(),1, u.GetMatrixArray(), 1, ustep.GetMatrixArray(),1, maxStep, w_elt,wstep_elt, u_elt,ustep_elt, fIrst_or_second); } //______________________________________________________________________________ Double_t TQpVar::FindBlockingSub(Int_t n, Double_t *w, Int_t incw, Double_t *wstep,Int_t incwstep, Double_t *u, Int_t incu, Double_t *ustep,Int_t incustep, Double_t maxStep, Double_t &w_elt,Double_t &wstep_elt, Double_t &u_elt,Double_t &ustep_elt, Int_t &fIrst_or_second) { // See FindBlocking function Double_t bound = maxStep; Int_t i = n-1; Int_t lastBlocking = -1; // Search backward so that we fInd the blocking constraint of lowest // index. We do this to make things consistent with MPI's MPI_MINLOC, // which returns the processor with smallest rank where a min occurs. // // Still, going backward is ugly! Double_t *pw = w +(n-1)*incw; Double_t *pwstep = wstep+(n-1)*incwstep; Double_t *pu = u +(n-1)*incu; Double_t *pustep = ustep+(n-1)*incustep; while (i >= 0) { Double_t tmp = *pwstep; if (*pw > 0 && tmp < 0) { tmp = -*pw/tmp; if( tmp <= bound ) { bound = tmp; lastBlocking = i; fIrst_or_second = 1; } } tmp = *pustep; if (*pu > 0 && tmp < 0) { tmp = -*pu/tmp; if( tmp <= bound ) { bound = tmp; lastBlocking = i; fIrst_or_second = 2; } } i--; if (i >= 0) { // It is safe to decrement the pointers pw -= incw; pwstep -= incwstep; pu -= incu; pustep -= incustep; } } if (lastBlocking > -1) { // fIll out the elements w_elt = w[lastBlocking]; wstep_elt = wstep[lastBlocking]; u_elt = u[lastBlocking]; ustep_elt = ustep[lastBlocking]; } return bound; } //______________________________________________________________________________ void TQpVar::InteriorPoint(Double_t alpha,Double_t beta) { // Sets components of (u,t,v,w) to alpha and of (lambda,pi,phi,gamma) to beta fS.Zero(); fX.Zero(); fY.Zero(); fZ.Zero(); if (fNxlo > 0) { fV = alpha; fV.SelectNonZeros(fXloIndex); fGamma = beta; fGamma.SelectNonZeros(fXloIndex); } if (fNxup > 0) { fW = alpha; fW.SelectNonZeros(fXupIndex); fPhi = beta; fPhi.SelectNonZeros(fXupIndex); } if (fMclo > 0 ) { fT = alpha; fT.SelectNonZeros(fCloIndex); fLambda = beta; fLambda.SelectNonZeros(fCloIndex); } if (fMcup > 0) { fU = alpha; fU.SelectNonZeros(fCupIndex); fPi = beta; fPi.SelectNonZeros(fCupIndex); } } //______________________________________________________________________________ Double_t TQpVar::Violation() { // The amount by which the current variables violate the non-negativity constraints. Double_t viol = 0.0; Double_t cmin; if (fNxlo > 0) { cmin = fV.Min(); if (cmin < viol) viol = cmin; cmin = fGamma.Min(); if (cmin < viol) viol = cmin; } if (fNxup > 0) { cmin = fW.Min(); if (cmin < viol) viol = cmin; cmin = fPhi.Min(); if (cmin < viol) viol = cmin; } if (fMclo > 0) { cmin = fT.Min(); if (cmin < viol) viol = cmin; cmin = fLambda.Min(); if (cmin < viol) viol = cmin; } if (fMcup > 0) { cmin = fU.Min(); if (cmin < viol) viol = cmin; cmin = fPi.Min(); if (cmin < viol) viol = cmin; } return -viol; } //______________________________________________________________________________ void TQpVar::ShiftBoundVariables(Double_t alpha,Double_t beta) { // Add alpha to components of (u,t,v,w) and beta to components of (lambda,pi,phi,gamma) if (fNxlo > 0) { fV .AddSomeConstant(alpha,fXloIndex); fGamma.AddSomeConstant(beta, fXloIndex); } if (fNxup > 0) { fW .AddSomeConstant(alpha,fXupIndex); fPhi.AddSomeConstant(beta, fXupIndex); } if (fMclo > 0) { fT .AddSomeConstant(alpha,fCloIndex); fLambda.AddSomeConstant(beta, fCloIndex); } if (fMcup > 0) { fU .AddSomeConstant(alpha,fCupIndex); fPi.AddSomeConstant(beta, fCupIndex); } } //______________________________________________________________________________ void TQpVar::Print(Option_t * /*option*/) const { // Print class members cout << "fNx : " << fNx << endl; cout << "fMy : " << fMy << endl; cout << "fMz : " << fMz << endl; cout << "fNxup: " << fNxup << endl; cout << "fNxlo: " << fNxlo << endl; cout << "fMcup: " << fMcup << endl; cout << "fMclo: " << fMclo << endl; fXloIndex.Print("fXloIndex"); fXupIndex.Print("fXupIndex"); fCupIndex.Print("fCupIndex"); fCloIndex.Print("fCloIndex"); fX.Print("fX"); fS.Print("fS"); fY.Print("fY"); fZ.Print("fZ"); fV.Print("fV"); fPhi.Print("fPhi"); fW.Print("fW"); fGamma.Print("fGamma"); fT.Print("fT"); fLambda.Print("fLambda"); fU.Print("fU"); fPi.Print("fPi"); } //______________________________________________________________________________ Double_t TQpVar::Norm1() { // Return the sum of the vector-norm1's Double_t norm = 0.0; norm += fX.Norm1(); norm += fS.Norm1(); norm += fY.Norm1(); norm += fZ.Norm1(); norm += fV.Norm1(); norm += fPhi.Norm1(); norm += fW.Norm1(); norm += fGamma.Norm1(); norm += fT.Norm1(); norm += fLambda.Norm1(); norm += fU.Norm1(); norm += fPi.Norm1(); return norm; } //______________________________________________________________________________ Double_t TQpVar::NormInf() { // Return the sum of the vector-normInf's Double_t norm = 0.0; Double_t tmp = fX.NormInf(); if (tmp > norm) norm = tmp; tmp = fS.NormInf(); if (tmp > norm) norm = tmp; tmp = fY.NormInf(); if (tmp > norm) norm = tmp; tmp = fZ.NormInf(); if (tmp > norm) norm = tmp; tmp = fV.NormInf(); if (tmp > norm) norm = tmp; tmp = fPhi.NormInf(); if (tmp > norm) norm = tmp; tmp = fW.NormInf(); if (tmp > norm) norm = tmp; tmp = fGamma.NormInf(); if (tmp > norm) norm = tmp; tmp = fT.NormInf(); if (tmp > norm) norm = tmp; tmp = fLambda.NormInf(); if (tmp > norm) norm = tmp; tmp = fU.NormInf(); if (tmp > norm) norm = tmp; tmp = fPi.NormInf(); if (tmp > norm) norm = tmp; return norm; } //______________________________________________________________________________ Bool_t TQpVar::ValidNonZeroPattern() { // Check that the variables conform to the non-zero indices if (fNxlo > 0 && ( !fV .MatchesNonZeroPattern(fXloIndex) || !fGamma.MatchesNonZeroPattern(fXloIndex) ) ) { return kFALSE; } if (fNxup > 0 && ( !fW .MatchesNonZeroPattern(fXupIndex) || !fPhi.MatchesNonZeroPattern(fXupIndex) ) ) { return kFALSE; } if (fMclo > 0 && ( !fT .MatchesNonZeroPattern(fCloIndex) || !fLambda.MatchesNonZeroPattern(fCloIndex) ) ) { return kFALSE; } if (fMcup > 0 && ( !fU .MatchesNonZeroPattern(fCupIndex) || !fPi.MatchesNonZeroPattern(fCupIndex) ) ) { return kFALSE; } return kTRUE; } //______________________________________________________________________________ TQpVar &TQpVar::operator=(const TQpVar &source) { // Assignment operator if (this != &source) { TObject::operator=(source); fNx = source.fNx; fMy = source.fMy; fMz = source.fMz; fNxup = source.fNxup; fNxlo = source.fNxlo; fMcup = source.fMcup; fMclo = source.fMclo; fXloIndex = source.fXloIndex; fXupIndex = source.fXupIndex; fCupIndex = source.fCupIndex; fCloIndex = source.fCloIndex; fX .ResizeTo(source.fX); fX = source.fX; fS .ResizeTo(source.fS); fS = source.fS; fY .ResizeTo(source.fY); fY = source.fY; fZ .ResizeTo(source.fZ); fZ = source.fZ; fV .ResizeTo(source.fV); fV = source.fV; fPhi .ResizeTo(source.fPhi); fPhi = source.fPhi; fW .ResizeTo(source.fW); fW = source.fW; fGamma .ResizeTo(source.fGamma) ; fGamma = source.fGamma; fT .ResizeTo(source.fT); fT = source.fT; fLambda.ResizeTo(source.fLambda); fLambda = source.fLambda; fU .ResizeTo(source.fU); fU = source.fU; fPi .ResizeTo(source.fPi); fPi = source.fPi; // LM: copy also this data member fNComplementaryVariables = source.fNComplementaryVariables; } return *this; }