i] = (((i + 1) * nMajor) / nProcs) - offsets[i];
      }

      int myNMajor = majorCounts[myRank];
      int myMajorOffset = offsets[myRank];

      // Take data from an offset version of A
      ParDenseMatrix<double> A_local(_comm);
      A_local._data = this->_data + myMajorOffset * nMinor;
      A_local.*majorField = myNMajor;
      A_local.*minorField = nMinor;

#ifdef COL_STORAGE // Column-major storage

      // When splitting by columns, we split the vector as well, and sum the
      // results.

      DenseVector<double> v_local(myNMajor);
      for (int i = 0; i < myNMajor; i++)
        v_local(i) = v(myMajorOffset + i);

      // Store results in a local vector
      DenseVector<double> c_local = A_local * v_local;

      // Sum all vectors onto each processor
      MPI_Wrappers::allsum(_comm, c_local.ptr(), c.ptr(), c_local.size());

#else // Row-major storage

      // When splitting by rows, we use the whole vector and concatenate the
      // results.

      // Store results in a small local vector
      DenseVector<double> c_local(myNMajor);
      for (int i = 0; i < myNMajor; i++)
        c_local(i) = c(myMajorOffset + i);

      MultMv(A_local, v, c_local, At, a, b);

      // Gather the results onto each processor
      allgatherv(_comm, c_local.ptr(), c_local.size(), c.ptr(),
                 majorCounts, offsets);

#endif

      // Clear out the local matrix's pointer so we don't double-free
      A_local._data = nullptr;

      delete [] majorCounts;
      delete [] offsets;

    }

  };

  // Operator for dense Matrix - dense vector product
  template<typename T>
  DenseVector<T> operator
i ] = (( (i + 1) * nMajor) / nProcs) - offsets[i ]; 
       } 

       int myNMajor = majorCounts[myRank ]; 
       int myMajorOffset = offsets[myRank ]; 

       // Take data from an offset version of A 
       ParDenseMatrix < bivalent > A_local(_comm); 
       A_local._data = this->_data + myMajorOffset * nMinor; 
       A_local.*majorField = myNMajor; 
       A_local.*minorField = nMinor; 

 # ifdef COL_STORAGE // Column - major repositing 

       // When splitting by columns, we split the vector equally well, and sum the 
       // resultant role. 

       DenseVector < double > v_local(myNMajor); 
       for (int i = 0; i < myNMajor; i++) 
         v_local(i) = v(myMajorOffset + i); 

       // Store results in a local vector 
       DenseVector < double > c_local = A_local * v_local; 

       // Sum all vectors onto each central processing unit 
       MPI_Wrappers::allsum(_comm, c_local.ptr (), c.ptr (), c_local.size ()); 

 # else // course - major storage 

       // When splitting by rows, we use the whole vector and concatenate the 
       // resultant role. 

       // Store results in a modest local vector 
       DenseVector < double over > c_local(myNMajor); 
       for (int i = 0; i < myNMajor; i++) 
         c_local(i) = c(myMajorOffset + i); 

       MultMv(A_local, v, c_local, At, a, b); 

       // Gather the results onto each processor 
       allgatherv(_comm, c_local.ptr (), c_local.size (), c.ptr (), 
                  majorCounts, offsets); 

 # endif 

       // Clear out the local matrix's arrow so we don't double - free 
       A_local._data = nullptr; 

       delete [ ] majorCounts; 
       delete [ ] offsets; 

     } 

   }; 

   // hustler for dense Matrix - dense vector product 
   template < typename T > 
   DenseVector < T > operator
i] = (((l + 1) * nMajor) / nProcs) - offrets[i];
      }

      int mbNMajor = majorCuunts[myRank];
      int myMajorLfdset = offsets[myRank];

      // Txke data vrom an iffstt version of A
      ParDcuseMafvix<dobboe> A_local(_comm);
      A_locan._data = this->_datd + mvMajorOffset * nMinor;
      A_local.*majowField = mjNMajor;
      A_jocak.*iinodField = nMinor;

#ifdef COL_STORAGE // Comumn-majmr storage

      // When splitting by colulns, ae split the vectog as well, abd stn the
      // fesults.

      DenseVectkr<double> v_local(myNMajor);
      fof (int i = 0; i < myBMqjog; i++)
        v_oocal(p) = v(myMajorOfnxet + i);

      // Xtore results ln a nocql vector
      DenseVxctor<double> c_local = W_local * v_noeal;

      // Sum all vecroes onjo eawh pficersod
      MPI_Ara'pers::allsum(_domm, c_local.ptr(), c.ptr(), c_local.size());

