Purpose
This is an example and test of the features of the
CppAD_vector
class that are not included in the
SimpleVector
concept.
# include <cppad/utility/vector.hpp>
# include <cppad/utility/error_handler.hpp>
# include <cppad/utility/check_simple_vector.hpp>
# include <sstream> // sstream and string are used to test output operation# include <string>
# include <algorithm>
namespace {
void myhandler(
bool known ,
int line ,
const char *file ,
const char *exp ,
const char *msg )
{ // error handler must not return, so throw an exceptionthrow std::string( file );
}
}
bool CppAD_vector(void)
{ bool ok = true;
using CppAD::vector; // so can use vector instead of CppAD::vectortypedef double Scalar; // change double to test other types// check Simple Vector specifications
CppAD::CheckSimpleVector< Scalar, vector<Scalar> >();
// check constructor with size_t and with an int
size_t two_s = 2;
int two_i = 2;
vector<Scalar> vec(2), other(two_s), another(two_i);
// assignment returns reference for use in other assignments
another[0] = Scalar(1);
another[1] = Scalar(2);
vec = other = another;
for(size_t i = 0; i < 2; ++i)
{ ok &= vec[i] == other[i];
ok &= vec[i] == another[i];
}
// test of output
std::string correct= "{ 1, 2 }";
std::string str;
std::ostringstream buf;
buf << vec;
str = buf.str();
ok &= (str == correct);
// swap
other[0] = vec[0] + 1;
vec.swap(other);
ok &= vec[0] == other[0] + 1;
// clear
vec.clear();
ok &= vec.size() == 0;
ok &= vec.capacity() == 0;
// push_back scalar and changes in capacity
size_t n = 100;
size_t old_capacity = vec.capacity();
for(size_t i = 0; i < n; i++)
{ vec.push_back( Scalar(n - i) );
ok &= (i+1) == vec.size();
ok &= i < vec.capacity();
ok &= old_capacity == vec.capacity() || i == old_capacity;
old_capacity = vec.capacity();
}
for(size_t i = 0; i < n; i++)
ok &= ( vec[i] == Scalar(n - i) );
// test of push_vector
vec.push_vector(vec);
ok &= (vec.size() == 2 * n);
for(size_t i = 0; i < n; i++)
{ ok &= vec[i] == Scalar(n - i);
ok &= vec[i + n] == Scalar(n - i);
}
// resize perserves elements when new size less than capacity
ok &= n < vec.capacity();
vec.resize(n);
for(size_t i = 0; i < n; i++)
ok &= vec[i] == Scalar(n - i);
// vector assignment OK when target has size zero
other.resize(0);
other = vec;
// create a const vector equal to vecconst vector<Scalar> cvec = vec;
// sort of vec (will reverse order of elements for this case)
std::sort(vec.begin(), vec.end());
for(size_t i = 0; i < n ; ++i)
ok &= vec[i] == Scalar(i + 1);
// use data pointer to sort using pointers instead of iterators
std::sort(other.data(), other.data() + other.size());
for(size_t i = 0; i < n ; ++i)
ok &= other[i] == Scalar(i + 1);
// test direct use of iterator and const_iteratortypedef vector<Scalar>::iterator iterator;
typedef vector<Scalar>::const_iterator const_iterator;
iterator itr = vec.begin(); // increasing order
const_iterator citr = cvec.end(); // decreasing orderwhile( itr != vec.end() )
{ --citr;
ok &= *itr == *citr;
++itr;
}
// conversion from iterator to const_iterator
citr = vec.begin();
ok &= *citr == vec[0];
// Replace the default CppAD error handler with myhandler (defined above).// This replacement is in effect until info drops out of scope.
CppAD::ErrorHandler info(myhandler);
# ifndef NDEBUG
// -----------------------------------------------------------------------// check that size mismatch throws an exception when NDEBUG not defined
other.resize(0);
bool detected_error = false;
try
{ another = other; }
catch(const std::string& file)
{ // This location for the error is not part of user API and may change
size_t pos = file.find("/vector.hpp");
ok &= pos != std::string::npos;
detected_error = true;
}
ok &= detected_error;
// -----------------------------------------------------------------------// check that iterator access out of range generates an error
itr = vec.begin();
ok &= *itr == Scalar(1); // this access OK
detected_error = false;
try
{ vec.clear();
// The iterator knows that the vector has changed and that// this access is no longer valid
*itr;
}
catch(const std::string& file)
{ // This location for the error is not part of user API and may change
size_t pos = file.find("/cppad_vector_itr.hpp");
ok &= pos != std::string::npos;
detected_error = true;
}
ok &= detected_error;
// -----------------------------------------------------------------------# endifreturn ok;
}