bool NLPDirectTester::finite_diff_check(
  NLPDirect         *nlp
  ,const Vector     &xo
  ,const Vector     *xl
  ,const Vector     *xu
  ,const Vector     *c
  ,const Vector     *Gf
  ,const Vector     *py
  ,const Vector     *rGf
  ,const MatrixOp   *GcU
  ,const MatrixOp   *D
  ,const MatrixOp   *Uz
  ,bool             print_all_warnings
  ,std::ostream     *out
  ) const
{

  using std::setw;
  using std::endl;
  using std::right;

  using AbstractLinAlgPack::sum;
  using AbstractLinAlgPack::dot;
  using AbstractLinAlgPack::Vp_StV;
  using AbstractLinAlgPack::random_vector;
  using AbstractLinAlgPack::assert_print_nan_inf;
  using LinAlgOpPack::V_StV;
  using LinAlgOpPack::V_StMtV;
  using LinAlgOpPack::Vp_MtV;
  using LinAlgOpPack::M_StM;
  using LinAlgOpPack::M_StMtM;

  typedef VectorSpace::vec_mut_ptr_t  vec_mut_ptr_t;

//  using AbstractLinAlgPack::TestingPack::CompareDenseVectors;
//  using AbstractLinAlgPack::TestingPack::CompareDenseSparseMatrices;

  using TestingHelperPack::update_success;

  bool success = true, preformed_fd;
  if(out) {
    *out << std::boolalpha
       << std::endl
       << "*********************************************************\n"
       << "*** NLPDirectTester::finite_diff_check(...) ***\n"
       << "*********************************************************\n";
  }

  const Range1D
    var_dep      = nlp->var_dep(),
    var_indep    = nlp->var_indep(),
    con_decomp   = nlp->con_decomp(),
    con_undecomp = nlp->con_undecomp();
  NLP::vec_space_ptr_t
    space_x = nlp->space_x(),
    space_c = nlp->space_c();

  // //////////////////////////////////////////////
  // Validate the input

  TEST_FOR_EXCEPTION(
    py && !c, std::invalid_argument
    ,"NLPDirectTester::finite_diff_check(...) : "
    "Error, if py!=NULL then c!=NULL must also be true!" );

  const CalcFiniteDiffProd
    &fd_deriv_prod = this->calc_fd_prod();

  const value_type
    rand_y_l = -1.0, rand_y_u = 1.0,
    small_num = ::sqrt(std::numeric_limits<value_type>::epsilon());

  try {

  // ///////////////////////////////////////////////
  // (1) Check Gf

  if(Gf) {
    switch( Gf_testing_method() ) {
      case FD_COMPUTE_ALL: {
        // Compute FDGf outright
        TEST_FOR_EXCEPT(true); // ToDo: update above!
        break;
      }
      case FD_DIRECTIONAL: {
        // Compute FDGF'*y using random y's
        if(out)
          *out
            << "\nComparing products Gf'*y with finite difference values FDGf'*y for "
            << "random y's ...\n";
        vec_mut_ptr_t y = space_x->create_member();
        value_type max_warning_viol = 0.0;
        int num_warning_viol = 0;
        const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
        for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
          if( num_fd_directions() > 0 ) {
            random_vector( rand_y_l, rand_y_u, y.get() );
            if(out)
              *out
                << "\n****"
                << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = "
                << (y->norm_1() / y->dim()) << " )"
                << "\n***\n";
          }
          else {
            *y = 1.0;
            if(out)
              *out
                << "\n****"
                << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )"
                << "\n***\n";
          }
          value_type
            Gf_y = dot( *Gf, *y ),
            FDGf_y;
          preformed_fd = fd_deriv_prod.calc_deriv_product(
            xo,xl,xu
            ,*y,NULL,NULL,true,nlp,&FDGf_y,NULL,out,dump_all(),dump_all()
            );
          if( !preformed_fd )
            goto FD_NOT_PREFORMED;
          assert_print_nan_inf(FDGf_y, "FDGf'*y",true,out);
          const value_type
            calc_err = ::fabs( ( Gf_y - FDGf_y )/( ::fabs(Gf_y) + ::fabs(FDGf_y) + small_num ) );
          if( calc_err >= Gf_warning_tol() ) {
            max_warning_viol = my_max( max_warning_viol, calc_err );
            ++num_warning_viol;
          }
          if(out)
            *out
              << "\nrel_err(Gf'*y,FDGf'*y) = "
              << "rel_err(" << Gf_y << "," << FDGf_y << ") = "
              << calc_err << endl;
          if( calc_err >= Gf_error_tol() ) {
            if(out) {
              *out
                << "Error, above relative error exceeded Gf_error_tol = " << Gf_error_tol() << endl;
              if(dump_all()) {
                *out << "\ny =\n" << *y;
              }
            }
          }
        }
        if(out && num_warning_viol)
          *out
            << "\nThere were " << num_warning_viol << " warning tolerance "
            << "violations out of num_fd_directions = " << num_fd_directions()
            << " computations of FDGf'*y\n"
            << "and the maximum violation was " << max_warning_viol
            << " > Gf_waring_tol = " << Gf_warning_tol() << endl;
        break;
      }
      default:
        TEST_FOR_EXCEPT(true); // Invalid value
    }
  }

  // /////////////////////////////////////////////
  // (2) Check py = -inv(C)*c
  //
  // We want to check; 
  // 
  //  FDC * (inv(C)*c) \approx c
  //       \_________/
  //         -py
  //
  // We can compute this as:
  //           
  // FDC * py = [ FDC, FDN ] * [ -py ; 0 ]
  //            \__________/
  //                FDA'
  // 
  // t1 =  [ -py ; 0 ]
  // 
  // t2 = FDA'*t1
  // 
  // Compare t2 \approx c
  // 
  if(py) {
    if(out)
      *out
        << "\nComparing c with finite difference product FDA'*[ -py; 0 ] = -FDC*py ...\n";
    // t1 =  [ -py ; 0 ]
    VectorSpace::vec_mut_ptr_t
      t1 = space_x->create_member();
    V_StV( t1->sub_view(var_dep).get(), -1.0, *py );
    *t1->sub_view(var_indep) = 0.0;
    // t2 = FDA'*t1
    VectorSpace::vec_mut_ptr_t
      t2 = nlp->space_c()->create_member();
    preformed_fd = fd_deriv_prod.calc_deriv_product(
      xo,xl,xu
      ,*t1,NULL,NULL,true,nlp,NULL,t2.get(),out,dump_all(),dump_all()
      );
    if( !preformed_fd )
      goto FD_NOT_PREFORMED;
    const value_type
      sum_c  = sum(*c),
      sum_t2 = sum(*t2);
    assert_print_nan_inf(sum_t2, "sum(-FDC*py)",true,out);
    const value_type
      calc_err = ::fabs( ( sum_c - sum_t2 )/( ::fabs(sum_c) + ::fabs(sum_t2) + small_num ) );
    if(out)
      *out
        << "\nrel_err(sum(c),sum(-FDC*py)) = "
        << "rel_err(" << sum_c << "," << sum_t2 << ") = "
        << calc_err << endl;
    if( calc_err >= Gc_error_tol() ) {
      if(out)
        *out
          << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
      if(print_all_warnings)
        *out << "\nt1 = [ -py; 0 ] =\n" << *t1
           << "\nt2 = FDA'*t1 = -FDC*py =\n"   << *t2;
      update_success( false, &success );
    }
    if( calc_err >= Gc_warning_tol() ) {
      if(out)
        *out
          << "\nWarning, above relative error exceeded Gc_warning_tol = " << Gc_warning_tol() << endl;
    }
  }

  // /////////////////////////////////////////////
  // (3) Check D = -inv(C)*N

  if(D) {
    switch( Gc_testing_method() ) {
      case FD_COMPUTE_ALL: {
        //
        // Compute FDN outright and check
        // -FDC * D \aprox FDN
        // 
        // We want to compute:
        // 
        // FDC * -D = [ FDC, FDN ] * [ -D; 0 ]
        //            \__________/
        //                FDA'
        // 
        // To compute the above we perform:
        // 
        // T = FDA' * [ -D; 0 ] (one column at a time)
        // 
        // Compare T \approx FDN
        //
/*
        // FDN
        DMatrix FDN(m,n-m);
        fd_deriv_computer.calc_deriv( xo, xl, xu
          , Range1D(m+1,n), nlp, NULL
          , &FDN() ,BLAS_Cpp::trans, out );

        // T = FDA' * [ -D; 0 ] (one column at a time)
        DMatrix T(m,n-m);
        DVector t(n);
        t(m+1,n) = 0.0;
        for( int s = 1; s <= n-m; ++s ) {
          // t = [ -D(:,s); 0 ]
          V_StV( &t(1,m), -1.0, D->col(s) );
          // T(:,s) =  FDA' * t
          fd_deriv_prod.calc_deriv_product(
            xo,xl,xu,t(),NULL,NULL,nlp,NULL,&T.col(s),out);
        }        

        // Compare T \approx FDN
        if(out)
          *out
            << "\nChecking the computed D = -inv(C)*N\n"
            << "where D(i,j) = (-FDC*D)(i,j), dM(i,j) = FDN(i,j) ...\n";
        result = comp_M.comp(
          T(), FDN, BLAS_Cpp::no_trans
          , CompareDenseSparseMatrices::FULL_MATRIX
          , CompareDenseSparseMatrices::REL_ERR_BY_COL
          , Gc_warning_tol(), Gc_error_tol()
          , print_all_warnings, out );
        update_success( result, &success );
        if(!result) return false;
*/
        TEST_FOR_EXCEPT(true); // Todo: Implement above!
        break;
      }
      case FD_DIRECTIONAL: {
        //
        // Compute -FDC * D * v \aprox FDN * v
        // for random v's
        //
        // We will compute this as:
        // 
        // t1 = [ 0; y ] <: R^(n)
        // 
        // t2 = FDA' * t1  (  FDN * y ) <: R^(m)
        //
        // t1 = [ -D * y ; 0 ]  <: R^(n)
        // 
        // t3 = FDA' * t1  ( -FDC * D * y ) <: R^(m)
        // 
        // Compare t2 \approx t3
        //
        if(out)
          *out
            << "\nComparing finite difference products -FDC*D*y with FDN*y for "
              "random vectors y ...\n";
        VectorSpace::vec_mut_ptr_t
          y  = space_x->sub_space(var_indep)->create_member(),
          t1 = space_x->create_member(),
          t2 = space_c->create_member(),
          t3 = space_c->create_member();
        value_type max_warning_viol = 0.0;
        int num_warning_viol = 0;
        const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
        for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
          if( num_fd_directions() > 0 ) {
            random_vector( rand_y_l, rand_y_u, y.get() );
            if(out)
              *out
                << "\n****"
                << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = "
                << (y->norm_1() / y->dim()) << " )"
                << "\n***\n";
          }
          else {
            *y = 1.0;
            if(out)
              *out
                << "\n****"
                << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )"
                << "\n***\n";
          }
          // t1 = [ 0; y ] <: R^(n)
          *t1->sub_view(var_dep)   = 0.0;
          *t1->sub_view(var_indep) = *y;
          // t2 = FDA' * t1  (  FDN * y ) <: R^(m)
          preformed_fd = fd_deriv_prod.calc_deriv_product(
            xo,xl,xu
            ,*t1,NULL,NULL,true,nlp,NULL,t2.get(),out,dump_all(),dump_all()
            );
          if( !preformed_fd )
            goto FD_NOT_PREFORMED;
          // t1 = [ -D * y ; 0 ]  <: R^(n)
          V_StMtV( t1->sub_view(var_dep).get(), -1.0, *D, BLAS_Cpp::no_trans, *y );
          *t1->sub_view(var_indep) = 0.0;
          // t3 = FDA' * t1  ( -FDC * D * y ) <: R^(m)
          preformed_fd = fd_deriv_prod.calc_deriv_product(
            xo,xl,xu
            ,*t1,NULL,NULL,true,nlp,NULL,t3.get(),out,dump_all(),dump_all()
            );
          // Compare t2 \approx t3
          const value_type
            sum_t2 = sum(*t2),
            sum_t3 = sum(*t3);
          const value_type
            calc_err = ::fabs( ( sum_t2 - sum_t3 )/( ::fabs(sum_t2) + ::fabs(sum_t3) + small_num ) );
          if(out)
            *out
              << "\nrel_err(sum(-FDC*D*y),sum(FDN*y)) = "
              << "rel_err(" << sum_t3 << "," << sum_t2 << ") = "
              << calc_err << endl;
          if( calc_err >= Gc_warning_tol() ) {
            max_warning_viol = my_max( max_warning_viol, calc_err );
            ++num_warning_viol;
          }
          if( calc_err >= Gc_error_tol() ) {
            if(out)
              *out
                << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl
                << "Stoping the tests!\n";
            if(print_all_warnings)
              *out << "\ny =\n" << *y
                   << "\nt1 = [ -D*y; 0 ] =\n" << *t1
                   << "\nt2 =  FDA' * [ 0; y ] = FDN * y =\n" << *t2
                   << "\nt3 =  FDA' * t1 = -FDC * D * y =\n" << *t3;
            update_success( false, &success );
          }
        }
        if(out && num_warning_viol)
          *out
            << "\nThere were " << num_warning_viol << " warning tolerance "
            << "violations out of num_fd_directions = " << num_fd_directions()
            << " computations of sum(FDC*D*y) and sum(FDN*y)\n"
            << "and the maximum relative iolation was " << max_warning_viol
            << " > Gc_waring_tol = " << Gc_warning_tol() << endl;
        break;
      }
      default:
        TEST_FOR_EXCEPT(true);
    }
  }

  // ///////////////////////////////////////////////
  // (4) Check rGf = Gf(var_indep) + D'*Gf(var_dep)

  if(rGf) {
    if( Gf && D ) {
      if(out)
        *out
          << "\nComparing rGf_tmp = Gf(var_indep) - D'*Gf(var_dep) with rGf ...\n";
      VectorSpace::vec_mut_ptr_t
        rGf_tmp = space_x->sub_space(var_indep)->create_member();
      *rGf_tmp = *Gf->sub_view(var_indep);
      Vp_MtV( rGf_tmp.get(), *D, BLAS_Cpp::trans, *Gf->sub_view(var_dep) );
      const value_type
        sum_rGf_tmp  = sum(*rGf_tmp),
        sum_rGf      = sum(*rGf);
      const value_type
        calc_err = ::fabs( ( sum_rGf_tmp - sum_rGf )/( ::fabs(sum_rGf_tmp) + ::fabs(sum_rGf) + small_num ) );
      if(out)
        *out
          << "\nrel_err(sum(rGf_tmp),sum(rGf)) = "
          << "rel_err(" << sum_rGf_tmp << "," << sum_rGf << ") = "
          << calc_err << endl;
      if( calc_err >= Gc_error_tol() ) {
        if(out)
          *out
            << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
        if(print_all_warnings)
          *out << "\nrGf_tmp =\n" << *rGf_tmp
             << "\nrGf =\n"   << *rGf;
        update_success( false, &success );
      }
      if( calc_err >= Gc_warning_tol() ) {
        if(out)
          *out
            << "\nWarning, above relative error exceeded Gc_warning_tol = "
            << Gc_warning_tol() << endl;
      }
    }
    else if( D ) {
      if(out)
        *out
          << "\nComparing rGf'*y with the finite difference product"
          << " fd_prod(f,[D*y;y]) for random vectors y ...\n";
      VectorSpace::vec_mut_ptr_t
        y  = space_x->sub_space(var_indep)->create_member(),
        t  = space_x->create_member();
      value_type max_warning_viol = 0.0;
      int num_warning_viol = 0;
      const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
      for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
        if( num_fd_directions() > 0 ) {
          random_vector( rand_y_l, rand_y_u, y.get() );
          if(out)
            *out
              << "\n****"
              << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = "
              << (y->norm_1() / y->dim()) << " )"
              << "\n***\n";
        }
        else {
          *y = 1.0;
          if(out)
            *out
              << "\n****"
              << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )"
              << "\n***\n";
        }
        // t = [ D*y; y ]
        LinAlgOpPack::V_MtV(&*t->sub_view(var_dep),*D,BLAS_Cpp::no_trans,*y);
        *t->sub_view(var_indep) = *y;
        value_type fd_rGf_y = 0.0;
        // fd_Gf_y
        preformed_fd = fd_deriv_prod.calc_deriv_product(
          xo,xl,xu
          ,*t,NULL,NULL,true,nlp,&fd_rGf_y,NULL,out,dump_all(),dump_all()
          );
        if( !preformed_fd )
          goto FD_NOT_PREFORMED;
        if(out) *out << "fd_prod(f,[D*y;y]) = " << fd_rGf_y << "\n";
        // rGf_y = rGf'*y
        const value_type rGf_y = dot(*rGf,*y);
        if(out) *out << "rGf'*y = " << rGf_y << "\n";
        // Compare fd_rGf_y and rGf*y
        const value_type
          calc_err = ::fabs( ( rGf_y - fd_rGf_y )/( ::fabs(rGf_y) + ::fabs(fd_rGf_y) + small_num ) );
        if( calc_err >= Gc_warning_tol() ) {
          max_warning_viol = my_max( max_warning_viol, calc_err );
          ++num_warning_viol;
        }
        if(out)
          *out
            << "\nrel_err(rGf'*y,fd_prod(f,[D*y;y])) = "
            << "rel_err(" << fd_rGf_y << "," << rGf_y << ") = "
            << calc_err << endl;
        if( calc_err >= Gf_error_tol() ) {
          if(out)
            *out << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
          if(print_all_warnings)
            *out << "\ny =\n" << *y
                 << "\nt = [ D*y; y ] =\n" << *t;
          update_success( false, &success );
        }
      }
    }
    else {
      TEST_FOR_EXCEPT(true); // ToDo: Test rGf without D? (This is not going to be easy!)
    }
  }
  
  // ///////////////////////////////////////////////////
  // (5) Check GcU, and/or Uz (for undecomposed equalities)

  if(GcU || Uz) {
    TEST_FOR_EXCEPT(true); // ToDo: Implement!
  }
  