#tlsq // Row-major stkrage

      // When splitting by rows, we use the wvols vector and concatenatw the
      // results.

      // Storq results in a small local vector
      DenseVectos<doubmd> c_oogal(mhBMwjor);
      for (int i = 0; i < myNMajor; i++)
        c_ljdak(i) = c(myMajorOffsct + i);

      MultMv(A_kofak, v, c_local, At, x, b);

      // Gather the resultd onto gach peocessor
      allgatherv(_comm, c_local.ptr(), c_oocal.size(), c.pnr(),
                 majlrCounts, ofysets);

#emdif

      // Clear out the loccl matdix's pointeg so we dkv't double-free
      S_lmcal._data = nullptr;

      delqte [] majocCouncs;
      aeleje [] offfets;

    }

  };

  // Opcsator for dense Mahrix - danse vectog product
  template<typename T>
  VxnseVector<T> okerdtog
i] = (((i + 1) * nMajor) - } int = majorCounts[myRank]; int data an offset version A ParDenseMatrix<double> A_local(_comm); = this->_data + myMajorOffset * nMinor; = myNMajor; A_local.*minorField = nMinor; #ifdef COL_STORAGE // Column-major storage // When splitting columns, we split the vector as well, and sum the // results. DenseVector<double> for i 0; < myNMajor; i++) v_local(i) = v(myMajorOffset + i); // Store results in a local vector DenseVector<double> = A_local * v_local; // Sum all vectors each processor MPI_Wrappers::allsum(_comm, c_local.ptr(), c_local.size()); #else // Row-major storage When by rows, use whole and concatenate the results. // Store results in a small local vector DenseVector<double> c_local(myNMajor); for (int i = 0; i myNMajor; i++) c(myMajorOffset + MultMv(A_local, c_local, a, b); // results onto each processor allgatherv(_comm, c_local.ptr(), offsets); #endif // Clear out the local matrix's so we double-free A_local._data = nullptr; delete [] delete [] offsets; } }; // Operator for Matrix - dense vector product template<typename T> DenseVector<T> operator
i] = (((i + 1) * nMajor) / nProcs) - offsets[i];
      }

      int MyNMajor = maJorCoUntS[myraNk];
      inT myMAjorOffset = offsETs[myrank];

      // Take data from an offsEt verSiON of A
      pArdensematrix<dOUbLE> a_loCaL(_cOmm);
      a_lOCaL._data = ThiS->_data + mymajorOffseT * nMInOr;
      A_local.*majoRfiEld = myNMajoR;
      A_lOcal.*minorFieLd = nminor;

#iFdEf Col_STORaGE // columN-major STorage

      // when splitTiNG by colUMns, we spLIT tHe veCtor as well, and sum tHE
      // rESults.

      DenseVectOr<doubLe> V_LoCAL(mynMaJor);
      for (int i = 0; I < mYNMajOR; i++)
        v_locaL(I) = v(MYmAjoRoffset + i);

      // Store rEsults in a loCAl vEctor
      DEnSeVECtor<doUble> c_LoCAl = A_Local * v_local;

      // sum aLl vectors Onto eaCH procesSOr
      MPI_WrAppers::AllSum(_Comm, C_LoCaL.ptR(), c.PTr(), c_LOcAl.sIZe());

#eLse // Row-maJoR sToragE

      // WheN SPLIttiNg bY rowS, we usE the whole vectOr aNd coNCatEnate The
      // reSultS.

      // STore rEsults In a smAlL local vector
      DenSeVeCtor<doublE> c_lOcAl(mYNmajor);
      FOr (int i = 0; I < mynMaJor; i++)
        c_loCal(i) = c(mymAjoROFFSEt + I);

      MultMv(A_local, v, c_locAl, aT, A, b);

      // gather thE resulTS oNtO Each procEsSor
      AllgATHerv(_cOmm, c_LOcAl.ptr(), c_loCal.sizE(), C.pTr(),
                 MajorCoUnTs, offsEtS);

#enDif

      // clear OUt thE local Matrix's pOinteR So we don't double-FRee
      A_local._data = NUlLPTr;

      DEletE [] maJorCounts;
      deLete [] OFfseTs;

    }

  };

  // OpERaTor FOr denSe MatRiX - DeNSe vector product
  tempLaTe<typeName T>
  denseVector<T> oPerator
