RTOpPack::SparseSubVector
AbstractLinAlgPack::sub_vec_view(
  const SpVectorSlice&   sv_in
  ,const Range1D&        rng_in
  )
{
  using Teuchos::null;
  const Range1D        rng = RangePack::full_range(rng_in,1,sv_in.dim());
  const SpVectorSlice  sv = sv_in(rng);

  RTOpPack::SparseSubVector  sub_vec;

  if(!sv.nz()) {
    sub_vec.initialize(
      rng.lbound()-1  // global_offset
      ,rng.size()     // sub_dim
      ,0              // nz
      ,null           // vlaues
      ,1              // values_stride
      ,null           // indices
      ,1              // indices_stride
      ,0              // local_offset
      ,1              // is_sorted
      );
  }
  else {
    SpVectorSlice::const_iterator itr = sv.begin();
    TEUCHOS_TEST_FOR_EXCEPT( !( itr != sv.end() ) );
    if( sv.dim() && sv.nz() == sv.dim() && sv.is_sorted() ) {
      const Teuchos::ArrayRCP<const value_type>  values =
        Teuchos::arcp(&itr->value(), 0, values_stride*rng.size(), false) ;
      sub_vec.initialize(
        rng.lbound()-1    // global_offset
        ,rng.size()       // sub_dim
        ,values           // values
        ,values_stride    // values_stride
        );
    }
    else {
      const Teuchos::ArrayRCP<const value_type>  values =
        Teuchos::arcp(&itr->value(), 0, values_stride*sv.nz(), false) ;
      const Teuchos::ArrayRCP<const index_type> indexes =
        Teuchos::arcp(&itr->index(), 0, indices_stride*sv.nz(), false);
      sub_vec.initialize(
        rng.lbound()-1    // global_offset
        ,sv.dim()         // sub_dim
        ,sv.nz()          // sub_nz
        ,values           // values
        ,values_stride    // values_stride
        ,indexes          // indices
        ,indices_stride   // indices_stride
        ,sv.offset()      // local_offset
        ,sv.is_sorted()   // is_sorted
        );
    }
  }
  
  return sub_vec;
}
std::ostream&
AbstractLinAlgPack::operator<<(std::ostream& os, const SpVectorSlice& svs)
{
  os << std::left << std::setw(0) << svs.dim() << "  " << svs.nz() << std::endl << std::right;
  if( !svs.dim() ) return os;
  const SpVectorSlice::difference_type offset = svs.offset();
  for(SpVectorSlice::const_iterator itr = svs.begin(); itr != svs.end(); ++itr )
    os << "  " << itr->value() << ":" << (itr->index() + offset);
  return os << std::endl;
}
void MultiVectorMutableCols::Vp_StMtV(
  VectorMutable* y, value_type a, BLAS_Cpp::Transp M_trans
  ,const SpVectorSlice& x, value_type b
  ) const
{
  using AbstractLinAlgPack::dot;

  // y = b*y
  LinAlgOpPack::Vt_S(y,b);

  if( M_trans == BLAS_Cpp::no_trans ) {
    //
    // y += a*M*x
    //
    // =>
    //
    // y += a * x(1) * M(:,1) + a * x(2) * M(:,2) + ...
    //
    SpVectorSlice::difference_type o = x.offset();
    for( SpVectorSlice::const_iterator itr = x.begin(); itr != x.end(); ++itr ) {
      const size_type j = itr->index() + o;
      LinAlgOpPack::Vp_StV( y, a * itr->value(), *col_vecs_[j-1] );
    }
  }
  else {
    //
    // y += a*M'*x
    //
    // =>
    //
    // y(1) += a M(:,1)*x
    // y(2) += a M(:,2)*x
    // ...
    //
    for( size_type j = 1; j <= col_vecs_.size(); ++j )
      y->set_ele(
        j
        ,y->get_ele(j) + a * dot(*col_vecs_[j-1],x)
        );
  }
}
void AbstractLinAlgPack::add_elements( SpVector* sv_lhs, value_type alpha, const SpVectorSlice& sv_rhs
                   , size_type offset, bool add_zeros )
{
  typedef SpVector::element_type ele_t;
  const bool assume_sorted = ( !sv_lhs->nz() || ( sv_lhs->nz() && sv_lhs->is_sorted() ) )
    && ( !sv_rhs.nz() || ( sv_rhs.nz() || sv_rhs.is_sorted() ) );
  if(add_zeros) {
    for( SpVectorSlice::const_iterator itr = sv_rhs.begin(); itr != sv_rhs.end(); ++itr )
      sv_lhs->add_element( ele_t( itr->index() + sv_rhs.offset() + offset, alpha * (itr->value()) ) );
  }
  else {
    for( SpVectorSlice::const_iterator itr = sv_rhs.begin(); itr != sv_rhs.end(); ++itr )
      if(itr->value() != 0.0 )
        sv_lhs->add_element( ele_t( itr->index() + sv_rhs.offset() + offset, alpha * (itr->value()) ) );
  }
  sv_lhs->assume_sorted(assume_sorted);
}