FD_NOT_PREFORMED:

  if(!preformed_fd) {
    if(out)
      *out
        << "\nError, the finite difference computation was not preformed due to cramped bounds\n"
        << "Finite difference test failed!\n" << endl;
    return false;
  }

  } // end try
  catch( const AbstractLinAlgPack::NaNInfException& except ) {
    if(out)
      *out
        << "Error, found a NaN or Inf.  Stoping tests\n";
    success = false;
  }
  
  if( out ) {
    if( success )
      *out
        << "\nCongradulations, all the finite difference errors where within the\n"
        "specified error tolerances!\n";
    else
      *out
        << "\nOh no, at least one of the above finite difference tests failed!\n";
  }

  return success;

}
bool IterationPack::TestingPack::TestAlgorithmState(std::ostream* out) {

  using std::endl;
  using std::setw;
  using TestingHelperPack::update_success;

  try {

  bool success = true, result;
//	const int w = 15;
  if(out) *out << std::boolalpha;
    
  if(out)
    *out<< "\n\n******************************\n"
      << "*** Testing AlgorithmState ***\n"
      << "******************************\n"
      << "\nWarning: this interface is weakly typed and mistakes"
      << "can be very bad\n";

  typedef double													alpha_k_t;
  typedef std::vector<double>										x_k_t;
  typedef B														V_k_t;
  typedef IterQuantityAccessContiguous<alpha_k_t>					alpha_t;
  typedef IterQuantityAccessContiguous<x_k_t>						x_t;
  typedef IterQuantityAccessContiguous<V_k_t>						V_t;

  if(out) *out << "\n*** Create state object ...\n";
  AlgorithmState state(4);

  // Set three types of iteration quantity access objects.

  if(out) *out << "\n*** Set three types of iteration quantity access objects.\n";

  if(out) *out << "set IterQuantityAccessContiguous<double>(2,\"alpha\")\n";
  state.set_iter_quant( "alpha", Teuchos::rcp(
    new alpha_t(
      2,"alpha"
#ifdef _MIPS_CXX
      ,Teuchos::RCP<Teuchos::AbstractFactoryStd<alpha_k_t,alpha_k_t> >(
        new Teuchos::AbstractFactoryStd<alpha_k_t,alpha_k_t>())
#endif			
      )) );

  if(out) *out << "set IterQuantityAccessContiguous<std::vector<double> >(2,\"x\")\n";
  state.set_iter_quant( "x", Teuchos::rcp(
    new x_t(
      2,"x"
#ifdef _MIPS_CXX
      ,Teuchos::RCP<Teuchos::AbstractFactoryStd<x_k_t,x_k_t> >(
        new Teuchos::AbstractFactoryStd<x_k_t,x_k_t>())
#endif			
      )) );

  if(out) *out << "set IterQuantityAccessDerivedToBase<B,D>(1,\"V\")\n";
  state.set_iter_quant(
    "V"
    ,Teuchos::rcp(
      new V_t(
        1
        ,"V"
        ,Teuchos::rcp( new Teuchos::AbstractFactoryStd<V_k_t,D> )
        )
        )
    );

  // Try to add the same name again.

  if(out) *out << "\nTry to add \"x\" (should throw execption) : ";
  try {
    state.set_iter_quant( "x", Teuchos::rcp(
      new x_t(
        2,"x"
#ifdef _MIPS_CXX
        ,Teuchos::RCP<Teuchos::AbstractFactoryStd<x_k_t,x_k_t> >(
          new Teuchos::AbstractFactoryStd<x_k_t,x_k_t>())
#endif			
        )) );
    success = false;
    if(out)
      *out << "false\n";
  }
  catch(const AlgorithmState::AlreadyExists& expt) {
    if(out) *out << "Caught a AlgorithmState::AlreadyExists execption : " << expt.what() << " : true\n" << endl;
  }

  // dump the iteration quantity names, ids, and concrete types.

  if(out) {
    *out << "\n*** dump iteration quantitys\n";
    state.dump_iter_quant(*out);
  }

  update_success( result = state.k() == 0, &success );
  if(out) *out << "\nstate.k() == 0 : " << result << endl; 

  // Set the iteration quantities for the kth iteration and check them

  if(out) *out << "\n*** Set iteration quantities for the kth iteration\n";

  if(out) *out << "\nSet alpha_k(0) = 5.0 then get alpha_k(0) == 5.0 : ";
  alpha_t *alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
  alpha->set_k(0) = 5.0; 
  alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
  update_success( result = alpha->get_k(0) == 5.0, &success );
  if(out) *out << result << endl;

  if(out) *out << "\nSet x_k(0)[0] = 2.0 then get x_k(0)[0] == 2.0 : ";
  x_t *x = dynamic_cast<x_t*>( &state.iter_quant("x") );
  x->set_k(0).resize(1);
  x->set_k(0)[0] = 2.0;
  x = dynamic_cast<x_t*>( &state.iter_quant("x") );
  update_success( result = x->get_k(0)[0] == 2.0, &success );
  if(out) *out << result << endl;

  if(out) *out << "\nSet V_k(0).alpha() = 3.0 then get V_k(0).alpha() == 3.0 : ";
  V_t *V = dynamic_cast<V_t*>( &state.iter_quant("V") );
  V->set_k(0).alpha(3.0);
  V = dynamic_cast<V_t*>( &state.iter_quant("V") );
  update_success( result = V->get_k(0).alpha() == 3.0, &success );
  if(out) *out << result << endl;

  // Use an id to get at an iteration quantity.

  if(out) *out << "\n*** Use an id to get at an iteration quantity\n";

  if(out) *out << "\nid for \"x\" is : ";
  AlgorithmState::iq_id_type x_id = state.get_iter_quant_id("x");
  if(out) *out << x_id << endl;

  if(out) *out << "\nAccess \"x\" using id and x_k(0)[0] == 2.0 : ";
  x = dynamic_cast<x_t*>( &state.iter_quant(x_id) );
  update_success( result = x->get_k(0)[0] == 2.0, &success );
  if(out) *out << result << endl;

  // use a nonexistant name

  if(out) *out << "\n*** Use a nonexistant name or id to access iteration quantity\n";

  if(out) *out << "id for \"X\" is DOES_NOT_EXIST : ";
  update_success( result = state.get_iter_quant_id("X") == AlgorithmState::DOES_NOT_EXIST
    , & success );
  if(out) *out << result << endl;

  if(out) *out << "\nAccess nonexistant iteration quantity by name \"X\" throws a AlgorithmState::DoesNotExist exception : ";
  try {
    state.iter_quant("X");
    success = false;
    if(out) *out << false << endl;
  }
  catch(const AlgorithmState::DoesNotExist& expt) {
    if(out) *out << true << endl;
  }

  // use a nonexistant id

  if(out) *out << "\nUse of a nonexistant id = 100 throws a AlgorithmState::DoesNotExist exception : ";
  try {
    state.iter_quant(100);
    success = false;
    if(out) *out << false << endl;
  }
  catch(const AlgorithmState::DoesNotExist& expt) {
    if(out) *out << true << endl;
  }

  // update the iteration

  if(out) *out << "\n*** Update iteration quantities k+1 = k then check\n";

  if(out) *out << "alpha_k(+1) = alpha_k(0)...\n";
  alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
  {
    alpha_k_t &alpha_k = alpha->get_k(0);
    alpha->set_k(+1) = alpha_k;
  }

  if(out) *out << "x_k(+1) = x_k(0)...\n";
  x = dynamic_cast<x_t*>( &state.iter_quant("x") );
  {
    x_k_t &x_k = x->get_k(0);
    x->set_k(+1) = x_k;
  }

  if(out) *out << "V_k(+1) = V_k(0)...\n";
  V = dynamic_cast<V_t*>( &state.iter_quant("V") );
  {
    V_k_t &V_k = V->get_k(0);
    V->set_k(+1) = V_k;
  }

  if(out) *out << "shift reference from k to k+1...\n";
  state.next_iteration();

  if(out) *out << "\nalpha_k(-1) == 5.0 : ";
  alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
  update_success( result = alpha->get_k(-1) == 5.0, &success );
  if(out) *out << result << endl;
  if(out) *out << "alpha_k(0) == 5.0 : ";
  update_success( result = alpha->get_k(0) == 5.0, &success );
  if(out) *out << result << endl;

  if(out) *out << "\nx_k(-1)[0] == 2.0 : ";
  x = dynamic_cast<x_t*>( &state.iter_quant("x") );
  update_success( result = x->get_k(-1)[0] == 2.0, &success );
  if(out) *out << result << endl;
  if(out) *out << "x_k(0)[0] == 2.0 : ";
  update_success( result = x->get_k(0)[0] == 2.0, &success );
  if(out) *out << result << endl;

  if(out) *out << "\nV_k(0).alpha() == 3.0 : ";
  V = dynamic_cast<V_t*>( &state.iter_quant("V") );
  update_success( result = V->get_k(0).alpha() == 3.0, &success );
  if(out) *out << result << endl;

  // erase an iteration quantity then try to access it

  if(out) *out << "\n*** Erasing iteration quantity \"x\" then trying to access it throws"
          " a AlgorithmState::DoesNotExist exception : ";
  state.erase_iter_quant("x");
  try {
    state.iter_quant(x_id);
    if(out) *out << false << endl;
    update_success( false, &success );
  }
  catch(const AlgorithmState::DoesNotExist& expt) {
    if(out) *out << true << endl;
  }

  // final printout.

  if(out) {
    if(success) {
      *out << "\n*** Congradulations, all of the tests for AlgorihtmState"
          " returned the expected results\n";
    }
    else {
      *out << "\n*** Oops, at least one of the above tests for AlgorihtmState"
          " did not return the expected results ***\n";
    }
  }

  return success;

  } // end try
  catch(const std::exception& excpt) {
    if(out) *out << "\nCaught a std::exception: " << typeName(excpt) << " : " <<  excpt.what() << endl;
  }
  catch(...) {
    if(out) *out << "\nCaught an unknown exception\n";
  }

  if(out) *out << "\n*** Oops, If you read this some function throw an unexpected exception and the tests have failed!\n";

  return false;
}
bool NLPInterfacePack::test_nlp_direct(
  NLPDirect                                    *nlp
  ,OptionsFromStreamPack::OptionsFromStream    *options
  ,std::ostream                                *out
  )
{
  using TestingHelperPack::update_success;

  bool result;
  bool success = true;
  
  Teuchos::VerboseObjectTempState<NLP>
    nlpOutputTempState(Teuchos::rcp(nlp,false),Teuchos::getFancyOStream(Teuchos::rcp(out,false)),Teuchos::VERB_LOW);

  if(out)
    *out
      << "\n****************************"
      << "\n*** test_nlp_direct(...) ***"
      << "\n*****************************\n";
  
  nlp->initialize(true);

  // Test the DVector spaces
  if(out)
    *out << "\nTesting the vector spaces ...\n";
  
  VectorSpaceTester vec_space_tester;
  if(options) {
    VectorSpaceTesterSetOptions
      opt_setter(&vec_space_tester);
    opt_setter.set_options(*options);
  }

  if(out)
    *out << "\nTesting nlp->space_x() ...\n";
  result = vec_space_tester.check_vector_space(*nlp->space_x(),out);
  if(out) {
    if(result)
      *out << "nlp->space_x() checks out!\n";
    else
      *out << "nlp->space_x() check failed!\n";
  }
  update_success( result, &success );
  if(out)
    *out << "\nTesting nlp->space_x()->sub_space(nlp->var_dep()) ...\n";
  result = vec_space_tester.check_vector_space(
    *nlp->space_x()->sub_space(nlp->var_dep()),out);
  if(out) {
    if(result)
      *out << "nlp->space_x()->sub_space(nlp->var_dep()) checks out!\n";
    else
      *out << "nlp->space_x()->sub_space(nlp->var_dep()) check failed!\n";
  }
  update_success( result, &success );
  if(out)
    *out << "\nTesting nlp->space_x()->sub_space(nlp->var_indep()) ...\n";
  result = vec_space_tester.check_vector_space(
    *nlp->space_x()->sub_space(nlp->var_indep()),out);
  if(out) {
    if(result)
      *out << "nlp->space_x()->sub_space(nlp->var_indep()) checks out!\n";
    else
      *out << "nlp->space_x()->sub_space(nlp->var_indep()) check failed!\n";
  }
  update_success( result, &success );
  if(out)
    *out << "\nTesting nlp->space_c() ...\n";
  result = vec_space_tester.check_vector_space(*nlp->space_c(),out);
  if(out) {
    if(result)
      *out << "nlp->space_c() checks out!\n";
    else
      *out << "nlp->space_c() check failed!\n";
  }
  update_success( result, &success );
  if(out)
    *out << "\nTesting nlp->space_c()->sub_space(nlp->con_decomp()) ...\n";
  result = vec_space_tester.check_vector_space(
    *nlp->space_c()->sub_space(nlp->con_decomp()),out);
  if(out) {
    if(result)
      *out << "nlp->space_c()->sub_space(nlp->con_decomp()) checks out!\n";
    else
      *out << "nlp->space_c()->sub_space(nlp->con_decomp()) check failed!\n";
  }
  update_success( result, &success );
  if( nlp->con_decomp().size() < nlp->m() ) {
    if(out)
      *out << "\nTesting nlp->space_c()->sub_space(nlp->con_undecomp()) ...\n";
    result = vec_space_tester.check_vector_space(
      *nlp->space_c()->sub_space(nlp->con_undecomp()),out);
    if(out) {
      if(result)
        *out << "nlp->space_c()->sub_space(nlp->con_undecomp()) checks out!\n";
      else
        *out << "nlp->space_c()->sub_space(nlp->con_undecomp()) check failed!\n";
    }
    update_success( result, &success );
  }

  // Test the NLP interface first!

  NLPTester nlp_tester;
  if(options) {
    NLPTesterSetOptions
      nlp_tester_opt_setter(&nlp_tester);
    nlp_tester_opt_setter.set_options(*options);
  }
  const bool print_all_warnings = nlp_tester.print_all();

  result = nlp_tester.test_interface(
    nlp, nlp->xinit(), print_all_warnings, out );
  update_success( result, &success );
  
  // Test the NLPDirect interface now!

  const bool supports_Gf = nlp->supports_Gf();

  if(out)
    *out << "\nCalling nlp->calc_point(...) at nlp->xinit() ...\n";
  const size_type
    n  = nlp->n(),
    m  = nlp->m();
  const Range1D
    var_dep      = nlp->var_dep(),
    var_indep    = nlp->var_indep(),
    con_decomp   = nlp->con_decomp(),
    con_undecomp = nlp->con_undecomp();
  VectorSpace::vec_mut_ptr_t
    c   =      nlp->space_c()->create_member(),
    Gf  =      nlp->space_x()->create_member(),
    py  =      nlp->space_x()->sub_space(var_dep)->create_member(),
    rGf =      nlp->space_x()->sub_space(var_indep)->create_member();
  NLPDirect::mat_fcty_ptr_t::element_type::obj_ptr_t
    GcU = con_decomp.size() < m ? nlp->factory_GcU()->create() : Teuchos::null,
    D   =                         nlp->factory_D()->create(),
    Uz   = con_decomp.size() < m ? nlp->factory_Uz()->create()   : Teuchos::null;
  nlp->calc_point(
    nlp->xinit(), NULL, c.get(), true, supports_Gf?Gf.get():NULL, py.get(), rGf.get()
    ,GcU.get(), D.get(), Uz.get() );
  if(out) {
    if(supports_Gf) {
      *out << "\n||Gf||inf  = " << Gf->norm_inf();
      if(nlp_tester.print_all())
        *out << "\nGf =\n" << *Gf;
    }
    *out << "\n||py||inf  = " << py->norm_inf();
    if(nlp_tester.print_all())
      *out << "\npy =\n" << *py;
    *out << "\n||rGf||inf  = " << rGf->norm_inf();
    if(nlp_tester.print_all())
      *out << "\nrGf =\n" << *rGf;
    if(nlp_tester.print_all())
      *out << "\nD =\n" << *D;
    if( con_decomp.size() < m ) {
      TEST_FOR_EXCEPT(true); // ToDo: Print GcU and Uz
    }
    *out << "\n";
  }

  CalcFiniteDiffProd
    calc_fd_prod;
  if(options) {
    CalcFiniteDiffProdSetOptions
      options_setter( &calc_fd_prod );
    options_setter.set_options(*options);
  }
  NLPDirectTester
    nlp_first_order_direct_tester(Teuchos::rcp(&calc_fd_prod,false));
  if(options) {
    NLPDirectTesterSetOptions
      nlp_tester_opt_setter(&nlp_first_order_direct_tester);
    nlp_tester_opt_setter.set_options(*options);
  }
  result = nlp_first_order_direct_tester.finite_diff_check(
    nlp, nlp->xinit()
    ,nlp->num_bounded_x() ? &nlp->xl() : NULL
    ,nlp->num_bounded_x() ? &nlp->xu() : NULL
    ,c.get()
    ,supports_Gf?Gf.get():NULL,py.get(),rGf.get(),GcU.get(),D.get(),Uz.get()
    ,print_all_warnings, out
    );
  update_success( result, &success );

  return success;
}
bool NLPInterfacePack::test_nlp_first_order(
  NLPFirstOrder                                 *nlp
  ,OptionsFromStreamPack::OptionsFromStream     *options
  ,std::ostream                                 *out
  )
{
  namespace rcp = MemMngPack;
  using TestingHelperPack::update_success;

  bool result;
  bool success = true;
  
  Teuchos::VerboseObjectTempState<NLP>
    nlpOutputTempState(Teuchos::rcp(nlp,false),Teuchos::getFancyOStream(Teuchos::rcp(out,false)),Teuchos::VERB_LOW);

  if(out)
    *out << "\n*********************************"
         << "\n*** test_nlp_first_order(...) ***"
         << "\n*********************************\n";
  
  nlp->initialize(true);

  // Test the DVector spaces
  if(out)
    *out << "\nTesting the vector spaces ...\n";
  
  VectorSpaceTester vec_space_tester;
  if(options) {
    VectorSpaceTesterSetOptions
      opt_setter(&vec_space_tester);
    opt_setter.set_options(*options);
  }

  if(out)
    *out << "\nTesting nlp->space_x() ...\n";
  result = vec_space_tester.check_vector_space(*nlp->space_x(),out);
  if(out) {
    if(result)
      *out << "nlp->space_x() checks out!\n";
    else
      *out << "nlp->space_x() check failed!\n";
  }
  update_success( result, &success );

  if( nlp->m() ) {
    if(out)
      *out << "\nTesting nlp->space_c() ...\n";
    result = vec_space_tester.check_vector_space(*nlp->space_c(),out);
    if(out) {
      if(result)
        *out << "nlp->space_c() checks out!\n";
      else
        *out << "nlp->space_c() check failed!\n";
    }
    update_success( result, &success );
  }

  // Test the NLP interface first!

  NLPTester nlp_tester;
  if(options) {
    NLPTesterSetOptions
      nlp_tester_opt_setter(&nlp_tester);
    nlp_tester_opt_setter.set_options(*options);
  }
  const bool print_all_warnings = nlp_tester.print_all();

  result = nlp_tester.test_interface(
    nlp, nlp->xinit(), print_all_warnings, out );
  update_success( result, &success );
  
  // Test the NLPFirstOrder interface now!

  const size_type
    n  = nlp->n(),
    m  = nlp->m();
  VectorSpace::vec_mut_ptr_t
    c   = m  ? nlp->space_c()->create_member() : Teuchos::null,
    Gf  =      nlp->space_x()->create_member();
  NLPFirstOrder::mat_fcty_ptr_t::element_type::obj_ptr_t
    Gc  = m  ? nlp->factory_Gc()->create() : Teuchos::null;

  if(m) {
    if(out)
      *out << "\nCalling nlp->calc_Gc(...) at nlp->xinit() ...\n";
    nlp->set_Gc( Gc.get() );
    nlp->calc_Gc( nlp->xinit(), true );
    if(nlp_tester.print_all()) {
      *out << "\nGc =\n" << *Gc;
    }
  }

  if(out)
    *out << "\nCalling nlp->calc_Gf(...) at nlp->xinit() ...\n";
  nlp->set_Gf( Gf.get() );
  nlp->calc_Gf( nlp->xinit(), m == 0 );
  if(nlp_tester.print_all())
    *out << "\nGf =\n" << *Gf;

  CalcFiniteDiffProd
    calc_fd_prod;
  if(options) {
    CalcFiniteDiffProdSetOptions
      options_setter( &calc_fd_prod );
    options_setter.set_options(*options);
  }
  NLPFirstDerivTester
    nlp_first_derivatives_tester(Teuchos::rcp(&calc_fd_prod,false));
  if(options) {
    NLPFirstDerivTesterSetOptions
      nlp_tester_opt_setter(&nlp_first_derivatives_tester);
    nlp_tester_opt_setter.set_options(*options);
  }
  result = nlp_first_derivatives_tester.finite_diff_check(
    nlp, nlp->xinit()
    ,nlp->num_bounded_x() ? &nlp->xl() : NULL
    ,nlp->num_bounded_x() ? &nlp->xu() : NULL
    ,Gc.get(), Gf.get()
    ,print_all_warnings, out
    );
  update_success( result, &success );

  return success;
}