void DenseLinAlgPack::syr(value_type alpha, const DVectorSlice& vs_rhs, DMatrixSliceSym* sym_lhs)
{
  assert_gms_square(sym_lhs->gms());
  MtV_assert_sizes( sym_lhs->gms().rows(), sym_lhs->gms().cols()
    , BLAS_Cpp::no_trans, vs_rhs.dim() );
  BLAS_Cpp::syr( sym_lhs->uplo(), vs_rhs.dim(), alpha, vs_rhs.raw_ptr()
    , vs_rhs.stride(), sym_lhs->gms().col_ptr(1), sym_lhs->gms().max_rows() );
}
void DenseLinAlgPack::ger(
  value_type alpha, const DVectorSlice& vs_rhs1, const DVectorSlice& vs_rhs2
  , DMatrixSlice* gms_lhs )
{
  Vp_MtV_assert_sizes( vs_rhs2.dim(),  gms_lhs->rows(), gms_lhs->cols()
    , BLAS_Cpp::no_trans, vs_rhs1.dim() );
  BLAS_Cpp::ger(
    gms_lhs->rows(), gms_lhs->cols(), alpha
    ,vs_rhs1.raw_ptr(), vs_rhs1.stride()
    ,vs_rhs2.raw_ptr(), vs_rhs2.stride()
    ,gms_lhs->col_ptr(1), gms_lhs->max_rows() );
}
void AbstractLinAlgPack::add_elements( SpVector* sv_lhs, value_type alpha, const DVectorSlice& vs_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() );
  DVectorSlice::const_iterator
    itr = vs_rhs.begin();
  if(add_zeros) {
    for( size_type i = 1; i <= vs_rhs.dim(); ++i )
      sv_lhs->add_element( ele_t( i + offset, alpha * (*itr++) ) );
  }
  else {
    for( size_type i = 1; i <= vs_rhs.dim(); ++i, ++itr )
      if( *itr != 0.0 )
        sv_lhs->add_element( ele_t( i + offset, alpha * (*itr) ) );
  }
  sv_lhs->assume_sorted(assume_sorted);
}
void DenseLinAlgPack::Vp_StMtV(DVectorSlice* vs_lhs, value_type alpha, const DMatrixSlice& gms_rhs1
  , BLAS_Cpp::Transp trans_rhs1, const DVectorSlice& vs_rhs2, value_type beta)
{
  Vp_MtV_assert_sizes(vs_lhs->dim(), gms_rhs1.rows()	, gms_rhs1.cols(), trans_rhs1
    , vs_rhs2.dim());
  BLAS_Cpp::gemv(trans_rhs1,gms_rhs1.rows(),gms_rhs1.cols(),alpha,gms_rhs1.col_ptr(1)
    ,gms_rhs1.max_rows(), vs_rhs2.raw_ptr(),vs_rhs2.stride(),beta,vs_lhs->raw_ptr()
    ,vs_lhs->stride());
}
void DenseLinAlgPack::V_InvMtV(DVectorSlice* vs_lhs, const DMatrixSliceTri& tri_rhs1, BLAS_Cpp::Transp trans_rhs1
  , const DVectorSlice& vs_rhs2)
{
  assert_gms_square(tri_rhs1.gms());
  MtV_assert_sizes(tri_rhs1.gms().rows(), tri_rhs1.gms().cols(), trans_rhs1, vs_rhs2.dim());
  Vp_V_assert_sizes( vs_lhs->dim(), tri_rhs1.gms().rows() );
  (*vs_lhs) = vs_rhs2;
  BLAS_Cpp::trsv(tri_rhs1.uplo(),trans_rhs1,tri_rhs1.diag(),tri_rhs1.gms().rows()
    ,tri_rhs1.gms().col_ptr(1),tri_rhs1.gms().max_rows(), vs_lhs->raw_ptr(),vs_lhs->stride());
}
void DenseLinAlgPack::Vp_StMtV(DVectorSlice* vs_lhs, value_type alpha, const DMatrixSliceSym& sym_rhs1
  , BLAS_Cpp::Transp trans_rhs1, const DVectorSlice& vs_rhs2, value_type beta)
{
  assert_gms_square(sym_rhs1.gms());
  Vp_MtV_assert_sizes(vs_lhs->dim(), sym_rhs1.gms().rows(), sym_rhs1.gms().cols(), trans_rhs1
    , vs_rhs2.dim());
  BLAS_Cpp::symv(sym_rhs1.uplo(),sym_rhs1.gms().rows(),alpha,sym_rhs1.gms().col_ptr(1)
    ,sym_rhs1.gms().max_rows(),vs_rhs2.raw_ptr(),vs_rhs2.stride(),beta
    ,vs_lhs->raw_ptr(),vs_lhs->stride());
}
void MatrixSymPosDefLBFGS::Vp_DtV( DVectorSlice* y, const DVectorSlice& x ) const
{
  DenseLinAlgPack::Vp_MtV_assert_sizes(
    y->dim(), m_bar_, m_bar_, BLAS_Cpp::no_trans, x.dim() );

  DVectorSlice::const_iterator
    d_itr	= STY_.diag(0).begin(),
    x_itr	= x.begin();
  DVectorSlice::iterator
    y_itr	= y->begin();

  while( y_itr != y->end() )
    *y_itr++ += (*d_itr++) * (*x_itr++);		
}
void DenseLinAlgPack::Vp_StMtV(DVectorSlice* vs_lhs, value_type alpha, const DMatrixSliceTri& tri_rhs1
  , BLAS_Cpp::Transp trans_rhs1, const DVectorSlice& vs_rhs2, value_type beta)
{
  Vp_MtV_assert_sizes(vs_lhs->dim(),tri_rhs1.gms().rows(),tri_rhs1.gms().cols()
            ,trans_rhs1,vs_rhs2.dim() );

  // If op(gms_rhs2) == gms_lhs and beta = 0.0 then this is a direct call to the BLAS.
  if( vs_lhs->overlap(vs_rhs2) == SAME_MEM && beta == 0.0 )
  {
    V_MtV(vs_lhs, tri_rhs1, trans_rhs1, vs_rhs2);
    if(alpha != 1.0) Vt_S(vs_lhs,alpha);
  }
  else {
    // This is something else so the alias problem is not handled.
    if(beta != 1.0) Vt_S(vs_lhs,beta);
    DVector tmp;
    V_MtV(&tmp, tri_rhs1, trans_rhs1, vs_rhs2);
    Vp_StV(vs_lhs,alpha,tmp());
  }
}
void QPInitFixedFreeStd::initialize(
    const DVectorSlice                   &g
    ,const MatrixSymOp              &G
    ,const MatrixOp                 *A
    ,size_type                          n_R
    ,const size_type                    i_x_free[]
    ,const size_type                    i_x_fixed[]
    ,const EBounds                      bnd_fixed[]
    ,const DVectorSlice                  &b_X
    ,const MatrixSymOpNonsing    &Ko
    ,const DVectorSlice                  &fo
    ,Constraints                        *constraints
    ,std::ostream                       *out
    ,bool                               test_setup
    ,value_type                         warning_tol
    ,value_type                         error_tol
    ,bool                               print_all_warnings
)
{
    namespace GPMSTP = AbstractLinAlgPack::GenPermMatrixSliceIteratorPack;

    if(!constraints)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "constraints == NULL is not allowed." );

    // Validate the sizes of the input arguments
    const size_type
    n = constraints->n(),
    n_X = n - n_R;
    if( n_R > n )
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "n_R > constraints->n() is not allowed." );
    if(g.dim() !=n)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "g.dim() != constraints->n()." );
    if(G.rows() != n || G.cols() !=  n)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "G.rows() != constraints->n() or G.cols() !=  constraints->n()." );
    size_type
    m = 0;
    if(A) {
        m = A->cols();
        if( A->rows() != n )
            throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                         "A->rows() != constraints->n()." );
    }
    if(b_X.dim() != n_X)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "b_X.dim() != constraints->n() - n_R." );
    if(Ko.rows() != n_R+m || Ko.cols() !=  n_R+m)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "Ko.rows() != n_R+A->cols() or Ko.cols() !=  n_R+A->cols()." );
    if(fo.dim() != n_R+m)
        throw std::invalid_argument( "QPInitFixedFreeStd::initialize(...) : Error, "
                                     "fo.dim() != n_R+A->cols()." );

    // Setup x_init, l_x_X_map, i_x_X_map

    const int NOT_SET_YET = -9999; // Can't be FREE, LOWER, UPPER, or EQUALITY
    if(test_setup)
        x_init_.assign( n, (EBounds)NOT_SET_YET );
    else
        x_init_.resize(n);
    l_x_X_map_.assign(n,0);
    i_x_X_map_.assign(n_X,0);

    // Set free portion of x_init
    if( i_x_free == NULL ) {
        for( size_type i = 0; i < n_R; ++i )
            x_init_[i] = FREE;
    }
    else {
        if(test_setup) {
            for( const size_type *i_x_R = i_x_free; i_x_R != i_x_free + n_R; ++i_x_R ) {
                if( *i_x_R < 1 || *i_x_R > n ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "i_x_free[" << i_x_R-i_x_free << "] = "
                            << (*i_x_R) << " is out of bounds";
                    throw std::invalid_argument( omsg.str() );
                }
                if( x_init_(*i_x_R) != NOT_SET_YET ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "Duplicate entries for i_x_free[i] = "
                            << (*i_x_R);
                    throw std::invalid_argument( omsg.str() );
                }
                x_init_(*i_x_R) = FREE;
            }
        }
        else {
            for( const size_type *i_x_R = i_x_free; i_x_R != i_x_free + n_R; ++i_x_R ) {
                x_init_(*i_x_R) = FREE;
            }
        }
    }

    // Setup the fixed portion of x_init and l_x_X_map and i_x_X_map
    {
        const size_type
        *i_x_X = i_x_fixed;
        const EBounds
        *bnd = bnd_fixed;
        i_x_X_map_t::iterator
        i_x_X_map_itr = i_x_X_map_.begin();
        if(test_setup) {
            for( size_type l = 1; l <= n_X; ++l, ++i_x_X, ++bnd, ++i_x_X_map_itr ) {
                if( *i_x_X < 1 || *i_x_X > n ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "i_x_fixed[" << i_x_X-i_x_fixed << "] = "
                            << (*i_x_X) << " is out of bounds";
                    throw std::invalid_argument( omsg.str() );
                }
                if( *bnd == FREE ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "bnd_fixed[" << l-1 << "] can not equal FREE";
                    throw std::invalid_argument( omsg.str() );
                }
                if( x_init_(*i_x_X) != NOT_SET_YET ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "Duplicate entries for i_x_fixed[i] = "
                            << (*i_x_X);
                    throw std::invalid_argument( omsg.str() );
                }
                x_init_(*i_x_X) = *bnd;
                l_x_X_map_(*i_x_X) = l;
                *i_x_X_map_itr = *i_x_X;
            }
            // Check that x_init was filled up properly
            for( size_type i = 1; i <= n; ++i ) {
                if( x_init_(i) == NOT_SET_YET ) {
                    std::ostringstream omsg;
                    omsg
                            << "QPInitFixedFreeStd::initialize(...) : Error, "
                            << "x_init(" << i << ") has not been set by"
                            " i_x_free[] or i_x_fixed[].";
                    throw std::invalid_argument( omsg.str() );
                }
            }
        }
        else {
            for( size_type l = 1; l <= n_X; ++l, ++i_x_X, ++bnd, ++i_x_X_map_itr ) {
                x_init_(*i_x_X) = *bnd;
                l_x_X_map_(*i_x_X) = l;
                *i_x_X_map_itr = *i_x_X;
            }
        }
    }

    // Setup Q_R and Q_X
    Q_R_row_i_.resize( i_x_free ? n_R : 0 );
    Q_R_col_j_.resize( i_x_free ? n_R : 0 );
    Q_X_row_i_.resize(n_X);
    Q_X_col_j_.resize(n_X);
    initialize_Q_R_Q_X(
        n_R,n_X,i_x_free,i_x_fixed,test_setup
        ,n_R && i_x_free ? &Q_R_row_i_[0] : NULL
        ,n_R && i_x_free ? &Q_R_col_j_[0] : NULL
        ,&Q_R_
        ,n_X ? &Q_X_row_i_[0] : NULL
        ,n_X ? &Q_X_col_j_[0] : NULL
        ,&Q_X_
    );

    // Setup other arguments
    n_				= n;
    n_R_			= n_R;
    m_				= m;
    g_.bind(const_cast<DVectorSlice&>(g));
    G_				= &G;
    A_				= A;
    b_X_.bind(const_cast<DVectorSlice&>(b_X));
    Ko_				= &Ko;
    fo_.bind(const_cast<DVectorSlice&>(fo));
    constraints_ 	= constraints;
}
void MatrixSymIdentitySerial::V_InvMtV(
  DVectorSlice* y, BLAS_Cpp::Transp M_trans, const DVectorSlice& x
  ) const
{
  DenseLinAlgPack::Vp_MtV_assert_sizes( y->dim(), rows(), cols(), BLAS_Cpp::no_trans, x.dim() );
  LinAlgOpPack::V_StV(y,scale_,x);
}
void MatrixSymIdentitySerial::Vp_StMtV(
  DVectorSlice* y, value_type a, BLAS_Cpp::Transp M_trans
  ,const DVectorSlice& x, value_type b
  ) const
{
  DenseLinAlgPack::Vp_MtV_assert_sizes( y->dim(), rows(), cols(), BLAS_Cpp::no_trans, x.dim() );
  DenseLinAlgPack::Vt_S(y,b);
  DenseLinAlgPack::Vp_StV(y,a*scale_,x);
}