// | |
// Copyright (c) 2000-2002 | |
// Joerg Walter, Mathias Koch | |
// | |
// Distributed under the Boost Software License, Version 1.0. (See | |
// accompanying file LICENSE_1_0.txt or copy at | |
// http://www.boost.org/LICENSE_1_0.txt) | |
// | |
// The authors gratefully acknowledge the support of | |
// GeNeSys mbH & Co. KG in producing this work. | |
// | |
#ifndef _BOOST_UBLAS_DEFINITIONS_ | |
#define _BOOST_UBLAS_DEFINITIONS_ | |
namespace boost { namespace numeric { namespace ublas { | |
namespace detail { | |
/* Borrowed from boost/concept_checks.hpp | |
"inline" is used for ignore_unused_variable_warning() | |
to make sure there is no overhead with g++. | |
*/ | |
template <class T> inline | |
void ignore_unused_variable_warning(const T&) {} | |
} // namespace detail | |
// Borrowed from Dave Abraham's noncopyable. | |
// I believe this should be part of utility.hpp one day... | |
namespace nonassignable_ // protection from unintended ADL | |
{ | |
class nonassignable { | |
protected: | |
nonassignable () {} | |
~nonassignable () {} | |
private: // emphasize the following members are private | |
const nonassignable& operator= (const nonassignable &); | |
}; // nonassignable | |
} | |
typedef nonassignable_::nonassignable nonassignable; | |
// Assignment proxy. | |
// Provides temporary free assigment when LHS has no alias on RHS | |
template<class C> | |
class noalias_proxy: | |
private nonassignable { | |
public: | |
typedef typename C::closure_type closure_type; | |
BOOST_UBLAS_INLINE | |
noalias_proxy (C& lval): | |
nonassignable (), lval_ (lval) {} | |
BOOST_UBLAS_INLINE | |
noalias_proxy (const noalias_proxy& p): | |
nonassignable (), lval_ (p.lval_) {} | |
template <class E> | |
BOOST_UBLAS_INLINE | |
closure_type &operator= (const E& e) { | |
lval_.assign (e); | |
return lval_; | |
} | |
template <class E> | |
BOOST_UBLAS_INLINE | |
closure_type &operator+= (const E& e) { | |
lval_.plus_assign (e); | |
return lval_; | |
} | |
template <class E> | |
BOOST_UBLAS_INLINE | |
closure_type &operator-= (const E& e) { | |
lval_.minus_assign (e); | |
return lval_; | |
} | |
private: | |
closure_type lval_; | |
}; | |
// Improve syntax of efficient assignment where no aliases of LHS appear on the RHS | |
// noalias(lhs) = rhs_expression | |
template <class C> | |
BOOST_UBLAS_INLINE | |
noalias_proxy<C> noalias (C& lvalue) { | |
return noalias_proxy<C> (lvalue); | |
} | |
template <class C> | |
BOOST_UBLAS_INLINE | |
noalias_proxy<const C> noalias (const C& lvalue) { | |
return noalias_proxy<const C> (lvalue); | |
} | |
// Possible future compatible syntax where lvalue possible has an unsafe alias on the RHS | |
// safe(lhs) = rhs_expression | |
template <class C> | |
BOOST_UBLAS_INLINE | |
C& safe (C& lvalue) { | |
return lvalue; | |
} | |
template <class C> | |
BOOST_UBLAS_INLINE | |
const C& safe (const C& lvalue) { | |
return lvalue; | |
} | |
// Dimension accessors | |
namespace dimension { | |
// Generic accessors | |
template<unsigned dimension> | |
struct dimension_properties {}; | |
template<> | |
struct dimension_properties<1> { | |
template <class E> | |
BOOST_UBLAS_INLINE static | |
typename E::size_type size (const vector_expression<E> &e) { | |
return e ().size (); | |
} | |
template <class E> | |
BOOST_UBLAS_INLINE static | |
typename E::size_type size (const matrix_expression<E> &e) { | |
return e ().size1 (); | |
} | |
// Note: Index functions cannot deduce dependant template parameter V or M from i | |
template <class V> | |
BOOST_UBLAS_INLINE static | |
typename V::size_type index (const typename V::iterator &i) { | |
return i.index (); | |
} | |
template <class M> | |
BOOST_UBLAS_INLINE static | |
typename M::size_type index (const typename M::iterator1 &i) { | |
return i.index1 (); | |
} | |
template <class M> | |
BOOST_UBLAS_INLINE static | |
typename M::size_type index (const typename M::iterator2 &i) { | |
return i.index1 (); | |
} | |
}; | |
template<> | |
struct dimension_properties<2> { | |
template <class E> | |
BOOST_UBLAS_INLINE static | |
typename E::size_type size (const vector_expression<E> &) { | |
return 1; | |
} | |
template <class E> | |
BOOST_UBLAS_INLINE static | |
typename E::size_type size (const matrix_expression<E> &e) { | |
return e ().size2 (); | |
} | |
template <class V> | |
BOOST_UBLAS_INLINE static | |
typename V::size_type index (const typename V::iterator &) { | |
return 1; | |
} | |
template <class M> | |
BOOST_UBLAS_INLINE static | |
typename M::size_type index (const typename M::iterator1 &i) { | |
return i.index2 (); | |
} | |
template <class M> | |
BOOST_UBLAS_INLINE static | |
typename M::size_type index (const typename M::iterator2 &i) { | |
return i.index2 (); | |
} | |
}; | |
template<unsigned dimension, class E> | |
BOOST_UBLAS_INLINE | |
typename E::size_type size (const E& e) { | |
return dimension_properties<dimension>::size (e); | |
} | |
template<unsigned dimension, class I> | |
BOOST_UBLAS_INLINE | |
typename I::container_type::size_type | |
index (const I& i) { | |
typedef typename I::container_type container_type; | |
return dimension_properties<dimension>::template index<container_type> (i); | |
} | |
// Named accessors - just syntactic sugar | |
template<class V> | |
typename V::size_type num_elements (const V &v) { | |
return v.size (); | |
} | |
template<class M> | |
typename M::size_type num_rows (const M &m) { | |
return m.size1 (); | |
} | |
template<class M> | |
typename M::size_type num_columns (const M &m) { | |
return m.size2 (); | |
} | |
template<class MV> | |
typename MV::size_type num_non_zeros (const MV &mv) { | |
return mv.non_zeros (); | |
} | |
} | |
}}} | |
#endif |