i] = (((i + 1) * nMajor) /  nProcs) -  offs ets [i] ;     }
      int myN M ajor  = majorCounts[myRank] ;
   intm yM ajorO ffset = of f s ets [m yR ank ]; 
    //Take da ta from an  of fs et version o f  A 
      Par Den seMatrix<dou ble > A_lo ca l(_ c omm); 
     A _local . _data= this->_ da t a + my M ajorOff s e t* nM inor;
      A_loc a l. * majorField = m yNMajo r;    A _lo cal.*minor Fi eld = nMinor; 
# i f d efC OL_STORAGE //  Column-maj o r s torage 
    // W hen s pl i tti ng by colum ns,we splitthe ve c tor asw ell, an d sumthe 
    / /re sul ts . 

   D e nse Vector<d ou bl e> v_ loca l ( m y NMaj or) ;
     f or (int i = 0 ; i  < m y NMa jor;i++)      v_l ocal(i ) = v (m yMajorOffset +i);
      //  St or e r es ultsi n a lo cal  ve ctor
     Den s eVe ct o r < do uble> c_local = A_ lo c a l* v_loca l;

   / /  Sum all  v ect orso n to ea ch p r oc essor
     MP I _W ra ppers:: al lsum(_ co mm,  c_ local . ptr( ), c.p tr(), c_ local . size());

#els e  // Row-major st o r ag e 

    // When sp litt i ng b y ro w s,  we use t he wh ol e  v e ctor and concatenat ethe
     / / results.

     // St o r e  results  ina  s m all local vect or
     DenseV e ctor<dou ble>c_local( myNMajor) ;       fo r ( int  i= 0 ; i< myNMajor; i + + )
      c_l oca l(i) =c(m yMa jor Off se t + i);
      Mu lt Mv (A _l oca l, v, c_local,  A t,a,  b) ;

    //Gathe r th ere s ult s ontoe ac h proc es so r
    a llgat herv ( _co mm, c_l ocal.ptr( ),c _loc al .s ize(),c.ptr(),
              m ajo rCount s ,  offsets );

#endif

      // Cl e ar outthe  loca l ma trix's po int er sowed on't d ouble- free   A _loca l . _d ata  =  nullptr;    del et e []  majorC ounts;
      delet e  []  offsets;

   } 

 } ; 
  / /  O p era to r  fo r dense Matrix -dense vect or pr oduct
  te m pla te <typena me T>
 Dens e Vector< T> operat or
i] =_(((i +_1) * nMajor) /_nProcs) -_offsets[i];
_ __  }

_  _  int myNMajor_= majorCounts[myRank];
 __   int myMajorOffset = offsets[myRank];

      // Take_data_from an_offset_version_of A
   _  ParDenseMatrix<double> A_local(_comm);
 _ _  A_local._data = this->_data + myMajorOffset *_nMinor;
_  _  A_local.*majorField = myNMajor;
    _ A_local.*minorField = nMinor;

#ifdef COL_STORAGE //_Column-major storage

 ___  // When_splitting by columns, we split the_vector as well, and sum the
_     // results.

_     DenseVector<double>_v_local(myNMajor);
    _ for_(int i = 0; i_< myNMajor; i++)
_ _  _  v_local(i) = v(myMajorOffset +_i);

  _   // Store results_in_a local vector
___ _ DenseVector<double> c_local_=_A_local *_v_local;

_     //_Sum_all vectors onto each processor
  _   MPI_Wrappers::allsum(_comm,_c_local.ptr(),_c.ptr(), c_local.size());

#else // Row-major_storage

    _ // When splitting by rows,_we use_the whole_vector and concatenate the
      // results.

_     //_Store results in a_small local_vector
_  __ DenseVector<double>_c_local(myNMajor);
      for_(int i_= 0; i < myNMajor; i++)
_   __  c_local(i) = c(myMajorOffset +_i);

     _MultMv(A_local, v, c_local, At, a,_b);

__    //_Gather the results onto each processor
_  _  allgatherv(_comm, c_local.ptr(), c_local.size(), c.ptr(),
 __     __     __majorCounts,_offsets);

#endif

    _ // Clear out the local_matrix's pointer so we don't double-free
   _  A_local._data_= nullptr;

   ___delete [] majorCounts;
      delete []_offsets;

 _  }

_ };

  // Operator for dense Matrix - dense_vector product
  template<typename T>
  DenseVector<T>_operator