2
0
mirror of https://github.com/boostorg/ublas.git synced 2026-02-21 03:22:14 +00:00

Merge branch 'feature/ublas00002_fixed_matrix' into ublas_develop

This commit is contained in:
nasos
2014-04-11 23:54:18 -04:00
11 changed files with 2192 additions and 111 deletions

View File

@@ -59,4 +59,5 @@ SOURCES += \
../../../test/num_columns.cpp \
../../../test/concepts.cpp \
../../../test/comp_mat_erase.cpp \
../../../test/begin_end.cpp
../../../test/begin_end.cpp \
../../../test/test_fixed_containers.cpp

View File

@@ -170,7 +170,7 @@ BOOST_UBLAS_INLINE vector_move_manip<T> move(T i) {
*
* \todo Doxygen has some problems with similar template functions. Correct that.
*/
template <std::size_t I>
template <std::ptrdiff_t I>
class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
public:
template <typename V>
@@ -198,8 +198,8 @@ public:
*
* \todo Doxygen has some problems with similar template functions. Correct that.
*/
template <std::size_t I>
BOOST_UBLAS_INLINE static_vector_move_manip<I> move() {
template <std::ptrdiff_t I>
static_vector_move_manip<I> move() {
return static_vector_move_manip<I>();
}
@@ -269,7 +269,7 @@ BOOST_UBLAS_INLINE matrix_move_to_manip<T> move_to(T i, T j) {
*
* \todo Doxygen has some problems with similar template functions. Correct that.
*/
template <std::size_t I, std::size_t J>
template <std::size_t I,std::size_t J>
class static_matrix_move_to_manip: public index_manipulator<static_matrix_move_to_manip<I, J> > {
public:
template <typename V, typename K>
@@ -369,7 +369,7 @@ BOOST_UBLAS_INLINE matrix_move_manip<T> move(T i, T j) {
*
* \todo Doxygen has some problems with similar template functions. Correct that.
*/
template <std::size_t I, std::size_t J>
template <std::ptrdiff_t I, std::ptrdiff_t J>
class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
public:
template <typename V, typename K>
@@ -407,7 +407,7 @@ public:
*
* \todo Doxygen has some problems with similar template functions. Correct that.
*/
template <std::size_t I, std::size_t J>
template <std::ptrdiff_t I, std::ptrdiff_t J>
BOOST_UBLAS_INLINE static_matrix_move_manip<I, J> move() {
return static_matrix_move_manip<I, J>();
}
@@ -804,7 +804,7 @@ namespace traverse_policy {
l++; j++;
if (l>=e().size2()) {
l=0; k++; j=j0; i++;
// It is assumed that the iteration starts from 0 and happens only using this function from within
// It is assumed that the iteration starts from 0 and progresses only using this function from within
// an assigner object.
// Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
// outside the if statement.
@@ -850,7 +850,7 @@ namespace traverse_policy {
k++; i++;
if (k>=e().size1()) {
k=0; l++; i=i0; j++;
// It is assumed that the iteration starts from 0 and happens only using this function from within
// It is assumed that the iteration starts from 0 and progresses only using this function from within
// an assigner object.
// Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
// outside the if statement.

View File

@@ -190,11 +190,11 @@ namespace boost { namespace numeric { namespace ublas {
BOOST_UBLAS_INLINE
compressed_matrix_view(const compressed_matrix_view& o) :
size1_(size1_), size2_(size2_),
nnz_(nnz_),
index1_data_(index1_data_),
index2_data_(index2_data_),
value_data_(value_data_)
size1_(o.size1_), size2_(o.size2_),
nnz_(o.nnz_),
index1_data_(o.index1_data_),
index2_data_(o.index2_data_),
value_data_(o.value_data_)
{}
//

View File

@@ -17,6 +17,10 @@
#include <memory>
#ifdef BOOST_UBLAS_CPP11
#include <array>
#endif
namespace boost { namespace numeric { namespace ublas {
// Storage types
@@ -88,6 +92,10 @@ namespace boost { namespace numeric { namespace ublas {
template<class T, class A = unbounded_array<T> >
class vector;
#ifdef BOOST_UBLAS_CPP11
template<class T, std::size_t N, class A = std::array<T, N> >
class fixed_vector;
#endif
template<class T, std::size_t N>
class bounded_vector;
@@ -125,6 +133,10 @@ namespace boost { namespace numeric { namespace ublas {
template<class T, class L = row_major, class A = unbounded_array<T> >
class matrix;
#ifdef BOOST_UBLAS_CPP11
template<class T, std::size_t M, std::size_t N, class L = row_major, class A = std::array<T, M*N> >
class fixed_matrix;
#endif
template<class T, std::size_t M, std::size_t N, class L = row_major>
class bounded_matrix;

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_float.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/mpl/and.hpp>
// anonymous namespace to avoid ADL issues
@@ -36,23 +37,120 @@ namespace {
// we'll find either std::sqrt or else another version via ADL:
return sqrt (t);
}
template<class T> T boost_numeric_ublas_abs (const T& t) {
using namespace std;
// template<class T> T boost_numeric_ublas_abs (const T& t) {
// using namespace std;
// we'll find either std::abs or else another version via ADL:
return abs (t);
}
// return abs (t);
// }
template<typename T>
typename boost::disable_if<
boost::is_unsigned<T>, T >::type
inline boost_numeric_ublas_abs (const T &t ) {
using namespace std;
return abs( t );
}
// unsigned types are always non-negative
template<> unsigned int boost_numeric_ublas_abs (const unsigned int& t) {
return t;
}
//template<> inline unsigned int boost_numeric_ublas_abs (const unsigned int& t) {
// return t;
//}
// unsigned types are always non-negative
template<> unsigned long boost_numeric_ublas_abs (const unsigned long& t) {
return t;
}
//template<> inline unsigned long boost_numeric_ublas_abs (const unsigned long& t) {
// return t;
//}
template<typename T>
typename boost::enable_if<
boost::is_unsigned<T>, T >::type
inline boost_numeric_ublas_abs (const T &t ) {
return t;
}
}
namespace boost { namespace numeric { namespace ublas {
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
return R (in1) + in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
return in1 + R (in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
return R (in1) - in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
return in1 - R (in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
return R (in1) * in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
return in1 * R(in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
return R(in1) / in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
return in1 / R (in2);
}
// Use Joel de Guzman's return type deduction
// uBLAS assumes a common return type for all binary arithmetic operators
template<class X, class Y>
@@ -73,86 +171,6 @@ namespace boost { namespace numeric { namespace ublas {
typedef typename id::type promote_type;
};
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
return R (in1) + in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
return in1 + R (in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
return R (in1) - in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
return in1 - R (in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
return R (in1) * in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
return in1 * R(in2);
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
return R(in1) / in2;
}
template<typename R, typename I>
typename boost::enable_if<
mpl::and_<
boost::is_float<R>,
boost::is_integral<I>
>,
std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
return in1 / R (in2);
}
// Type traits - generic numeric properties and functions

View File

@@ -1,6 +1,7 @@
//
// Copyright (c) 2000-2010
// Joerg Walter, Mathias Koch, David Bellot
// Copyright (c) 2014, Athanasios Iliopoulos
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -22,6 +23,10 @@
#include <boost/serialization/collection_size_type.hpp>
#include <boost/serialization/nvp.hpp>
#ifdef BOOST_UBLAS_CPP11
#include <array>
#include <initializer_list>
#endif
// Iterators based on ideas of Jeremy Siek
@@ -793,6 +798,753 @@ namespace boost { namespace numeric { namespace ublas {
};
#ifdef BOOST_UBLAS_CPP11
/** \brief A dense vector of values of type \c T.
*
* For a \f$n\f$-dimensional vector \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped
* to the \f$i\f$-th element of the container. A storage type \c A can be specified which defaults to \c std::array.
* Elements are constructed by \c A, which need not initialise their value.
*
* \tparam T type of the objects stored in the vector (like int, double, complex,...)
* \tparam A The type of the storage array of the vector. Default is \c std::array<T>.
*/
template<class T, std::size_t N, class A>
class fixed_vector:
public vector_container<fixed_vector<T, N, A> > {
typedef fixed_vector<T, N, A> self_type;
public:
#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
using vector_container<self_type>::operator ();
#endif
typedef typename A::size_type size_type;
typedef typename A::difference_type difference_type;
typedef T value_type;
typedef typename type_traits<T>::const_reference const_reference;
typedef T &reference;
typedef T *pointer;
typedef const T *const_pointer;
typedef A array_type;
typedef const vector_reference<const self_type> const_closure_type;
typedef vector_reference<self_type> closure_type;
typedef self_type vector_temporary_type;
typedef dense_tag storage_category;
// Construction and destruction
/// \brief Constructor of a fixed_vector
BOOST_UBLAS_INLINE
fixed_vector ():
vector_container<self_type> (),
data_ () {}
/// \brief Constructor of a fixed_vector by copying from another container
/// This type has the generic name \c array_typ within the vector definition.
/// \param data container of type \c A
BOOST_UBLAS_INLINE
fixed_vector (const array_type &data):
vector_container<self_type> (),
data_ (data) {}
/// \brief Constructor of a fixed_vector with a predefined size and a unique initial value
/// \param init value to assign to each element of the vector
BOOST_UBLAS_INLINE
fixed_vector (const value_type &init):
vector_container<self_type> (),
data_ () {
data_.fill( init );
}
/// \brief Copy-constructor of a fixed_vector
/// \param v is the fixed_vector to be duplicated
BOOST_UBLAS_INLINE
fixed_vector (const fixed_vector &v):
vector_container<self_type> (),
data_ (v.data_) {}
/// \brief Copy-constructor of a vector from a vector_expression
/// Depending on the vector_expression, this constructor can have the cost of the computations
/// of the expression (trivial to say it, but it is to take into account in your complexity calculations).
/// \param ae the vector_expression which values will be duplicated into the vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector (const vector_expression<AE> &ae):
vector_container<self_type> (),
data_ ( ) {
vector_assign<scalar_assign> (*this, ae);
}
/// \brief Construct a fixed_vector from a list of values
/// The list should be included in curly braces. Typical syntax is:
/// fixed_vector<double, 3> v = { 1, 2, 3 } or fixed_vector<double,3> v( {1, 2, 3} ) or fixed_vector<double,3> v( 1, 2, 3 )
template <typename... Types>
fixed_vector(value_type v0, Types... vrest) :
vector_container<self_type> (),
data_{ { v0, vrest... } } {}
// -----------------------
// Random Access Container
// -----------------------
/// \brief Return the maximum size of the data container.
/// Return the upper bound (maximum size) on the data container. Depending on the container, it can be bigger than the current size of the vector.
BOOST_UBLAS_INLINE
size_type max_size () const {
return data_.max_size ();
}
/// \brief Return true if the vector is empty (\c size==0)
/// \return \c true if empty, \c false otherwise
BOOST_UBLAS_INLINE
const bool &empty () const {
return data_.empty();
}
// ---------
// Accessors
// ---------
/// \brief Return the size of the vector
BOOST_UBLAS_INLINE
constexpr size_type size () const{ // should have a const after C++14
return data_.size ();
}
// -----------------
// Storage accessors
// -----------------
/// \brief Return a \c const reference to the container. Useful to access data directly for specific type of container.
BOOST_UBLAS_INLINE
const array_type &data () const {
return data_;
}
/// \brief Return a reference to the container. Useful to speed-up write operations to the data in very specific case.
BOOST_UBLAS_INLINE
array_type &data () {
return data_;
}
// ---------------
// Element support
// ---------------
/// \brief Return a pointer to the element \f$i\f$
/// \param i index of the element
// XXX this semantic is not the one expected by the name of this method
BOOST_UBLAS_INLINE
pointer find_element (size_type i) {
return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
}
/// \brief Return a const pointer to the element \f$i\f$
/// \param i index of the element
// XXX this semantic is not the one expected by the name of this method
BOOST_UBLAS_INLINE
const_pointer find_element (size_type i) const {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); // Since std:array doesn't check for bounds
return & (data () [i]);
}
// --------------
// Element access
// --------------
/// \brief Return a const reference to the element \f$i\f$
/// Return a const reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
/// \param i index of the element
BOOST_UBLAS_INLINE
const_reference operator () (size_type i) const {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
return data () [i];
}
/// \brief Return a reference to the element \f$i\f$
/// Return a reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
/// \param i index of the element
BOOST_UBLAS_INLINE
reference operator () (size_type i) {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
return data () [i];
}
/// \brief Return a const reference to the element \f$i\f$
/// \param i index of the element
BOOST_UBLAS_INLINE
const_reference operator [] (size_type i) const {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
return (*this) (i);
}
/// \brief Return a reference to the element \f$i\f$
/// \param i index of the element
BOOST_UBLAS_INLINE
reference operator [] (size_type i) {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
return (*this) (i);
}
// ------------------
// Element assignment
// ------------------
/// \brief Set element \f$i\f$ to the value \c t
/// \param i index of the element
/// \param t reference to the value to be set
// XXX semantic of this is to insert a new element and therefore size=size+1 ?
BOOST_UBLAS_INLINE
reference insert_element (size_type i, const_reference t) {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index ());
return (data () [i] = t);
}
/// \brief Set element \f$i\f$ to the \e zero value
/// \param i index of the element
BOOST_UBLAS_INLINE
void erase_element (size_type i) {
BOOST_UBLAS_CHECK (i < data_.size(), bad_index ());
data () [i] = value_type/*zero*/();
}
// -------
// Zeroing
// -------
/// \brief Clear the vector, i.e. set all values to the \c zero value.
BOOST_UBLAS_INLINE
void clear () {
std::fill (data ().begin (), data ().end (), value_type/*zero*/());
}
// Assignment
#ifdef BOOST_UBLAS_MOVE_SEMANTICS
/// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
/// \param v is the source vector
/// \return a reference to a fixed_vector (i.e. the destination vector)
/*! @note "pass by value" the key idea to enable move semantics */
BOOST_UBLAS_INLINE
fixed_vector &operator = (fixed_vector v) {
assign_temporary(v);
return *this;
}
#else
/// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
/// \param v is the source vector
/// \return a reference to a vector (i.e. the destination vector)
BOOST_UBLAS_INLINE
fixed_vector &operator = (const fixed_vector &v) {
data () = v.data ();
return *this;
}
#endif
/// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
/// Assign a full vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector). This method does not create any temporary.
/// \param v is the source vector container
/// \return a reference to a vector (i.e. the destination vector)
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
fixed_vector &operator = (const vector_container<C> &v) {
assign (v);
return *this;
}
/// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
/// \param v is the source vector
/// \return a reference to a vector (i.e. the destination vector)
BOOST_UBLAS_INLINE
fixed_vector &assign_temporary (fixed_vector &v) {
swap ( v );
return *this;
}
/// \brief Assign the result of a vector_expression to the vector
/// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &operator = (const vector_expression<AE> &ae) {
self_type temporary (ae);
return assign_temporary (temporary);
}
/// \brief Assign the result of a vector_expression to the vector
/// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &assign (const vector_expression<AE> &ae) {
vector_assign<scalar_assign> (*this, ae);
return *this;
}
// -------------------
// Computed assignment
// -------------------
/// \brief Assign the sum of the vector and a vector_expression to the vector
/// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// A temporary is created for the computations.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &operator += (const vector_expression<AE> &ae) {
self_type temporary (*this + ae);
return assign_temporary (temporary);
}
/// \brief Assign the sum of the vector and a vector_expression to the vector
/// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
fixed_vector &operator += (const vector_container<C> &v) {
plus_assign (v);
return *this;
}
/// \brief Assign the sum of the vector and a vector_expression to the vector
/// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &plus_assign (const vector_expression<AE> &ae) {
vector_assign<scalar_plus_assign> (*this, ae);
return *this;
}
/// \brief Assign the difference of the vector and a vector_expression to the vector
/// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// A temporary is created for the computations.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &operator -= (const vector_expression<AE> &ae) {
self_type temporary (*this - ae);
return assign_temporary (temporary);
}
/// \brief Assign the difference of the vector and a vector_expression to the vector
/// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class C> // Container assignment without temporary
BOOST_UBLAS_INLINE
fixed_vector &operator -= (const vector_container<C> &v) {
minus_assign (v);
return *this;
}
/// \brief Assign the difference of the vector and a vector_expression to the vector
/// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param ae is a const reference to the vector_expression
/// \return a reference to the resulting vector
template<class AE>
BOOST_UBLAS_INLINE
fixed_vector &minus_assign (const vector_expression<AE> &ae) {
vector_assign<scalar_minus_assign> (*this, ae);
return *this;
}
/// \brief Assign the product of the vector and a scalar to the vector
/// Assign the product of the vector and a scalar to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param at is a const reference to the scalar
/// \return a reference to the resulting vector
template<class AT>
BOOST_UBLAS_INLINE
fixed_vector &operator *= (const AT &at) {
vector_assign_scalar<scalar_multiplies_assign> (*this, at);
return *this;
}
/// \brief Assign the division of the vector by a scalar to the vector
/// Assign the division of the vector by a scalar to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
/// No temporary is created. Computations are done and stored directly into the resulting vector.
/// \tparam AE is the type of the vector_expression
/// \param at is a const reference to the scalar
/// \return a reference to the resulting vector
template<class AT>
BOOST_UBLAS_INLINE
fixed_vector &operator /= (const AT &at) {
vector_assign_scalar<scalar_divides_assign> (*this, at);
return *this;
}
// --------
// Swapping
// --------
/// \brief Swap the content of the vector with another vector
/// \param v is the vector to be swapped with
BOOST_UBLAS_INLINE
void swap (fixed_vector &v) {
if (this != &v) {
data ().swap (v.data ());
}
}
/// \brief Swap the content of two vectors
/// \param v1 is the first vector. It takes values from v2
/// \param v2 is the second vector It takes values from v1
BOOST_UBLAS_INLINE
friend void swap (fixed_vector &v1, fixed_vector &v2) {
v1.swap (v2);
}
// Iterator types
private:
// Use the storage array iterator
typedef typename A::const_iterator const_subiterator_type;
typedef typename A::iterator subiterator_type;
public:
#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
typedef indexed_iterator<self_type, dense_random_access_iterator_tag> iterator;
typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator;
#else
class const_iterator;
class iterator;
#endif
// --------------
// Element lookup
// --------------
/// \brief Return a const iterator to the element \e i
/// \param i index of the element
BOOST_UBLAS_INLINE
const_iterator find (size_type i) const {
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
return const_iterator (*this, data ().begin () + i);
#else
return const_iterator (*this, i);
#endif
}
/// \brief Return an iterator to the element \e i
/// \param i index of the element
BOOST_UBLAS_INLINE
iterator find (size_type i) {
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
return iterator (*this, data ().begin () + i);
#else
return iterator (*this, i);
#endif
}
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
class const_iterator:
public container_const_reference<fixed_vector>,
public random_access_iterator_base<dense_random_access_iterator_tag,
const_iterator, value_type, difference_type> {
public:
typedef typename fixed_vector::difference_type difference_type;
typedef typename fixed_vector::value_type value_type;
typedef typename fixed_vector::const_reference reference;
typedef const typename fixed_vector::pointer pointer;
// ----------------------------
// Construction and destruction
// ----------------------------
BOOST_UBLAS_INLINE
const_iterator ():
container_const_reference<self_type> (), it_ () {}
BOOST_UBLAS_INLINE
const_iterator (const self_type &v, const const_subiterator_type &it):
container_const_reference<self_type> (v), it_ (it) {}
BOOST_UBLAS_INLINE
const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here
container_const_reference<self_type> (it ()), it_ (it.it_) {}
// ----------
// Arithmetic
// ----------
/// \brief Increment by 1 the position of the iterator
/// \return a reference to the const iterator
BOOST_UBLAS_INLINE
const_iterator &operator ++ () {
++ it_;
return *this;
}
/// \brief Decrement by 1 the position of the iterator
/// \return a reference to the const iterator
BOOST_UBLAS_INLINE
const_iterator &operator -- () {
-- it_;
return *this;
}
/// \brief Increment by \e n the position of the iterator
/// \return a reference to the const iterator
BOOST_UBLAS_INLINE
const_iterator &operator += (difference_type n) {
it_ += n;
return *this;
}
/// \brief Decrement by \e n the position of the iterator
/// \return a reference to the const iterator
BOOST_UBLAS_INLINE
const_iterator &operator -= (difference_type n) {
it_ -= n;
return *this;
}
/// \brief Return the different in number of positions between 2 iterators
BOOST_UBLAS_INLINE
difference_type operator - (const const_iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ - it.it_;
}
/// \brief Dereference an iterator
/// Dereference an iterator: a bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
/// \return a const reference to the value pointed by the iterator
BOOST_UBLAS_INLINE
const_reference operator * () const {
BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
return *it_;
}
/// \brief Dereference an iterator at the n-th forward value
/// Dereference an iterator at the n-th forward value, that is the value pointed by iterator+n.
/// A bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
/// \return a const reference
BOOST_UBLAS_INLINE
const_reference operator [] (difference_type n) const {
return *(it_ + n);
}
// Index
/// \brief return the index of the element referenced by the iterator
BOOST_UBLAS_INLINE
size_type index () const {
BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
return it_ - (*this) ().begin ().it_;
}
// Assignment
BOOST_UBLAS_INLINE
/// \brief assign the value of an iterator to the iterator
const_iterator &operator = (const const_iterator &it) {
container_const_reference<self_type>::assign (&it ());
it_ = it.it_;
return *this;
}
// Comparison
/// \brief compare the value of two itetarors
/// \return true if they reference the same element
BOOST_UBLAS_INLINE
bool operator == (const const_iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ == it.it_;
}
/// \brief compare the value of two iterators
/// \return return true if the left-hand-side iterator refers to a value placed before the right-hand-side iterator
BOOST_UBLAS_INLINE
bool operator < (const const_iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ < it.it_;
}
private:
const_subiterator_type it_;
friend class iterator;
};
#endif
/// \brief return an iterator on the first element of the vector
BOOST_UBLAS_INLINE
const_iterator begin () const {
return find (0);
}
/// \brief return an iterator after the last element of the vector
BOOST_UBLAS_INLINE
const_iterator end () const {
return find (data_.size ());
}
#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
class iterator:
public container_reference<fixed_vector>,
public random_access_iterator_base<dense_random_access_iterator_tag,
iterator, value_type, difference_type> {
public:
typedef typename fixed_vector::difference_type difference_type;
typedef typename fixed_vector::value_type value_type;
typedef typename fixed_vector::reference reference;
typedef typename fixed_vector::pointer pointer;
// Construction and destruction
BOOST_UBLAS_INLINE
iterator ():
container_reference<self_type> (), it_ () {}
BOOST_UBLAS_INLINE
iterator (self_type &v, const subiterator_type &it):
container_reference<self_type> (v), it_ (it) {}
// Arithmetic
BOOST_UBLAS_INLINE
iterator &operator ++ () {
++ it_;
return *this;
}
BOOST_UBLAS_INLINE
iterator &operator -- () {
-- it_;
return *this;
}
BOOST_UBLAS_INLINE
iterator &operator += (difference_type n) {
it_ += n;
return *this;
}
BOOST_UBLAS_INLINE
iterator &operator -= (difference_type n) {
it_ -= n;
return *this;
}
BOOST_UBLAS_INLINE
difference_type operator - (const iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ - it.it_;
}
// Dereference
BOOST_UBLAS_INLINE
reference operator * () const {
BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
return *it_;
}
BOOST_UBLAS_INLINE
reference operator [] (difference_type n) const {
return *(it_ + n);
}
// Index
BOOST_UBLAS_INLINE
size_type index () const {
BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
return it_ - (*this) ().begin ().it_;
}
// Assignment
BOOST_UBLAS_INLINE
iterator &operator = (const iterator &it) {
container_reference<self_type>::assign (&it ());
it_ = it.it_;
return *this;
}
// Comparison
BOOST_UBLAS_INLINE
bool operator == (const iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ == it.it_;
}
BOOST_UBLAS_INLINE
bool operator < (const iterator &it) const {
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
return it_ < it.it_;
}
private:
subiterator_type it_;
friend class const_iterator;
};
#endif
/// \brief Return an iterator on the first element of the vector
BOOST_UBLAS_INLINE
iterator begin () {
return find (0);
}
/// \brief Return an iterator at the end of the vector
BOOST_UBLAS_INLINE
iterator end () {
return find (data_.size ());
}
// Reverse iterator
typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
typedef reverse_iterator_base<iterator> reverse_iterator;
/// \brief Return a const reverse iterator before the first element of the reversed vector (i.e. end() of normal vector)
BOOST_UBLAS_INLINE
const_reverse_iterator rbegin () const {
return const_reverse_iterator (end ());
}
/// \brief Return a const reverse iterator on the end of the reverse vector (i.e. first element of the normal vector)
BOOST_UBLAS_INLINE
const_reverse_iterator rend () const {
return const_reverse_iterator (begin ());
}
/// \brief Return a const reverse iterator before the first element of the reversed vector (i.e. end() of normal vector)
BOOST_UBLAS_INLINE
reverse_iterator rbegin () {
return reverse_iterator (end ());
}
/// \brief Return a const reverse iterator on the end of the reverse vector (i.e. first element of the normal vector)
BOOST_UBLAS_INLINE
reverse_iterator rend () {
return reverse_iterator (begin ());
}
// -------------
// Serialization
// -------------
/// Serialize a vector into and archive as defined in Boost
/// \param ar Archive object. Can be a flat file, an XML file or any other stream
/// \param file_version Optional file version (not yet used)
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
ar & serialization::make_nvp("data",data_);
}
private:
array_type data_;
};
#endif // BOOST_UBLAS_CPP11
// --------------------
// Bounded vector class
// --------------------
@@ -867,6 +1619,7 @@ namespace boost { namespace numeric { namespace ublas {
};
// -----------------
// Zero vector class
// -----------------
@@ -1597,13 +2350,13 @@ namespace boost { namespace numeric { namespace ublas {
c_vector (size_type size):
size_ (size) /* , data_ () */ {
if (size_ > N)
bad_size ().raise ();
bad_size ().raise ();
}
BOOST_UBLAS_INLINE
c_vector (const c_vector &v):
size_ (v.size_) /* , data_ () */ {
if (size_ > N)
bad_size ().raise ();
bad_size ().raise ();
assign(v);
}
template<class AE>
@@ -1611,7 +2364,7 @@ namespace boost { namespace numeric { namespace ublas {
c_vector (const vector_expression<AE> &ae):
size_ (ae ().size ()) /* , data_ () */ {
if (size_ > N)
bad_size ().raise ();
bad_size ().raise ();
vector_assign<scalar_assign> (*this, ae);
}
@@ -1633,7 +2386,7 @@ namespace boost { namespace numeric { namespace ublas {
BOOST_UBLAS_INLINE
void resize (size_type size, bool preserve = true) {
if (size > N)
bad_size ().raise ();
bad_size ().raise ();
size_ = size;
}
@@ -1782,7 +2535,7 @@ namespace boost { namespace numeric { namespace ublas {
BOOST_UBLAS_INLINE
void swap (c_vector &v) {
if (this != &v) {
BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ());
BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ());
std::swap (size_, v.size_);
std::swap_ranges (data_, data_ + size_, v.data_);
}

View File

@@ -212,4 +212,9 @@ test-suite numeric/uBLAS
:
:
]
[ run test_fixed_containers.cpp
:
:
: <toolset>gcc:<cxxflags>-std=c++11 <toolset>clang:<cxxflags>-std=c++11 <toolset>intel:<cxxflags>-std=c++11 <define>BOOST_UBLAS_CPP11
]
;

View File

@@ -8,6 +8,9 @@
#define _HPP_TESTHELPER_
#include <utility>
#include <iostream>
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>
static unsigned _success_counter = 0;
static unsigned _fail_counter = 0;
@@ -43,7 +46,7 @@ void assertEquals(const char* message, T expected, T actual) {
}
}
static
inline static
std::pair<unsigned, unsigned> getResults() {
return std::make_pair(_success_counter, _fail_counter);
}

View File

@@ -807,5 +807,5 @@ int main () {
BOOST_UBLAS_TEST_END();
return EXIT_SUCCESS;;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,304 @@
#undef BOOST_UBLAS_NO_EXCEPTIONS
#include "common/testhelper.hpp"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/assignment.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <string>
#include <sstream>
#include <complex>
#include <iomanip>
#include "utils.hpp"
using namespace boost::numeric::ublas;
using std::cout;
using std::endl;
template < class T >
bool test_vector( std::string type_name)
{
std::stringstream stream;
stream << "Testing for: " << type_name;
BOOST_UBLAS_DEBUG_TRACE( stream.str() );
bool pass = true;
{
typedef fixed_vector<T, 1> vec1;
vec1 v1( 122.0 );
pass &= ( v1(0) == (T)122 );
}
{
typedef fixed_vector<T, 3> vec3;
vec3 v1((T)0.0, (T)0.0, (T)0.0);
pass &=(sizeof( vec3 ) == v1.size()*sizeof( T ) ) ;
vector<T> v( 3, 0 ) ;
pass &= compare( v1, v );
v1 <<= 10.0, 10, 33;
v <<= 10.0, 10, 33;
//cout << std::setprecision(20) << v1 << '\n' << v;
pass &= compare( v1, v );
vec3 v2;
v2( 0 ) = 10.0; v2( 1 ) = 10; v2( 2 ) = 33;
pass &= compare( v, v2 );
v2 += v;
pass &= compare( v2, 2*v );
v1 = 2*v1 + v - 6*v2;
pass &= compare( v1, (3-2*6)*v );
vec3 v3{ (T)-90.0, (T)-90.0, (T)-297.0 };
pass &= compare( v3, v1 );
vec3 v4 = { (T)-90.0, (T)-90.0, (T)-297.0 };
pass &= compare( v4, v1 );
vec3 v5( (T)-90.0, (T)-90.0, (T)-297.0 );
pass &= compare( v5, v1 );
vec3 v6((T) 5.0, (T)8.0, (T)9.0);
matrix<T> M = outer_prod( v6, v6), L( 3, 3);
L <<= 25, 40, 45, 40, 64, 72, 45, 72, 81;
pass &= compare( M, L );
L <<= 1, 2, 3, 4, 5, 6, 7, 8, 9;
v6 <<= 4, 5, 6;
vec3 v7 ( (T)32.0, (T)77.0, (T)122.0 );
pass &= compare( v7, prod(L, v6) );
vec3 v8;
noalias( v8 ) = prod(L, v6);
pass &= compare( v7, v8 );
}
{
const std::size_t N = 33;
typedef fixed_vector<T, N> vec33;
vec33 v1;
vector<T> v( N );
for ( std::size_t i = 0; i!= v1.size(); i++)
{
v1( i ) = 3.14159*i*i;
v ( i ) = 3.14159*i*i;
}
pass &= compare( v1, v );
auto ip = inner_prod( v, v);
auto ip1 = inner_prod( v1, v1);
pass &= ( ip == ip1 ) ;
T c = 0;
for (auto i = v1.begin(); i != v1.end(); i++)
{
*i = c;
c = c + 1;
}
c = 0;
for (auto i = v.begin(); i != v.end(); i++)
{
*i = c;
c = c + 1;
}
pass &= compare( v1, v );
// Check if bad index indeed works
try {
T a;
a=v1( 100 );
(void) a ;
} catch ( bad_index &e) {
std::cout << " Caught: " << e.what() << endl;
pass &= true;
}
}
return pass;
}
template < class T >
bool test_matrix( std::string type_name)
{
std::stringstream stream;
stream << "Testing for: " << type_name;
BOOST_UBLAS_DEBUG_TRACE( stream.str() );
bool pass = true;
typedef fixed_matrix<T, 3, 4> mat34;
typedef fixed_matrix<T, 4, 3> mat43;
typedef fixed_matrix<T, 3, 3> mat33;
{
typedef fixed_matrix<T, 1, 1> mat1;
mat1 m1( 122.0 );
pass &= ( m1(0, 0) == (T)122 );
}
{
mat34 m1( 3.0 );
pass &=(sizeof( mat34 ) == m1.size1()*m1.size2()*sizeof( T ) ) ;
matrix<T> m( 3.0, 4.0, 3.0 ) ;
pass &= compare( m1, m );
cout << m1 << endl;
cout << m << endl;
m1 <<= 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
m <<= 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
pass &= compare( m1, m );
cout << m1 << endl;
cout << m << endl;
mat34 m2( 0.0 );
T count = 1 ;
for ( std::size_t i = 0; i != m2.size1(); i++)
{
for (std::size_t j = 0; j!= m2.size2(); j++)
{
m2( i, j ) = count;
count = count + 1;
}
}
pass &= compare( m2, m );
cout << m2 << endl;
}
{
mat34 m1 = { (T)1, (T)2, (T)3, (T)3, (T)3, (T)2, (T)5, (T)4, (T)2, (T)6, (T)5, (T)2 };
mat43 m2 = { (T)4, (T)5, (T)6, (T)3, (T)2, (T)2, (T)1, (T)4, (T)2, (T)6, (T)5, (T)2 };
mat33 m3 = prod(m1, m2);
matrix<double> m(3, 3);
m <<= 31,36,22,47,59,40,43,52,38;
pass &= compare(m ,m3);
mat33 m4;
m4 <<= (T)1, (T)2, (T)1, (T)2, (T)1, (T)3, (T)1, (T)2, (T) 5;
m3 = prod(m4, trans(m4));
m<<=6,7,10,7,14,19,10,19,30;
cout << m3 << endl;
pass &= compare(m ,m3);
m3 = 2 * m4 - 1 * m3;
cout << m3;
m <<= -4,-3,-8,-3,-12,-13,-8,-15,-20;
pass &= compare(m, m3);
m = m3;
m3 = trans(m);
pass &= compare(m3, trans(m));
// Check if bad index indeed works
try {
T a;
a=m1( 100, 100 );
(void) a ;
} catch ( bad_index &e) {
std::cout << " Caught: " << e.what() << endl;
pass &= true;
}
}
return pass;
}
BOOST_UBLAS_TEST_DEF (test_vector) {
BOOST_UBLAS_DEBUG_TRACE( "Starting fixed container tests" );
BOOST_UBLAS_TEST_CHECK( test_vector< double >( "double") );
BOOST_UBLAS_TEST_CHECK( test_vector< float >( "float") );
BOOST_UBLAS_TEST_CHECK( test_vector< int >( "int") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<double> >( "std::complex<double>") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<float> >( "std::complex<float>") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<int> >( "std::complex<int>") );
BOOST_UBLAS_TEST_CHECK( test_matrix< double >( "double") );
BOOST_UBLAS_TEST_CHECK( test_vector< float >( "float") );
BOOST_UBLAS_TEST_CHECK( test_vector< int >( "int") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<double> >( "std::complex<double>") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<float> >( "std::complex<float>") );
BOOST_UBLAS_TEST_CHECK( test_vector< std::complex<int> >( "std::complex<int>") );
}
int main () {
#ifdef BOOST_UBLAS_NO_EXCEPTIONS
std::cout << "DEFINED SDFSDF SDF SDF " << std::endl;
#endif
BOOST_UBLAS_TEST_BEGIN();
BOOST_UBLAS_TEST_DO( test_vector );
BOOST_UBLAS_TEST_END();
return EXIT_SUCCESS;
}