BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
uBLAS has a shallow_array_adaptor that allows you to wrap an existing block of data with a uBLAS vector. This is useful if you want to wrap raw data provided by someone else. Exposing this functionality is questionable in terms of encapsulation and ownership, and so it isn't available by default. Consequently the documentation is pretty scarce. Here's an example of it's use in the context of a Boost.Test test case.
#define BOOST_TEST_MODULE $Id: test_complex.cc 1817 2009-03-18 19:01:25Z rhys $
// Before ublas #include, enable boost::numeric::ublas::shallow_array_adaptor<T>
#define BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 1
#include <algorithm>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/foreach.hpp>
#include <complex>
namespace ublas = boost::numeric::ublas;
typedef std::complex<double> complex;
typedef ublas::shallow_array_adaptor<double> shallow_adaptor_double;
typedef ublas::vector<double, shallow_adaptor_double> shallow_vector_double;
typedef ublas::shallow_array_adaptor<complex> shallow_adaptor_complex;
typedef ublas::vector<complex, shallow_adaptor_complex> shallow_vector_complex;
// Ensure we can use std::complex<double> as two consecutive doubles
BOOST_AUTO_TEST_CASE( shared_c_array )
{
// Assumption must hold true for any of this scheme to work
BOOST_REQUIRE_EQUAL( sizeof(complex), 2*sizeof(double) );
const std::size_t N = 6;
double carray_double[N] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
complex *carray_complex = reinterpret_cast<complex *>(carray_double);
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(carray_double[2*i], carray_complex[i].real());
BOOST_CHECK_EQUAL(carray_double[2*i+1], carray_complex[i].imag());
}
for (std::size_t i = 0; i < N/2; ++i)
{
carray_complex[i] += carray_complex[0];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(carray_double[2*i], carray_complex[i].real());
BOOST_CHECK_EQUAL(carray_double[2*i+1], carray_complex[i].imag());
}
}
// Ensure we can use a C-array of doubles as a ublas::vector.
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_double )
{
const std::size_t N = 3;
double raw[N];
shallow_adaptor_double adaptor(N, raw);
shallow_vector_double vec(N, adaptor);
BOOST_CHECK_EQUAL( vec.size(), N );
std::fill(&raw[0], &raw[N], 1.0);
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
std::fill(vec.begin(), vec.end(), 2.0);
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
}
// Ensure we can use a C-array of std::complex<double> as a ublas::vector.
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_complex )
{
const std::size_t N = 3;
complex raw[N];
shallow_adaptor_complex adaptor(N, raw);
shallow_vector_complex vec(N, adaptor);
BOOST_CHECK_EQUAL( vec.size(), N );
std::fill(&raw[0], &raw[N], complex(1.0, -1.0));
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
std::fill(vec.begin(), vec.end(), complex(2.0, -2.0));
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
}
// Ensure we can use the same data as either double or complex ublas::vector
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_shared )
{
const std::size_t N = 6;
double carray_double[N] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
complex *carray_complex = reinterpret_cast<complex *>(carray_double);
shallow_adaptor_double adaptor_double(N, carray_double);
shallow_vector_double vec_double(N, adaptor_double);
shallow_adaptor_complex adaptor_complex(N, carray_complex);
shallow_vector_complex vec_complex(N, adaptor_complex);
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
for (std::size_t i = 0; i < N/2; ++i)
{
vec_complex[i] += vec_complex[0];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
for (std::size_t i = 0; i < N; ++i)
{
vec_double[i] += vec_double[N-1];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
}
// Before ublas #include, enable boost::numeric::ublas::shallow_array_adaptor<T>
#define BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 1
#include <algorithm>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/foreach.hpp>
#include <complex>
namespace ublas = boost::numeric::ublas;
typedef std::complex<double> complex;
typedef ublas::shallow_array_adaptor<double> shallow_adaptor_double;
typedef ublas::vector<double, shallow_adaptor_double> shallow_vector_double;
typedef ublas::shallow_array_adaptor<complex> shallow_adaptor_complex;
typedef ublas::vector<complex, shallow_adaptor_complex> shallow_vector_complex;
// Ensure we can use std::complex<double> as two consecutive doubles
BOOST_AUTO_TEST_CASE( shared_c_array )
{
// Assumption must hold true for any of this scheme to work
BOOST_REQUIRE_EQUAL( sizeof(complex), 2*sizeof(double) );
const std::size_t N = 6;
double carray_double[N] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
complex *carray_complex = reinterpret_cast<complex *>(carray_double);
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(carray_double[2*i], carray_complex[i].real());
BOOST_CHECK_EQUAL(carray_double[2*i+1], carray_complex[i].imag());
}
for (std::size_t i = 0; i < N/2; ++i)
{
carray_complex[i] += carray_complex[0];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(carray_double[2*i], carray_complex[i].real());
BOOST_CHECK_EQUAL(carray_double[2*i+1], carray_complex[i].imag());
}
}
// Ensure we can use a C-array of doubles as a ublas::vector.
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_double )
{
const std::size_t N = 3;
double raw[N];
shallow_adaptor_double adaptor(N, raw);
shallow_vector_double vec(N, adaptor);
BOOST_CHECK_EQUAL( vec.size(), N );
std::fill(&raw[0], &raw[N], 1.0);
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
std::fill(vec.begin(), vec.end(), 2.0);
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
}
// Ensure we can use a C-array of std::complex<double> as a ublas::vector.
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_complex )
{
const std::size_t N = 3;
complex raw[N];
shallow_adaptor_complex adaptor(N, raw);
shallow_vector_complex vec(N, adaptor);
BOOST_CHECK_EQUAL( vec.size(), N );
std::fill(&raw[0], &raw[N], complex(1.0, -1.0));
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
std::fill(vec.begin(), vec.end(), complex(2.0, -2.0));
BOOST_CHECK_EQUAL_COLLECTIONS(&raw[0], &raw[N], vec.begin(), vec.end());
}
// Ensure we can use the same data as either double or complex ublas::vector
BOOST_AUTO_TEST_CASE( shallow_array_adaptor_shared )
{
const std::size_t N = 6;
double carray_double[N] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
complex *carray_complex = reinterpret_cast<complex *>(carray_double);
shallow_adaptor_double adaptor_double(N, carray_double);
shallow_vector_double vec_double(N, adaptor_double);
shallow_adaptor_complex adaptor_complex(N, carray_complex);
shallow_vector_complex vec_complex(N, adaptor_complex);
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
for (std::size_t i = 0; i < N/2; ++i)
{
vec_complex[i] += vec_complex[0];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
for (std::size_t i = 0; i < N; ++i)
{
vec_double[i] += vec_double[N-1];
}
for (std::size_t i = 0; i < N/2; ++i)
{
BOOST_CHECK_EQUAL(vec_double[2*i], vec_complex[i].real());
BOOST_CHECK_EQUAL(vec_double[2*i+1], vec_complex[i].imag());
}
}
No comments:
Post a Comment