--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_BOUNDS_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_BOUNDS_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/bounds.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class N>
+struct bounds : boundsdetail::get_impl<N>::type
+{} ;
+
+} } // namespace boost::numeric
+
+#endif
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+//
+// Revision History
+//
+// 19 Nov 2001 Syntatic changes as suggested by Darin Adler (Fernando Cacciola)
+// 08 Nov 2001 Fixes to accommodate MSVC (Fernando Cacciola)
+// 04 Nov 2001 Fixes to accommodate gcc2.92 (Fernando Cacciola)
+// 30 Oct 2001 Some fixes suggested by Daryle Walker (Fernando Cacciola)
+// 25 Oct 2001 Initial boostification (Fernando Cacciola)
+// 23 Jan 2004 Inital add to cvs (post review)s
+// 22 Jun 2011 Added support for specializing cast policies via numeric_cast_traits (Brandon Kohn).
+//
+#ifndef BOOST_NUMERIC_CONVERSION_CAST_25OCT2001_HPP
+#define BOOST_NUMERIC_CONVERSION_CAST_25OCT2001_HPP
+
+#include <boost/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+
+# include<boost/numeric/conversion/detail/old_numeric_cast.hpp>
+
+#else
+
+#include <boost/type.hpp>
+#include <boost/numeric/conversion/converter.hpp>
+#include <boost/numeric/conversion/numeric_cast_traits.hpp>
+
+namespace boost
+{
+ template <typename Target, typename Source>
+ inline Target numeric_cast( Source arg )
+ {
+ typedef numeric::conversion_traits<Target, Source> conv_traits;
+ typedef numeric::numeric_cast_traits<Target, Source> cast_traits;
+ typedef boost::numeric::converter
+ <
+ Target,
+ Source,
+ conv_traits,
+ typename cast_traits::overflow_policy,
+ typename cast_traits::rounding_policy,
+ boost::numeric::raw_converter< conv_traits >,
+ typename cast_traits::range_checking_policy
+ > converter;
+ return converter::convert(arg);
+ }
+
+ using numeric::bad_numeric_cast;
+} // namespace boost
+
+#endif
+
+#endif
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_CONVERSION_TRAITS_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_CONVERSION_TRAITS_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/conversion_traits.hpp"
+#include "boost/detail/workaround.hpp"
+#include "boost/config.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class T, class S>
+struct conversion_traits
+ : convdetail::get_conversion_traits<T,S>::type
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ typedef typename convdetail::get_conversion_traits<T,S>::type base_;
+ typedef typename base_::target_type target_type;
+ typedef typename base_::source_type source_type;
+ typedef typename base_::result_type result_type;
+ typedef typename base_::argument_type argument_type;
+#endif
+} ;
+
+} } // namespace boost::numeric
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_CONVERTER_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_CONVERTER_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/conversion_traits.hpp"
+#include "boost/numeric/conversion/converter_policies.hpp"
+
+#include "boost/numeric/conversion/detail/converter.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class T,
+ class S,
+ class Traits = conversion_traits<T,S>,
+ class OverflowHandler = def_overflow_handler,
+ class Float2IntRounder = Trunc< BOOST_DEDUCED_TYPENAME Traits::source_type> ,
+ class RawConverter = raw_converter<Traits>,
+ class UserRangeChecker = UseInternalRangeChecker
+ >
+struct converter : convdetail::get_converter_impl<Traits,
+ OverflowHandler,
+ Float2IntRounder,
+ RawConverter,
+ UserRangeChecker
+ >::type
+{
+ typedef Traits traits ;
+
+ typedef typename Traits::argument_type argument_type ;
+ typedef typename Traits::result_type result_type ;
+
+ result_type operator() ( argument_type s ) const { return this->convert(s) ; }
+} ;
+
+
+
+template<class S,
+ class OverflowHandler = def_overflow_handler,
+ class Float2IntRounder = Trunc<S> ,
+ class UserRangeChecker = UseInternalRangeChecker
+ >
+struct make_converter_from
+{
+ template<class T,
+ class Traits = conversion_traits<T,S>,
+ class RawConverter = raw_converter<Traits>
+ >
+ struct to
+ {
+ typedef converter<T,S,Traits,OverflowHandler,Float2IntRounder,RawConverter,UserRangeChecker> type ;
+ } ;
+
+} ;
+
+} } // namespace boost::numeric
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
+
+#include <typeinfo> // for std::bad_cast
+
+#include <boost/config/no_tr1/cmath.hpp> // for std::floor and std::ceil
+
+#include <functional>
+
+#include "boost/type_traits/is_arithmetic.hpp"
+
+#include "boost/mpl/if.hpp"
+#include "boost/mpl/integral_c.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class S>
+struct Trunc
+{
+ typedef S source_type ;
+
+ typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
+
+ static source_type nearbyint ( argument_type s )
+ {
+#if !defined(BOOST_NO_STDC_NAMESPACE)
+ using std::floor ;
+ using std::ceil ;
+#endif
+
+ return s < static_cast<S>(0) ? ceil(s) : floor(s) ;
+ }
+
+ typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
+} ;
+
+
+
+template<class S>
+struct Floor
+{
+ typedef S source_type ;
+
+ typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
+
+ static source_type nearbyint ( argument_type s )
+ {
+#if !defined(BOOST_NO_STDC_NAMESPACE)
+ using std::floor ;
+#endif
+
+ return floor(s) ;
+ }
+
+ typedef mpl::integral_c< std::float_round_style, std::round_toward_neg_infinity> round_style ;
+} ;
+
+template<class S>
+struct Ceil
+{
+ typedef S source_type ;
+
+ typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
+
+ static source_type nearbyint ( argument_type s )
+ {
+#if !defined(BOOST_NO_STDC_NAMESPACE)
+ using std::ceil ;
+#endif
+
+ return ceil(s) ;
+ }
+
+ typedef mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style ;
+} ;
+
+template<class S>
+struct RoundEven
+{
+ typedef S source_type ;
+
+ typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
+
+ static source_type nearbyint ( argument_type s )
+ {
+ // Algorithm contributed by Guillaume Melquiond
+
+#if !defined(BOOST_NO_STDC_NAMESPACE)
+ using std::floor ;
+ using std::ceil ;
+#endif
+
+ // only works inside the range not at the boundaries
+ S prev = floor(s);
+ S next = ceil(s);
+
+ S rt = (s - prev) - (next - s); // remainder type
+
+ S const zero(0.0);
+ S const two(2.0);
+
+ if ( rt < zero )
+ return prev;
+ else if ( rt > zero )
+ return next;
+ else
+ {
+ bool is_prev_even = two * floor(prev / two) == prev ;
+ return ( is_prev_even ? prev : next ) ;
+ }
+ }
+
+ typedef mpl::integral_c< std::float_round_style, std::round_to_nearest> round_style ;
+} ;
+
+
+enum range_check_result
+{
+ cInRange = 0 ,
+ cNegOverflow = 1 ,
+ cPosOverflow = 2
+} ;
+
+class bad_numeric_cast : public std::bad_cast
+{
+ public:
+
+ virtual const char * what() const throw()
+ { return "bad numeric conversion: overflow"; }
+};
+
+class negative_overflow : public bad_numeric_cast
+{
+ public:
+
+ virtual const char * what() const throw()
+ { return "bad numeric conversion: negative overflow"; }
+};
+class positive_overflow : public bad_numeric_cast
+{
+ public:
+
+ virtual const char * what() const throw()
+ { return "bad numeric conversion: positive overflow"; }
+};
+
+struct def_overflow_handler
+{
+ void operator() ( range_check_result r ) // throw(negative_overflow,positive_overflow)
+ {
+ if ( r == cNegOverflow )
+ throw negative_overflow() ;
+ else if ( r == cPosOverflow )
+ throw positive_overflow() ;
+ }
+} ;
+
+struct silent_overflow_handler
+{
+ void operator() ( range_check_result ) {} // throw()
+} ;
+
+template<class Traits>
+struct raw_converter
+{
+ typedef typename Traits::result_type result_type ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static result_type low_level_convert ( argument_type s ) { return static_cast<result_type>(s) ; }
+} ;
+
+struct UseInternalRangeChecker {} ;
+
+} } // namespace boost::numeric
+
+#endif
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_BOUNDS_DETAIL_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_BOUNDS_DETAIL_FLC_12NOV2002_HPP
+
+#include "boost/limits.hpp"
+#include "boost/config.hpp"
+#include "boost/mpl/if.hpp"
+
+namespace boost { namespace numeric { namespace boundsdetail
+{
+ template<class N>
+ class Integral
+ {
+ typedef std::numeric_limits<N> limits ;
+
+ public :
+
+ static N lowest () { return limits::min BOOST_PREVENT_MACRO_SUBSTITUTION (); }
+ static N highest () { return limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
+ static N smallest() { return static_cast<N>(1); }
+ } ;
+
+ template<class N>
+ class Float
+ {
+ typedef std::numeric_limits<N> limits ;
+
+ public :
+
+ static N lowest () { return static_cast<N>(-limits::max BOOST_PREVENT_MACRO_SUBSTITUTION ()) ; }
+ static N highest () { return limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
+ static N smallest() { return limits::min BOOST_PREVENT_MACRO_SUBSTITUTION (); }
+ } ;
+
+ template<class N>
+ struct get_impl
+ {
+ typedef mpl::bool_< ::std::numeric_limits<N>::is_integer > is_int ;
+
+ typedef Integral<N> impl_int ;
+ typedef Float <N> impl_float ;
+
+ typedef typename mpl::if_<is_int,impl_int,impl_float>::type type ;
+ } ;
+
+} } } // namespace boost::numeric::boundsdetail.
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERSION_TRAITS_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERSION_TRAITS_FLC_12NOV2002_HPP
+
+#include "boost/type_traits/is_arithmetic.hpp"
+#include "boost/type_traits/is_same.hpp"
+#include "boost/type_traits/remove_cv.hpp"
+
+#include "boost/numeric/conversion/detail/meta.hpp"
+#include "boost/numeric/conversion/detail/int_float_mixture.hpp"
+#include "boost/numeric/conversion/detail/sign_mixture.hpp"
+#include "boost/numeric/conversion/detail/udt_builtin_mixture.hpp"
+#include "boost/numeric/conversion/detail/is_subranged.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ //-------------------------------------------------------------------
+ // Implementation of the Conversion Traits for T != S
+ //
+ // This is a VISIBLE base class of the user-level conversion_traits<> class.
+ //-------------------------------------------------------------------
+ template<class T,class S>
+ struct non_trivial_traits_impl
+ {
+ typedef typename get_int_float_mixture <T,S>::type int_float_mixture ;
+ typedef typename get_sign_mixture <T,S>::type sign_mixture ;
+ typedef typename get_udt_builtin_mixture <T,S>::type udt_builtin_mixture ;
+
+ typedef typename get_is_subranged<T,S>::type subranged ;
+
+ typedef mpl::false_ trivial ;
+
+ typedef T target_type ;
+ typedef S source_type ;
+ typedef T result_type ;
+
+ typedef typename mpl::if_< is_arithmetic<S>, S, S const&>::type argument_type ;
+
+ typedef typename mpl::if_<subranged,S,T>::type supertype ;
+ typedef typename mpl::if_<subranged,T,S>::type subtype ;
+ } ;
+
+ //-------------------------------------------------------------------
+ // Implementation of the Conversion Traits for T == S
+ //
+ // This is a VISIBLE base class of the user-level conversion_traits<> class.
+ //-------------------------------------------------------------------
+ template<class N>
+ struct trivial_traits_impl
+ {
+ typedef typename get_int_float_mixture <N,N>::type int_float_mixture ;
+ typedef typename get_sign_mixture <N,N>::type sign_mixture ;
+ typedef typename get_udt_builtin_mixture<N,N>::type udt_builtin_mixture ;
+
+ typedef mpl::false_ subranged ;
+ typedef mpl::true_ trivial ;
+
+ typedef N target_type ;
+ typedef N source_type ;
+ typedef N const& result_type ;
+ typedef N const& argument_type ;
+
+ typedef N supertype ;
+ typedef N subtype ;
+
+ } ;
+
+ //-------------------------------------------------------------------
+ // Top level implementation selector.
+ //-------------------------------------------------------------------
+ template<class T, class S>
+ struct get_conversion_traits
+ {
+ typedef typename remove_cv<T>::type target_type ;
+ typedef typename remove_cv<S>::type source_type ;
+
+ typedef typename is_same<target_type,source_type>::type is_trivial ;
+
+ typedef trivial_traits_impl <target_type> trivial_imp ;
+ typedef non_trivial_traits_impl<target_type,source_type> non_trivial_imp ;
+
+ typedef typename mpl::if_<is_trivial,trivial_imp,non_trivial_imp>::type type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
+
+#include <functional>
+
+#include "boost/numeric/conversion/detail/meta.hpp"
+#include "boost/numeric/conversion/detail/conversion_traits.hpp"
+#include "boost/numeric/conversion/bounds.hpp"
+
+#include "boost/type_traits/is_same.hpp"
+
+#include "boost/mpl/integral_c.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ // Integral Constants representing rounding modes
+ typedef mpl::integral_c<std::float_round_style, std::round_toward_zero> round2zero_c ;
+ typedef mpl::integral_c<std::float_round_style, std::round_to_nearest> round2nearest_c ;
+ typedef mpl::integral_c<std::float_round_style, std::round_toward_infinity> round2inf_c ;
+ typedef mpl::integral_c<std::float_round_style, std::round_toward_neg_infinity> round2neg_inf_c ;
+
+ // Metafunction:
+ //
+ // for_round_style<RoundStyle,RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf>::type
+ //
+ // {RoundStyle} Integral Constant specifying a round style as declared above.
+ // {RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf} arbitrary types.
+ //
+ // Selects one of the 4 types according to the value of RoundStyle.
+ //
+ template<class RoundStyle,class RoundToZero,class RoundToNearest,class RoundToInf,class RoundToNegInf>
+ struct for_round_style
+ {
+ typedef ct_switch4<RoundStyle
+ , round2zero_c, round2nearest_c, round2inf_c // round2neg_inf_c
+ , RoundToZero , RoundToNearest , RoundToInf , RoundToNegInf
+ > selector ;
+
+ typedef typename selector::type type ;
+ } ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//--------------------------------------------------------------------------
+// Range Checking Logic.
+//
+// The range checking logic is built up by combining 1 or 2 predicates.
+// Each predicate is encapsulated in a template class and exposes
+// the static member function 'apply'.
+//
+//--------------------------------------------------------------------------
+
+
+ // Because a particular logic can combine either 1 or two predicates, the following
+ // tags are used to allow the predicate applier to receive 2 preds, but optimize away
+ // one of them if it is 'non-applicable'
+ struct non_applicable { typedef mpl::false_ do_apply ; } ;
+ struct applicable { typedef mpl::true_ do_apply ; } ;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Range Checking Logic implementations.
+ //
+ // The following classes, collectivelly named 'Predicates', are instantiated within
+ // the corresponding range checkers.
+ // Their static member function 'apply' is called to perform the actual range checking logic.
+ //--------------------------------------------------------------------------
+
+ // s < Lowest(T) ? cNegOverflow : cInRange
+ //
+ template<class Traits>
+ struct LT_LoT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s < static_cast<S>(bounds<T>::lowest()) ? cNegOverflow : cInRange ;
+ }
+ } ;
+
+ // s < 0 ? cNegOverflow : cInRange
+ //
+ template<class Traits>
+ struct LT_Zero : applicable
+ {
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s < static_cast<S>(0) ? cNegOverflow : cInRange ;
+ }
+ } ;
+
+ // s <= Lowest(T)-1 ? cNegOverflow : cInRange
+ //
+ template<class Traits>
+ struct LE_PrevLoT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s <= static_cast<S>(bounds<T>::lowest()) - static_cast<S>(1.0)
+ ? cNegOverflow : cInRange ;
+ }
+ } ;
+
+ // s < Lowest(T)-0.5 ? cNegOverflow : cInRange
+ //
+ template<class Traits>
+ struct LT_HalfPrevLoT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s < static_cast<S>(bounds<T>::lowest()) - static_cast<S>(0.5)
+ ? cNegOverflow : cInRange ;
+ }
+ } ;
+
+ // s > Highest(T) ? cPosOverflow : cInRange
+ //
+ template<class Traits>
+ struct GT_HiT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s > static_cast<S>(bounds<T>::highest())
+ ? cPosOverflow : cInRange ;
+ }
+ } ;
+
+ // s >= Lowest(T) + 1 ? cPosOverflow : cInRange
+ //
+ template<class Traits>
+ struct GE_SuccHiT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(1.0)
+ ? cPosOverflow : cInRange ;
+ }
+ } ;
+
+ // s >= Lowest(T) + 0.5 ? cPosgOverflow : cInRange
+ //
+ template<class Traits>
+ struct GT_HalfSuccHiT : applicable
+ {
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(0.5)
+ ? cPosOverflow : cInRange ;
+ }
+ } ;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Predicate Combiner.
+ //
+ // This helper classes are used to possibly combine the range checking logic
+ // individually performed by the predicates
+ //
+ //--------------------------------------------------------------------------
+
+
+ // Applies both predicates: first 'PredA', and if it equals 'cInRange', 'PredB'
+ template<class PredA, class PredB>
+ struct applyBoth
+ {
+ typedef typename PredA::argument_type argument_type ;
+
+ static range_check_result apply ( argument_type s )
+ {
+ range_check_result r = PredA::apply(s) ;
+ if ( r == cInRange )
+ r = PredB::apply(s);
+ return r ;
+ }
+ } ;
+
+ template<class PredA, class PredB>
+ struct combine
+ {
+ typedef applyBoth<PredA,PredB> Both ;
+ typedef void NNone ; // 'None' is defined as a macro in (/usr/X11R6/include/X11/X.h)
+
+ typedef typename PredA::do_apply do_applyA ;
+ typedef typename PredB::do_apply do_applyB ;
+
+ typedef typename for_both<do_applyA, do_applyB, Both, PredA, PredB, NNone>::type type ;
+ } ;
+
+
+
+
+
+
+
+
+
+
+
+
+//--------------------------------------------------------------------------
+// Range Checker classes.
+//
+// The following classes are VISIBLE base classes of the user-level converter<> class.
+// They supply the optimized 'out_of_range()' and 'validate_range()' static member functions
+// visible in the user interface.
+//
+//--------------------------------------------------------------------------
+
+ // Dummy range checker.
+ template<class Traits>
+ struct dummy_range_checker
+ {
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result out_of_range ( argument_type ) { return cInRange ; }
+ static void validate_range ( argument_type ) {}
+ } ;
+
+ // Generic range checker.
+ //
+ // All the range checking logic for all possible combinations of source and target
+ // can be arranged in terms of one or two predicates, which test overflow on both neg/pos 'sides'
+ // of the ranges.
+ //
+ // These predicates are given here as IsNegOverflow and IsPosOverflow.
+ //
+ template<class Traits, class IsNegOverflow, class IsPosOverflow, class OverflowHandler>
+ struct generic_range_checker
+ {
+ typedef OverflowHandler overflow_handler ;
+
+ typedef typename Traits::argument_type argument_type ;
+
+ static range_check_result out_of_range ( argument_type s )
+ {
+ typedef typename combine<IsNegOverflow,IsPosOverflow>::type Predicate ;
+
+ return Predicate::apply(s);
+ }
+
+ static void validate_range ( argument_type s )
+ { OverflowHandler()( out_of_range(s) ) ; }
+ } ;
+
+
+
+//--------------------------------------------------------------------------
+//
+// Selectors for the optimized Range Checker class.
+//
+//--------------------------------------------------------------------------
+
+ template<class Traits,class OverflowHandler>
+ struct GetRC_Sig2Sig_or_Unsig2Unsig
+ {
+ typedef dummy_range_checker<Traits> Dummy ;
+
+ typedef LT_LoT<Traits> Pred1 ;
+ typedef GT_HiT<Traits> Pred2 ;
+
+ typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
+
+ typedef typename Traits::subranged subranged ;
+
+ typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
+ } ;
+
+ template<class Traits, class OverflowHandler>
+ struct GetRC_Sig2Unsig
+ {
+ typedef LT_Zero<Traits> Pred1 ;
+ typedef GT_HiT <Traits> Pred2 ;
+
+ typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ChoiceA ;
+
+ typedef generic_range_checker<Traits,Pred1,non_applicable,OverflowHandler> ChoiceB ;
+
+ typedef typename Traits::target_type T ;
+ typedef typename Traits::source_type S ;
+
+ typedef typename subranged_Unsig2Sig<S,T>::type oposite_subranged ;
+
+ typedef typename mpl::not_<oposite_subranged>::type positively_subranged ;
+
+ typedef typename mpl::if_<positively_subranged,ChoiceA,ChoiceB>::type type ;
+ } ;
+
+ template<class Traits, class OverflowHandler>
+ struct GetRC_Unsig2Sig
+ {
+ typedef GT_HiT<Traits> Pred1 ;
+
+ typedef generic_range_checker<Traits,non_applicable,Pred1,OverflowHandler> type ;
+ } ;
+
+ template<class Traits,class OverflowHandler>
+ struct GetRC_Int2Int
+ {
+ typedef GetRC_Sig2Sig_or_Unsig2Unsig<Traits,OverflowHandler> Sig2SigQ ;
+ typedef GetRC_Sig2Unsig <Traits,OverflowHandler> Sig2UnsigQ ;
+ typedef GetRC_Unsig2Sig <Traits,OverflowHandler> Unsig2SigQ ;
+ typedef Sig2SigQ Unsig2UnsigQ ;
+
+ typedef typename Traits::sign_mixture sign_mixture ;
+
+ typedef typename
+ for_sign_mixture<sign_mixture,Sig2SigQ,Sig2UnsigQ,Unsig2SigQ,Unsig2UnsigQ>::type
+ selector ;
+
+ typedef typename selector::type type ;
+ } ;
+
+ template<class Traits>
+ struct GetRC_Int2Float
+ {
+ typedef dummy_range_checker<Traits> type ;
+ } ;
+
+ template<class Traits, class OverflowHandler, class Float2IntRounder>
+ struct GetRC_Float2Int
+ {
+ typedef LE_PrevLoT <Traits> Pred1 ;
+ typedef GE_SuccHiT <Traits> Pred2 ;
+ typedef LT_HalfPrevLoT<Traits> Pred3 ;
+ typedef GT_HalfSuccHiT<Traits> Pred4 ;
+ typedef GT_HiT <Traits> Pred5 ;
+ typedef LT_LoT <Traits> Pred6 ;
+
+ typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ToZero ;
+ typedef generic_range_checker<Traits,Pred3,Pred4,OverflowHandler> ToNearest ;
+ typedef generic_range_checker<Traits,Pred1,Pred5,OverflowHandler> ToInf ;
+ typedef generic_range_checker<Traits,Pred6,Pred2,OverflowHandler> ToNegInf ;
+
+ typedef typename Float2IntRounder::round_style round_style ;
+
+ typedef typename for_round_style<round_style,ToZero,ToNearest,ToInf,ToNegInf>::type type ;
+ } ;
+
+ template<class Traits, class OverflowHandler>
+ struct GetRC_Float2Float
+ {
+ typedef dummy_range_checker<Traits> Dummy ;
+
+ typedef LT_LoT<Traits> Pred1 ;
+ typedef GT_HiT<Traits> Pred2 ;
+
+ typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
+
+ typedef typename Traits::subranged subranged ;
+
+ typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
+ } ;
+
+ template<class Traits, class OverflowHandler, class Float2IntRounder>
+ struct GetRC_BuiltIn2BuiltIn
+ {
+ typedef GetRC_Int2Int<Traits,OverflowHandler> Int2IntQ ;
+ typedef GetRC_Int2Float<Traits> Int2FloatQ ;
+ typedef GetRC_Float2Int<Traits,OverflowHandler,Float2IntRounder> Float2IntQ ;
+ typedef GetRC_Float2Float<Traits,OverflowHandler> Float2FloatQ ;
+
+ typedef typename Traits::int_float_mixture int_float_mixture ;
+
+ typedef typename for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ>::type selector ;
+
+ typedef typename selector::type type ;
+ } ;
+
+ template<class Traits, class OverflowHandler, class Float2IntRounder>
+ struct GetRC
+ {
+ typedef GetRC_BuiltIn2BuiltIn<Traits,OverflowHandler,Float2IntRounder> BuiltIn2BuiltInQ ;
+
+ typedef dummy_range_checker<Traits> Dummy ;
+
+ typedef mpl::identity<Dummy> DummyQ ;
+
+ typedef typename Traits::udt_builtin_mixture udt_builtin_mixture ;
+
+ typedef typename for_udt_builtin_mixture<udt_builtin_mixture,BuiltIn2BuiltInQ,DummyQ,DummyQ,DummyQ>::type selector ;
+
+ typedef typename selector::type type ;
+ } ;
+
+
+
+
+//--------------------------------------------------------------------------
+// Converter classes.
+//
+// The following classes are VISIBLE base classes of the user-level converter<> class.
+// They supply the optimized 'nearbyint()' and 'convert()' static member functions
+// visible in the user interface.
+//
+//--------------------------------------------------------------------------
+
+ //
+ // Trivial Converter : used when (cv-unqualified) T == (cv-unqualified) S
+ //
+ template<class Traits>
+ struct trivial_converter_impl : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
+ ,BOOST_DEDUCED_TYPENAME Traits::result_type
+ >
+ ,public dummy_range_checker<Traits>
+ {
+ typedef Traits traits ;
+
+ typedef typename Traits::source_type source_type ;
+ typedef typename Traits::argument_type argument_type ;
+ typedef typename Traits::result_type result_type ;
+
+ static result_type low_level_convert ( argument_type s ) { return s ; }
+ static source_type nearbyint ( argument_type s ) { return s ; }
+ static result_type convert ( argument_type s ) { return s ; }
+ } ;
+
+
+ //
+ // Rounding Converter : used for float to integral conversions.
+ //
+ template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder>
+ struct rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
+ ,BOOST_DEDUCED_TYPENAME Traits::result_type
+ >
+ ,public RangeChecker
+ ,public Float2IntRounder
+ ,public RawConverter
+ {
+ typedef RangeChecker RangeCheckerBase ;
+ typedef Float2IntRounder Float2IntRounderBase ;
+ typedef RawConverter RawConverterBase ;
+
+ typedef Traits traits ;
+
+ typedef typename Traits::source_type source_type ;
+ typedef typename Traits::argument_type argument_type ;
+ typedef typename Traits::result_type result_type ;
+
+ static result_type convert ( argument_type s )
+ {
+ RangeCheckerBase::validate_range(s);
+ source_type s1 = Float2IntRounderBase::nearbyint(s);
+ return RawConverterBase::low_level_convert(s1);
+ }
+ } ;
+
+
+ //
+ // Non-Rounding Converter : used for all other conversions.
+ //
+ template<class Traits,class RangeChecker,class RawConverter>
+ struct non_rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
+ ,BOOST_DEDUCED_TYPENAME Traits::result_type
+ >
+ ,public RangeChecker
+ ,public RawConverter
+ {
+ typedef RangeChecker RangeCheckerBase ;
+ typedef RawConverter RawConverterBase ;
+
+ typedef Traits traits ;
+
+ typedef typename Traits::source_type source_type ;
+ typedef typename Traits::argument_type argument_type ;
+ typedef typename Traits::result_type result_type ;
+
+ static source_type nearbyint ( argument_type s ) { return s ; }
+
+ static result_type convert ( argument_type s )
+ {
+ RangeCheckerBase::validate_range(s);
+ return RawConverterBase::low_level_convert(s);
+ }
+ } ;
+
+
+
+
+//--------------------------------------------------------------------------
+//
+// Selectors for the optimized Converter class.
+//
+//--------------------------------------------------------------------------
+
+ template<class Traits,class OverflowHandler,class Float2IntRounder,class RawConverter, class UserRangeChecker>
+ struct get_non_trivial_converter
+ {
+ typedef GetRC<Traits,OverflowHandler,Float2IntRounder> InternalRangeCheckerQ ;
+
+ typedef is_same<UserRangeChecker,UseInternalRangeChecker> use_internal_RC ;
+
+ typedef mpl::identity<UserRangeChecker> UserRangeCheckerQ ;
+
+ typedef typename
+ mpl::eval_if<use_internal_RC,InternalRangeCheckerQ,UserRangeCheckerQ>::type
+ RangeChecker ;
+
+ typedef non_rounding_converter<Traits,RangeChecker,RawConverter> NonRounding ;
+ typedef rounding_converter<Traits,RangeChecker,RawConverter,Float2IntRounder> Rounding ;
+
+ typedef mpl::identity<NonRounding> NonRoundingQ ;
+ typedef mpl::identity<Rounding> RoundingQ ;
+
+ typedef typename Traits::int_float_mixture int_float_mixture ;
+
+ typedef typename
+ for_int_float_mixture<int_float_mixture, NonRoundingQ, NonRoundingQ, RoundingQ, NonRoundingQ>::type
+ selector ;
+
+ typedef typename selector::type type ;
+ } ;
+
+ template< class Traits
+ ,class OverflowHandler
+ ,class Float2IntRounder
+ ,class RawConverter
+ ,class UserRangeChecker
+ >
+ struct get_converter_impl
+ {
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x0561 ) )
+ // bcc55 prefers sometimes template parameters to be explicit local types.
+ // (notice that is is illegal to reuse the names like this)
+ typedef Traits Traits ;
+ typedef OverflowHandler OverflowHandler ;
+ typedef Float2IntRounder Float2IntRounder ;
+ typedef RawConverter RawConverter ;
+ typedef UserRangeChecker UserRangeChecker ;
+#endif
+
+ typedef trivial_converter_impl<Traits> Trivial ;
+ typedef mpl::identity <Trivial> TrivialQ ;
+
+ typedef get_non_trivial_converter< Traits
+ ,OverflowHandler
+ ,Float2IntRounder
+ ,RawConverter
+ ,UserRangeChecker
+ > NonTrivialQ ;
+
+ typedef typename Traits::trivial trivial ;
+
+ typedef typename mpl::eval_if<trivial,TrivialQ,NonTrivialQ>::type type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_INT_FLOAT_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_INT_FLOAT_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/config.hpp"
+#include "boost/limits.hpp"
+
+#include "boost/numeric/conversion/int_float_mixture_enum.hpp"
+#include "boost/numeric/conversion/detail/meta.hpp"
+
+#include "boost/mpl/integral_c.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ // Integral Constants for 'IntFloatMixture'
+ typedef mpl::integral_c<int_float_mixture_enum, integral_to_integral> int2int_c ;
+ typedef mpl::integral_c<int_float_mixture_enum, integral_to_float> int2float_c ;
+ typedef mpl::integral_c<int_float_mixture_enum, float_to_integral> float2int_c ;
+ typedef mpl::integral_c<int_float_mixture_enum, float_to_float> float2float_c ;
+
+ // Metafunction:
+ //
+ // get_int_float_mixture<T,S>::type
+ //
+ // Selects the appropriate Int-Float Mixture Integral Constant for the combination T,S.
+ //
+ template<class T,class S>
+ struct get_int_float_mixture
+ {
+ typedef mpl::bool_< ::std::numeric_limits<S>::is_integer > S_int ;
+ typedef mpl::bool_< ::std::numeric_limits<T>::is_integer > T_int ;
+
+ typedef typename
+ for_both<S_int, T_int, int2int_c, int2float_c, float2int_c, float2float_c>::type
+ type ;
+ } ;
+
+ // Metafunction:
+ //
+ // for_int_float_mixture<Mixture,int_int,int_float,float_int,float_float>::type
+ //
+ // {Mixture} is one of the Integral Constants for Mixture, declared above.
+ // {int_int,int_float,float_int,float_float} are aribtrary types. (not metafunctions)
+ //
+ // According to the value of 'IntFloatMixture', selects the corresponding type.
+ //
+ template<class IntFloatMixture, class Int2Int, class Int2Float, class Float2Int, class Float2Float>
+ struct for_int_float_mixture
+ {
+ typedef typename
+ ct_switch4<IntFloatMixture
+ ,int2int_c, int2float_c, float2int_c // default
+ ,Int2Int , Int2Float , Float2Int , Float2Float
+ >::type
+ type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP
+
+#include "boost/config.hpp"
+#include "boost/limits.hpp"
+
+#include "boost/mpl/int.hpp"
+#include "boost/mpl/multiplies.hpp"
+#include "boost/mpl/less.hpp"
+#include "boost/mpl/equal_to.hpp"
+
+#include "boost/type_traits/is_same.hpp"
+
+#include "boost/numeric/conversion/detail/meta.hpp"
+#include "boost/numeric/conversion/detail/int_float_mixture.hpp"
+#include "boost/numeric/conversion/detail/sign_mixture.hpp"
+#include "boost/numeric/conversion/detail/udt_builtin_mixture.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ //---------------------------------------------------------------
+ // Implementations of the compile time predicate "T is subranged"
+ //---------------------------------------------------------------
+
+ // for integral to integral conversions
+ template<class T,class S>
+ struct subranged_Sig2Unsig
+ {
+ // Signed to unsigned conversions are 'subranged' because of possible loose
+ // of negative values.
+ typedef mpl::true_ type ;
+ } ;
+
+ // for unsigned integral to signed integral conversions
+ template<class T,class S>
+ struct subranged_Unsig2Sig
+ {
+ // IMPORTANT NOTE:
+ //
+ // This code assumes that signed/unsigned integral values are represented
+ // such that:
+ //
+ // numeric_limits<signed T>::digits + 1 == numeric_limits<unsigned T>::digits
+ //
+ // The '+1' is required since numeric_limits<>::digits gives 1 bit less for signed integral types.
+ //
+ // This fact is used by the following logic:
+ //
+ // if ( (numeric_limits<T>::digits+1) < (2*numeric_limits<S>::digits) )
+ // then the conversion is subranged.
+ //
+
+ typedef mpl::int_< ::std::numeric_limits<S>::digits > S_digits ;
+ typedef mpl::int_< ::std::numeric_limits<T>::digits > T_digits ;
+
+ // T is signed, so take digits+1
+ typedef typename T_digits::next u_T_digits ;
+
+ typedef mpl::int_<2> Two ;
+
+ typedef typename mpl::multiplies<S_digits,Two>::type S_digits_times_2 ;
+
+ typedef typename mpl::less<u_T_digits,S_digits_times_2>::type type ;
+ } ;
+
+ // for integral to integral conversions of the same sign.
+ template<class T,class S>
+ struct subranged_SameSign
+ {
+ // An integral conversion of the same sign is subranged if digits(T) < digits(S).
+
+ typedef mpl::int_< ::std::numeric_limits<S>::digits > S_digits ;
+ typedef mpl::int_< ::std::numeric_limits<T>::digits > T_digits ;
+
+ typedef typename mpl::less<T_digits,S_digits>::type type ;
+ } ;
+
+ // for integral to float conversions
+ template<class T,class S>
+ struct subranged_Int2Float
+ {
+ typedef mpl::false_ type ;
+ } ;
+
+ // for float to integral conversions
+ template<class T,class S>
+ struct subranged_Float2Int
+ {
+ typedef mpl::true_ type ;
+ } ;
+
+ // for float to float conversions
+ template<class T,class S>
+ struct subranged_Float2Float
+ {
+ // If both T and S are floats,
+ // compare exponent bits and if they match, mantisa bits.
+
+ typedef mpl::int_< ::std::numeric_limits<S>::digits > S_mantisa ;
+ typedef mpl::int_< ::std::numeric_limits<T>::digits > T_mantisa ;
+
+ typedef mpl::int_< ::std::numeric_limits<S>::max_exponent > S_exponent ;
+ typedef mpl::int_< ::std::numeric_limits<T>::max_exponent > T_exponent ;
+
+ typedef typename mpl::less<T_exponent,S_exponent>::type T_smaller_exponent ;
+
+ typedef typename mpl::equal_to<T_exponent,S_exponent>::type equal_exponents ;
+
+ typedef mpl::less<T_mantisa,S_mantisa> T_smaller_mantisa ;
+
+ typedef mpl::eval_if<equal_exponents,T_smaller_mantisa,mpl::false_> not_bigger_exponent_case ;
+
+ typedef typename
+ mpl::eval_if<T_smaller_exponent,mpl::true_,not_bigger_exponent_case>::type
+ type ;
+ } ;
+
+ // for Udt to built-in conversions
+ template<class T,class S>
+ struct subranged_Udt2BuiltIn
+ {
+ typedef mpl::true_ type ;
+ } ;
+
+ // for built-in to Udt conversions
+ template<class T,class S>
+ struct subranged_BuiltIn2Udt
+ {
+ typedef mpl::false_ type ;
+ } ;
+
+ // for Udt to Udt conversions
+ template<class T,class S>
+ struct subranged_Udt2Udt
+ {
+ typedef mpl::false_ type ;
+ } ;
+
+ //-------------------------------------------------------------------
+ // Selectors for the implementations of the subranged predicate
+ //-------------------------------------------------------------------
+
+ template<class T,class S>
+ struct get_subranged_Int2Int
+ {
+ typedef subranged_SameSign<T,S> Sig2Sig ;
+ typedef subranged_Sig2Unsig<T,S> Sig2Unsig ;
+ typedef subranged_Unsig2Sig<T,S> Unsig2Sig ;
+ typedef Sig2Sig Unsig2Unsig ;
+
+ typedef typename get_sign_mixture<T,S>::type sign_mixture ;
+
+ typedef typename
+ for_sign_mixture<sign_mixture, Sig2Sig, Sig2Unsig, Unsig2Sig, Unsig2Unsig>::type
+ type ;
+ } ;
+
+ template<class T,class S>
+ struct get_subranged_BuiltIn2BuiltIn
+ {
+ typedef get_subranged_Int2Int<T,S> Int2IntQ ;
+
+ typedef subranged_Int2Float <T,S> Int2Float ;
+ typedef subranged_Float2Int <T,S> Float2Int ;
+ typedef subranged_Float2Float<T,S> Float2Float ;
+
+ typedef mpl::identity<Int2Float > Int2FloatQ ;
+ typedef mpl::identity<Float2Int > Float2IntQ ;
+ typedef mpl::identity<Float2Float> Float2FloatQ ;
+
+ typedef typename get_int_float_mixture<T,S>::type int_float_mixture ;
+
+ typedef for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ> for_ ;
+
+ typedef typename for_::type selected ;
+
+ typedef typename selected::type type ;
+ } ;
+
+ template<class T,class S>
+ struct get_subranged
+ {
+ typedef get_subranged_BuiltIn2BuiltIn<T,S> BuiltIn2BuiltInQ ;
+
+ typedef subranged_BuiltIn2Udt<T,S> BuiltIn2Udt ;
+ typedef subranged_Udt2BuiltIn<T,S> Udt2BuiltIn ;
+ typedef subranged_Udt2Udt<T,S> Udt2Udt ;
+
+ typedef mpl::identity<BuiltIn2Udt> BuiltIn2UdtQ ;
+ typedef mpl::identity<Udt2BuiltIn> Udt2BuiltInQ ;
+ typedef mpl::identity<Udt2Udt > Udt2UdtQ ;
+
+ typedef typename get_udt_builtin_mixture<T,S>::type udt_builtin_mixture ;
+
+ typedef typename
+ for_udt_builtin_mixture<udt_builtin_mixture, BuiltIn2BuiltInQ, BuiltIn2UdtQ, Udt2BuiltInQ, Udt2UdtQ>::type
+ selected ;
+
+ typedef typename selected::type selected2 ;
+
+ typedef typename selected2::type type ;
+ } ;
+
+
+ //-------------------------------------------------------------------
+ // Top level implementation selector.
+ //-------------------------------------------------------------------
+ template<class T, class S>
+ struct get_is_subranged
+ {
+ typedef get_subranged<T,S> non_trivial_case ;
+ typedef mpl::identity<mpl::false_> trivial_case ;
+
+ typedef is_same<T,S> is_trivial ;
+
+ typedef typename mpl::if_<is_trivial,trivial_case,non_trivial_case>::type selected ;
+
+ typedef typename selected::type type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_META_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_META_FLC_12NOV2002_HPP
+
+#include "boost/type_traits/remove_cv.hpp"
+
+#include "boost/mpl/if.hpp"
+#include "boost/mpl/eval_if.hpp"
+#include "boost/mpl/equal_to.hpp"
+#include "boost/mpl/not.hpp"
+#include "boost/mpl/and.hpp"
+#include "boost/mpl/bool.hpp"
+#include "boost/mpl/identity.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ template< class T1, class T2>
+ struct equal_to
+ {
+ #if !defined(__BORLANDC__)
+
+ enum { x = ( BOOST_MPL_AUX_VALUE_WKND(T1)::value == BOOST_MPL_AUX_VALUE_WKND(T2)::value ) };
+
+ BOOST_STATIC_CONSTANT(bool, value = x);
+
+ typedef mpl::bool_<value> type;
+
+ #else
+
+ BOOST_STATIC_CONSTANT(bool, value = (
+ BOOST_MPL_AUX_VALUE_WKND(T1)::value
+ == BOOST_MPL_AUX_VALUE_WKND(T2)::value
+ ));
+
+ typedef mpl::bool_<(
+ BOOST_MPL_AUX_VALUE_WKND(T1)::value
+ == BOOST_MPL_AUX_VALUE_WKND(T2)::value
+ )> type;
+ #endif
+ };
+
+// Metafunction:
+ //
+ // ct_switch4<Value,Case0Val,Case1Val,Case2Val,Case0Type,Case1Type,Case2Type,DefaultType>::type
+ //
+ // {Value,Case(X)Val} are Integral Constants (such as: mpl::int_<>)
+ // {Case(X)Type,DefaultType} are arbitrary types. (not metafunctions)
+ //
+ // Returns Case(X)Type if Val==Case(X)Val; DefaultType otherwise.
+ //
+ template<class Value,
+ class Case0Val,
+ class Case1Val,
+ class Case2Val,
+ class Case0Type,
+ class Case1Type,
+ class Case2Type,
+ class DefaultType
+ >
+ struct ct_switch4
+ {
+ typedef mpl::identity<Case0Type> Case0TypeQ ;
+ typedef mpl::identity<Case1Type> Case1TypeQ ;
+
+ typedef equal_to<Value,Case0Val> is_case0 ;
+ typedef equal_to<Value,Case1Val> is_case1 ;
+ typedef equal_to<Value,Case2Val> is_case2 ;
+
+ typedef mpl::if_<is_case2,Case2Type,DefaultType> choose_2_3Q ;
+ typedef mpl::eval_if<is_case1,Case1TypeQ,choose_2_3Q> choose_1_2_3Q ;
+
+ typedef typename
+ mpl::eval_if<is_case0,Case0TypeQ,choose_1_2_3Q>::type
+ type ;
+ } ;
+
+
+
+
+ // Metafunction:
+ //
+ // for_both<expr0,expr1,TT,TF,FT,FF>::type
+ //
+ // {exp0,expr1} are Boolean Integral Constants
+ // {TT,TF,FT,FF} are aribtrary types. (not metafunctions)
+ //
+ // According to the combined boolean value of 'expr0 && expr1', selects the corresponding type.
+ //
+ template<class expr0, class expr1, class TT, class TF, class FT, class FF>
+ struct for_both
+ {
+ typedef mpl::identity<TF> TF_Q ;
+ typedef mpl::identity<TT> TT_Q ;
+
+ typedef typename mpl::not_<expr0>::type not_expr0 ;
+ typedef typename mpl::not_<expr1>::type not_expr1 ;
+
+ typedef typename mpl::and_<expr0,expr1>::type caseTT ;
+ typedef typename mpl::and_<expr0,not_expr1>::type caseTF ;
+ typedef typename mpl::and_<not_expr0,expr1>::type caseFT ;
+
+ typedef mpl::if_<caseFT,FT,FF> choose_FT_FF_Q ;
+ typedef mpl::eval_if<caseTF,TF_Q,choose_FT_FF_Q> choose_TF_FT_FF_Q ;
+
+ typedef typename mpl::eval_if<caseTT,TT_Q,choose_TF_FT_FF_Q>::type type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+
+
--- /dev/null
+//
+//! Copyright (c) 2011-2012
+//! Brandon Kohn
+//
+// 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)
+//
+
+#if !defined(BOOST_NUMERIC_CONVERSION_DONT_USE_PREPROCESSED_FILES)
+
+ #include <boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp>
+
+ #if !defined(BOOST_NO_LONG_LONG)
+ #include <boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp>
+ #endif
+
+#else
+#if !BOOST_PP_IS_ITERATING
+
+ #include <boost/preprocessor/seq/elem.hpp>
+ #include <boost/preprocessor/seq/size.hpp>
+ #include <boost/preprocessor/iteration/iterate.hpp>
+
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(preserve: 2, line: 0, output: "preprocessed/numeric_cast_traits_common.hpp")
+ #endif
+//
+//! Copyright (c) 2011-2012
+//! Brandon Kohn
+//
+// 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)
+//
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(preserve: 1)
+ #endif
+
+ //! These are the assumed common built in fundamental types (not typedefs/macros.)
+ #define BOOST_NUMERIC_CONVERSION_BASE_BUILTIN_TYPES() \
+ (char) \
+ (signed char) \
+ (unsigned char) \
+ (short) \
+ (unsigned short) \
+ (int) \
+ (unsigned int) \
+ (long) \
+ (unsigned long) \
+ (float) \
+ (double) \
+ (long double) \
+ /***/
+
+ #define BOOST_NUMERIC_CONVERSION_SEQ_A() BOOST_NUMERIC_CONVERSION_BASE_BUILTIN_TYPES()
+ #define BOOST_NUMERIC_CONVERSION_SEQ_B() BOOST_NUMERIC_CONVERSION_BASE_BUILTIN_TYPES()
+
+namespace boost { namespace numeric {
+
+ #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_NUMERIC_CONVERSION_SEQ_A())), <boost/numeric/conversion/detail/numeric_cast_traits.hpp>))
+ #include BOOST_PP_ITERATE()
+
+}}//namespace boost::numeric;
+
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(output: null)
+ #endif
+
+ #if ( defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES) ) || !defined(BOOST_NO_LONG_LONG)
+
+ #undef BOOST_NUMERIC_CONVERSION_SEQ_A
+ #undef BOOST_NUMERIC_CONVERSION_SEQ_B
+
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(preserve: 2, line: 0, output: "preprocessed/numeric_cast_traits_long_long.hpp")
+ #endif
+
+//
+//! Copyright (c) 2011-2012
+//! Brandon Kohn
+//
+// 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)
+//
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(preserve: 1)
+ #endif
+
+namespace boost { namespace numeric {
+
+ #define BOOST_NUMERIC_CONVERSION_SEQ_A() BOOST_NUMERIC_CONVERSION_BASE_BUILTIN_TYPES()(boost::long_long_type)(boost::ulong_long_type)
+ #define BOOST_NUMERIC_CONVERSION_SEQ_B() (boost::long_long_type)(boost::ulong_long_type)
+
+ #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_NUMERIC_CONVERSION_SEQ_A())), <boost/numeric/conversion/detail/numeric_cast_traits.hpp>))
+ #include BOOST_PP_ITERATE()
+
+}}//namespace boost::numeric;
+
+ #if defined(__WAVE__) && defined(BOOST_NUMERIC_CONVERSION_CREATE_PREPROCESSED_FILES)
+ #pragma wave option(output: null)
+ #endif
+
+ #endif
+
+ #undef BOOST_NUMERIC_CONVERSION_BASE_BUILTIN_TYPES
+ #undef BOOST_NUMERIC_CONVERSION_SEQ_A
+ #undef BOOST_NUMERIC_CONVERSION_SEQ_B
+
+#elif BOOST_PP_ITERATION_DEPTH() == 1
+
+ #define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_NUMERIC_CONVERSION_SEQ_B())), <boost/numeric/conversion/detail/numeric_cast_traits.hpp>))
+ #include BOOST_PP_ITERATE()
+
+#elif BOOST_PP_ITERATION_DEPTH() == 2
+
+ //! Generate default traits for the specified source and target.
+ #define BOOST_NUMERIC_CONVERSION_A BOOST_PP_FRAME_ITERATION(1)
+ #define BOOST_NUMERIC_CONVERSION_B BOOST_PP_FRAME_ITERATION(2)
+
+ template <>
+ struct numeric_cast_traits
+ <
+ BOOST_PP_SEQ_ELEM(BOOST_NUMERIC_CONVERSION_A, BOOST_NUMERIC_CONVERSION_SEQ_A())
+ , BOOST_PP_SEQ_ELEM(BOOST_NUMERIC_CONVERSION_B, BOOST_NUMERIC_CONVERSION_SEQ_B())
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<BOOST_PP_SEQ_ELEM(BOOST_NUMERIC_CONVERSION_B, BOOST_NUMERIC_CONVERSION_SEQ_B())> rounding_policy;
+ };
+
+ #undef BOOST_NUMERIC_CONVERSION_A
+ #undef BOOST_NUMERIC_CONVERSION_B
+
+#endif//! Depth 2.
+#endif// BOOST_NUMERIC_CONVERSION_DONT_USE_PREPROCESSED_FILES
--- /dev/null
+// boost cast.hpp header file ----------------------------------------------//
+
+// (C) Copyright Kevlin Henney and Dave Abrahams 1999.
+// 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)
+
+// See http://www.boost.org/libs/conversion for Documentation.
+
+// Revision History
+// 23 JUN 05 Code extracted from /boost/cast.hpp into this new header.
+// Keeps this legacy version of numeric_cast<> for old compilers
+// wich can't compile the new version in /boost/numeric/conversion/cast.hpp
+// (Fernando Cacciola)
+// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
+// <boost/limits.hpp> instead (the workaround did not
+// actually compile when BOOST_NO_LIMITS was defined in
+// any case, so we loose nothing). (John Maddock)
+// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never
+// worked with stock GCC; trying to get it to do that broke
+// vc-stlport.
+// 20 Jan 01 Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
+// Removed unused BOOST_EXPLICIT_TARGET macro. Moved
+// boost::detail::type to boost/type.hpp. Made it compile with
+// stock gcc again (Dave Abrahams)
+// 29 Nov 00 Remove nested namespace cast, cleanup spacing before Formal
+// Review (Beman Dawes)
+// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams)
+// 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC
+// (Dave Abrahams)
+// 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams)
+// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes)
+// 27 Jun 00 More MSVC6 workarounds
+// 15 Jun 00 Add workarounds for MSVC6
+// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
+// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
+// 29 Dec 99 Change using declarations so usages in other namespaces work
+// correctly (Dave Abrahams)
+// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors
+// as suggested Darin Adler and improved by Valentin Bonnard.
+// 2 Sep 99 Remove controversial asserts, simplify, rename.
+// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast,
+// place in nested namespace.
+// 3 Aug 99 Initial version
+
+#ifndef BOOST_OLD_NUMERIC_CAST_HPP
+#define BOOST_OLD_NUMERIC_CAST_HPP
+
+# include <boost/config.hpp>
+# include <cassert>
+# include <typeinfo>
+# include <boost/type.hpp>
+# include <boost/limits.hpp>
+# include <boost/numeric/conversion/converter_policies.hpp>
+
+// It has been demonstrated numerous times that MSVC 6.0 fails silently at link
+// time if you use a template function which has template parameters that don't
+// appear in the function's argument list.
+//
+// TODO: Add this to config.hpp?
+// FLC: This macro is repeated in boost/cast.hpp but only locally (is undefined at the bottom)
+// so is OK to reproduce it here.
+# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
+# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
+# else
+# define BOOST_EXPLICIT_DEFAULT_TARGET
+# endif
+
+namespace boost
+{
+ using numeric::bad_numeric_cast;
+
+// LEGACY numeric_cast [only for some old broken compilers] --------------------------------------//
+
+// Contributed by Kevlin Henney
+
+// numeric_cast ------------------------------------------------------------//
+
+#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
+
+ namespace detail
+ {
+ template <class T>
+ struct signed_numeric_limits : std::numeric_limits<T>
+ {
+ static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return (std::numeric_limits<T>::min)() >= 0
+ // unary minus causes integral promotion, thus the static_cast<>
+ ? static_cast<T>(-(std::numeric_limits<T>::max)())
+ : (std::numeric_limits<T>::min)();
+ };
+ };
+
+ // Move to namespace boost in utility.hpp?
+ template <class T, bool specialized>
+ struct fixed_numeric_limits_base
+ : public if_true< std::numeric_limits<T>::is_signed >
+ ::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
+ std::numeric_limits<T>
+ >::type
+ {};
+
+ template <class T>
+ struct fixed_numeric_limits
+ : fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
+ {};
+
+# ifdef BOOST_HAS_LONG_LONG
+ // cover implementations which supply no specialization for long
+ // long / unsigned long long. Not intended to be full
+ // numeric_limits replacements, but good enough for numeric_cast<>
+ template <>
+ struct fixed_numeric_limits_base< ::boost::long_long_type, false>
+ {
+ BOOST_STATIC_CONSTANT(bool, is_specialized = true);
+ BOOST_STATIC_CONSTANT(bool, is_signed = true);
+ static ::boost::long_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+# ifdef LONGLONG_MAX
+ return LONGLONG_MAX;
+# else
+ return 9223372036854775807LL; // hope this is portable
+# endif
+ }
+
+ static ::boost::long_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+# ifdef LONGLONG_MIN
+ return LONGLONG_MIN;
+# else
+ return -( 9223372036854775807LL )-1; // hope this is portable
+# endif
+ }
+ };
+
+ template <>
+ struct fixed_numeric_limits_base< ::boost::ulong_long_type, false>
+ {
+ BOOST_STATIC_CONSTANT(bool, is_specialized = true);
+ BOOST_STATIC_CONSTANT(bool, is_signed = false);
+ static ::boost::ulong_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+# ifdef ULONGLONG_MAX
+ return ULONGLONG_MAX;
+# else
+ return 0xffffffffffffffffULL; // hope this is portable
+# endif
+ }
+
+ static ::boost::ulong_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
+ };
+# endif
+ } // namespace detail
+
+// less_than_type_min -
+ // x_is_signed should be numeric_limits<X>::is_signed
+ // y_is_signed should be numeric_limits<Y>::is_signed
+ // y_min should be numeric_limits<Y>::min()
+ //
+ // check(x, y_min) returns true iff x < y_min without invoking comparisons
+ // between signed and unsigned values.
+ //
+ // "poor man's partial specialization" is in use here.
+ template <bool x_is_signed, bool y_is_signed>
+ struct less_than_type_min
+ {
+ template <class X, class Y>
+ static bool check(X x, Y y_min)
+ { return x < y_min; }
+ };
+
+ template <>
+ struct less_than_type_min<false, true>
+ {
+ template <class X, class Y>
+ static bool check(X, Y)
+ { return false; }
+ };
+
+ template <>
+ struct less_than_type_min<true, false>
+ {
+ template <class X, class Y>
+ static bool check(X x, Y)
+ { return x < 0; }
+ };
+
+ // greater_than_type_max -
+ // same_sign should be:
+ // numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
+ // y_max should be numeric_limits<Y>::max()
+ //
+ // check(x, y_max) returns true iff x > y_max without invoking comparisons
+ // between signed and unsigned values.
+ //
+ // "poor man's partial specialization" is in use here.
+ template <bool same_sign, bool x_is_signed>
+ struct greater_than_type_max;
+
+ template<>
+ struct greater_than_type_max<true, true>
+ {
+ template <class X, class Y>
+ static inline bool check(X x, Y y_max)
+ { return x > y_max; }
+ };
+
+ template <>
+ struct greater_than_type_max<false, true>
+ {
+ // What does the standard say about this? I think it's right, and it
+ // will work with every compiler I know of.
+ template <class X, class Y>
+ static inline bool check(X x, Y)
+ { return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
+
+# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
+ // MSVC6 can't static_cast unsigned __int64 -> floating types
+# define BOOST_UINT64_CAST(src_type) \
+ static inline bool check(src_type x, unsigned __int64) \
+ { \
+ if (x < 0) return false; \
+ unsigned __int64 y = static_cast<unsigned __int64>(x); \
+ bool odd = y & 0x1; \
+ __int64 div2 = static_cast<__int64>(y >> 1); \
+ return ((static_cast<src_type>(div2) * 2.0) + odd) != x; \
+ }
+
+ BOOST_UINT64_CAST(long double);
+ BOOST_UINT64_CAST(double);
+ BOOST_UINT64_CAST(float);
+# undef BOOST_UINT64_CAST
+# endif
+ };
+
+ template<>
+ struct greater_than_type_max<true, false>
+ {
+ template <class X, class Y>
+ static inline bool check(X x, Y y_max)
+ { return x > y_max; }
+ };
+
+ template <>
+ struct greater_than_type_max<false, false>
+ {
+ // What does the standard say about this? I think it's right, and it
+ // will work with every compiler I know of.
+ template <class X, class Y>
+ static inline bool check(X x, Y)
+ { return static_cast<X>(static_cast<Y>(x)) != x; }
+ };
+
+#else // use #pragma hacks if available
+
+ namespace detail
+ {
+# if BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4018)
+# pragma warning(disable : 4146)
+#elif defined(__BORLANDC__)
+# pragma option push -w-8041
+# endif
+
+ // Move to namespace boost in utility.hpp?
+ template <class T>
+ struct fixed_numeric_limits : public std::numeric_limits<T>
+ {
+ static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return std::numeric_limits<T>::is_signed && (std::numeric_limits<T>::min)() >= 0
+ ? T(-(std::numeric_limits<T>::max)()) : (std::numeric_limits<T>::min)();
+ }
+ };
+
+# if BOOST_MSVC
+# pragma warning(pop)
+#elif defined(__BORLANDC__)
+# pragma option pop
+# endif
+ } // namespace detail
+
+#endif
+
+ template<typename Target, typename Source>
+ inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
+ {
+ // typedefs abbreviating respective trait classes
+ typedef detail::fixed_numeric_limits<Source> arg_traits;
+ typedef detail::fixed_numeric_limits<Target> result_traits;
+
+#if defined(BOOST_STRICT_CONFIG) \
+ || (!defined(__HP_aCC) || __HP_aCC > 33900) \
+ && (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
+ || defined(BOOST_SGI_CPP_LIMITS))
+ // typedefs that act as compile time assertions
+ // (to be replaced by boost compile time assertions
+ // as and when they become available and are stable)
+ typedef bool argument_must_be_numeric[arg_traits::is_specialized];
+ typedef bool result_must_be_numeric[result_traits::is_specialized];
+
+ const bool arg_is_signed = arg_traits::is_signed;
+ const bool result_is_signed = result_traits::is_signed;
+ const bool same_sign = arg_is_signed == result_is_signed;
+
+ if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, (result_traits::min)())
+ || greater_than_type_max<same_sign, arg_is_signed>::check(arg, (result_traits::max)())
+ )
+
+#else // We need to use #pragma hacks if available
+
+# if BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4018)
+#elif defined(__BORLANDC__)
+#pragma option push -w-8012
+# endif
+ if ((arg < 0 && !result_traits::is_signed) // loss of negative range
+ || (arg_traits::is_signed && arg < (result_traits::min)()) // underflow
+ || arg > (result_traits::max)()) // overflow
+# if BOOST_MSVC
+# pragma warning(pop)
+#elif defined(__BORLANDC__)
+#pragma option pop
+# endif
+#endif
+ {
+ throw bad_numeric_cast();
+ }
+ return static_cast<Target>(arg);
+ } // numeric_cast
+
+# undef BOOST_EXPLICIT_DEFAULT_TARGET
+
+} // namespace boost
+
+#endif // BOOST_OLD_NUMERIC_CAST_HPP
--- /dev/null
+//
+//! Copyright (c) 2011-2012
+//! Brandon Kohn
+//
+// 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)
+//
+
+
+
+namespace boost { namespace numeric {
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , signed char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<signed char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , unsigned char
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned char> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , unsigned short
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned short> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , unsigned int
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned int> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , unsigned long
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<unsigned long> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , float
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<float> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<double> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , long double
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<long double> rounding_policy;
+ };
+}}
--- /dev/null
+//
+//! Copyright (c) 2011-2012
+//! Brandon Kohn
+//
+// 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)
+//
+namespace boost { namespace numeric {
+
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ char
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ signed char
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned char
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ short
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned short
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ int
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned int
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ unsigned long
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ float
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ double
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ long double
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ boost::long_long_type
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ boost::long_long_type
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ boost::ulong_long_type
+ , boost::long_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::long_long_type> rounding_policy;
+ };
+
+ template <>
+ struct numeric_cast_traits
+ <
+ boost::ulong_long_type
+ , boost::ulong_long_type
+ >
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<boost::ulong_long_type> rounding_policy;
+ };
+}}
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_SIGN_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_SIGN_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/config.hpp"
+#include "boost/limits.hpp"
+
+#include "boost/numeric/conversion/sign_mixture_enum.hpp"
+#include "boost/numeric/conversion/detail/meta.hpp"
+
+#include "boost/mpl/integral_c.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ // Integral Constants for 'SignMixture'
+ typedef mpl::integral_c<sign_mixture_enum, unsigned_to_unsigned> unsig2unsig_c ;
+ typedef mpl::integral_c<sign_mixture_enum, signed_to_signed> sig2sig_c ;
+ typedef mpl::integral_c<sign_mixture_enum, signed_to_unsigned> sig2unsig_c ;
+ typedef mpl::integral_c<sign_mixture_enum, unsigned_to_signed> unsig2sig_c ;
+
+ // Metafunction:
+ //
+ // get_sign_mixture<T,S>::type
+ //
+ // Selects the appropriate SignMixture Integral Constant for the combination T,S.
+ //
+ template<class T,class S>
+ struct get_sign_mixture
+ {
+ typedef mpl::bool_< ::std::numeric_limits<S>::is_signed > S_signed ;
+ typedef mpl::bool_< ::std::numeric_limits<T>::is_signed > T_signed ;
+
+ typedef typename
+ for_both<S_signed, T_signed, sig2sig_c, sig2unsig_c, unsig2sig_c, unsig2unsig_c>::type
+ type ;
+ } ;
+
+ // Metafunction:
+ //
+ // for_sign_mixture<SignMixture,Sig2Sig,Sig2Unsig,Unsig2Sig,Unsig2Unsig>::type
+ //
+ // {SignMixture} is one of the Integral Constants for SignMixture, declared above.
+ // {Sig2Sig,Sig2Unsig,Unsig2Sig,Unsig2Unsig} are aribtrary types. (not metafunctions)
+ //
+ // According to the value of 'SignMixture', selects the corresponding type.
+ //
+ template<class SignMixture, class Sig2Sig, class Sig2Unsig, class Unsig2Sig, class Unsig2Unsig>
+ struct for_sign_mixture
+ {
+ typedef typename
+ ct_switch4<SignMixture
+ , sig2sig_c, sig2unsig_c, unsig2sig_c // default
+ , Sig2Sig , Sig2Unsig , Unsig2Sig , Unsig2Unsig
+ >::type
+ type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_UDT_BUILTIN_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_DETAIL_UDT_BUILTIN_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/type_traits/is_arithmetic.hpp"
+
+#include "boost/numeric/conversion/udt_builtin_mixture_enum.hpp"
+#include "boost/numeric/conversion/detail/meta.hpp"
+
+#include "boost/mpl/integral_c.hpp"
+
+namespace boost { namespace numeric { namespace convdetail
+{
+ // Integral Constants for 'UdtMixture'
+ typedef mpl::integral_c<udt_builtin_mixture_enum, builtin_to_builtin> builtin2builtin_c ;
+ typedef mpl::integral_c<udt_builtin_mixture_enum, builtin_to_udt> builtin2udt_c ;
+ typedef mpl::integral_c<udt_builtin_mixture_enum, udt_to_builtin> udt2builtin_c ;
+ typedef mpl::integral_c<udt_builtin_mixture_enum, udt_to_udt> udt2udt_c ;
+
+ // Metafunction:
+ //
+ // for_udt_mixture<UdtMixture,BuiltIn2BuiltIn,BuiltIn2Udt,Udt2BuiltIn,Udt2Udt>::type
+ //
+ // {UdtMixture} is one of the Integral Constants for UdMixture, declared above.
+ // {BuiltIn2BuiltIn,BuiltIn2Udt,Udt2BuiltIn,Udt2Udt} are aribtrary types. (not metafunctions)
+ //
+ // According to the value of 'UdtMixture', selects the corresponding type.
+ //
+ template<class UdtMixture, class BuiltIn2BuiltIn, class BuiltIn2Udt, class Udt2BuiltIn, class Udt2Udt>
+ struct for_udt_builtin_mixture
+ {
+ typedef typename
+ ct_switch4<UdtMixture
+ , builtin2builtin_c, builtin2udt_c, udt2builtin_c // default
+ , BuiltIn2BuiltIn , BuiltIn2Udt , Udt2BuiltIn , Udt2Udt
+ >::type
+ type ;
+ } ;
+
+ // Metafunction:
+ //
+ // get_udt_mixture<T,S>::type
+ //
+ // Selects the appropriate UdtMixture Integral Constant for the combination T,S.
+ //
+ template<class T,class S>
+ struct get_udt_builtin_mixture
+ {
+ typedef is_arithmetic<S> S_builtin ;
+ typedef is_arithmetic<T> T_builtin ;
+
+ typedef typename
+ for_both<S_builtin, T_builtin, builtin2builtin_c, builtin2udt_c, udt2builtin_c, udt2udt_c>::type
+ type ;
+ } ;
+
+} } } // namespace boost::numeric::convdetail
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_INT_FLOAT_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_INT_FLOAT_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/int_float_mixture.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class T, class S>
+struct int_float_mixture
+ : convdetail::get_int_float_mixture< BOOST_DEDUCED_TYPENAME remove_cv<T>::type
+ ,BOOST_DEDUCED_TYPENAME remove_cv<S>::type
+ >::type {} ;
+
+} } // namespace boost::numeric
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_INT_FLOAT_MIXTURE_ENUM_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_INT_FLOAT_MIXTURE_ENUM_FLC_12NOV2002_HPP
+
+namespace boost { namespace numeric
+{
+ enum int_float_mixture_enum
+ {
+ integral_to_integral
+ ,integral_to_float
+ ,float_to_integral
+ ,float_to_float
+ } ;
+
+} } // namespace boost::numeric
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_IS_SUBRANGED_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_IS_SUBRANGED_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/is_subranged.hpp"
+
+namespace boost { namespace numeric {
+
+template<class T, class S>
+struct is_subranged
+ : convdetail::get_is_subranged< BOOST_DEDUCED_TYPENAME remove_cv<T>::type
+ ,BOOST_DEDUCED_TYPENAME remove_cv<S>::type
+ >::type {} ;
+
+} } // namespace boost::numeric
+
+#endif
+
+
--- /dev/null
+//
+//! Copyright (c) 2011
+//! Brandon Kohn
+//
+// 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)
+//
+#ifndef BOOST_NUMERIC_CAST_TRAITS_HPP
+#define BOOST_NUMERIC_CAST_TRAITS_HPP
+
+#include <boost/numeric/conversion/converter_policies.hpp>
+
+namespace boost { namespace numeric {
+
+ template <typename Target, typename Source, typename EnableIf = void>
+ struct numeric_cast_traits
+ {
+ typedef def_overflow_handler overflow_policy;
+ typedef UseInternalRangeChecker range_checking_policy;
+ typedef Trunc<Source> rounding_policy;
+ };
+
+}}//namespace boost::numeric;
+
+#if !defined( BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS )
+#include <boost/cstdint.hpp>
+#include <boost/numeric/conversion/detail/numeric_cast_traits.hpp>
+#endif//!defined BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS
+
+#endif//BOOST_NUMERIC_CAST_TRAITS_HPP
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_SIGN_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_SIGN_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/sign_mixture.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class T, class S>
+struct sign_mixture
+ : convdetail::get_sign_mixture< BOOST_DEDUCED_TYPENAME remove_cv<T>::type
+ ,BOOST_DEDUCED_TYPENAME remove_cv<S>::type
+ >::type {} ;
+
+} } // namespace boost::numeric
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_SIGN_MIXTURE_ENUM_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_SIGN_MIXTURE_ENUM_FLC_12NOV2002_HPP
+
+namespace boost { namespace numeric
+{
+ enum sign_mixture_enum
+ {
+ unsigned_to_unsigned
+ ,signed_to_signed
+ ,signed_to_unsigned
+ ,unsigned_to_signed
+ } ;
+
+} } // namespace boost::numeric
+
+#endif
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_UDT_BUILTIN_MIXTURE_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_UDT_BUILTIN_MIXTURE_FLC_12NOV2002_HPP
+
+#include "boost/numeric/conversion/detail/udt_builtin_mixture.hpp"
+
+namespace boost { namespace numeric
+{
+
+template<class T, class S>
+struct udt_builtin_mixture
+ : convdetail::get_udt_builtin_mixture< BOOST_DEDUCED_TYPENAME remove_cv<T>::type
+ ,BOOST_DEDUCED_TYPENAME remove_cv<S>::type
+ >::type {} ;
+
+} } // namespace boost::numeric
+
+#endif
+
+
--- /dev/null
+// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
+// Use, modification, and distribution is subject to 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)
+
+// See library home page at http://www.boost.org/libs/numeric/conversion
+//
+// Contact the author at: fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NUMERIC_CONVERSION_UDT_BUILTIN_MIXTURE_ENUM_FLC_12NOV2002_HPP
+#define BOOST_NUMERIC_CONVERSION_UDT_BUILTIN_MIXTURE_ENUM_FLC_12NOV2002_HPP
+
+namespace boost { namespace numeric
+{
+ enum udt_builtin_mixture_enum
+ {
+ builtin_to_builtin
+ ,builtin_to_udt
+ ,udt_to_builtin
+ ,udt_to_udt
+ } ;
+
+} } // namespace boost::numeric
+
+#endif
+
--- /dev/null
+/* Boost interval.hpp header file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_HPP
+#define BOOST_NUMERIC_INTERVAL_HPP
+
+#include <boost/limits.hpp>
+#include <boost/numeric/interval/interval.hpp>
+#include <boost/numeric/interval/policies.hpp>
+
+#include <boost/numeric/interval/hw_rounding.hpp>
+#include <boost/numeric/interval/rounded_arith.hpp>
+#include <boost/numeric/interval/rounded_transc.hpp>
+#include <boost/numeric/interval/constants.hpp>
+
+#include <boost/numeric/interval/checking.hpp>
+#include <boost/numeric/interval/compare.hpp>
+#include <boost/numeric/interval/utility.hpp>
+
+#include <boost/numeric/interval/arith.hpp>
+#include <boost/numeric/interval/arith2.hpp>
+#include <boost/numeric/interval/arith3.hpp>
+#include <boost/numeric/interval/transc.hpp>
+
+#endif // BOOST_NUMERIC_INTERVAL_HPP
--- /dev/null
+/* Boost interval/arith.hpp template implementation file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ARITH_HPP
+#define BOOST_NUMERIC_INTERVAL_ARITH_HPP
+
+#include <boost/config.hpp>
+#include <boost/numeric/interval/interval.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/detail/division.hpp>
+#include <algorithm>
+
+namespace boost {
+namespace numeric {
+
+/*
+ * Basic arithmetic operators
+ */
+
+template<class T, class Policies> inline
+const interval<T, Policies>& operator+(const interval<T, Policies>& x)
+{
+ return x;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator-(const interval<T, Policies>& x)
+{
+ if (interval_lib::detail::test_input(x))
+ return interval<T, Policies>::empty();
+ return interval<T, Policies>(-x.upper(), -x.lower(), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator+=(const interval<T, Policies>& r)
+{
+ if (interval_lib::detail::test_input(*this, r))
+ set_empty();
+ else {
+ typename Policies::rounding rnd;
+ set(rnd.add_down(low, r.low), rnd.add_up(up, r.up));
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator+=(const T& r)
+{
+ if (interval_lib::detail::test_input(*this, r))
+ set_empty();
+ else {
+ typename Policies::rounding rnd;
+ set(rnd.add_down(low, r), rnd.add_up(up, r));
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator-=(const interval<T, Policies>& r)
+{
+ if (interval_lib::detail::test_input(*this, r))
+ set_empty();
+ else {
+ typename Policies::rounding rnd;
+ set(rnd.sub_down(low, r.up), rnd.sub_up(up, r.low));
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator-=(const T& r)
+{
+ if (interval_lib::detail::test_input(*this, r))
+ set_empty();
+ else {
+ typename Policies::rounding rnd;
+ set(rnd.sub_down(low, r), rnd.sub_up(up, r));
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator*=(const interval<T, Policies>& r)
+{
+ return *this = *this * r;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator*=(const T& r)
+{
+ return *this = r * *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator/=(const interval<T, Policies>& r)
+{
+ return *this = *this / r;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>& interval<T, Policies>::operator/=(const T& r)
+{
+ return *this = *this / r;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator+(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T,Policies>(rnd.add_down(x.lower(), y.lower()),
+ rnd.add_up (x.upper(), y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator+(const T& x, const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T,Policies>(rnd.add_down(x, y.lower()),
+ rnd.add_up (x, y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y)
+{ return y + x; }
+
+template<class T, class Policies> inline
+interval<T, Policies> operator-(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T,Policies>(rnd.sub_down(x.lower(), y.upper()),
+ rnd.sub_up (x.upper(), y.lower()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator-(const T& x, const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T,Policies>(rnd.sub_down(x, y.upper()),
+ rnd.sub_up (x, y.lower()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T,Policies>(rnd.sub_down(x.lower(), y),
+ rnd.sub_up (x.upper(), y), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator*(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ BOOST_USING_STD_MIN();
+ BOOST_USING_STD_MAX();
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ const T& yl = y.lower();
+ const T& yu = y.upper();
+
+ if (interval_lib::user::is_neg(xl))
+ if (interval_lib::user::is_pos(xu))
+ if (interval_lib::user::is_neg(yl))
+ if (interval_lib::user::is_pos(yu)) // M * M
+ return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.mul_down(xl, yu), rnd.mul_down(xu, yl)),
+ max BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.mul_up (xl, yl), rnd.mul_up (xu, yu)), true);
+ else // M * N
+ return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yl), true);
+ else
+ if (interval_lib::user::is_pos(yu)) // M * P
+ return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yu), true);
+ else // M * Z
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ else
+ if (interval_lib::user::is_neg(yl))
+ if (interval_lib::user::is_pos(yu)) // N * M
+ return I(rnd.mul_down(xl, yu), rnd.mul_up(xl, yl), true);
+ else // N * N
+ return I(rnd.mul_down(xu, yu), rnd.mul_up(xl, yl), true);
+ else
+ if (interval_lib::user::is_pos(yu)) // N * P
+ return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yl), true);
+ else // N * Z
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ else
+ if (interval_lib::user::is_pos(xu))
+ if (interval_lib::user::is_neg(yl))
+ if (interval_lib::user::is_pos(yu)) // P * M
+ return I(rnd.mul_down(xu, yl), rnd.mul_up(xu, yu), true);
+ else // P * N
+ return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yu), true);
+ else
+ if (interval_lib::user::is_pos(yu)) // P * P
+ return I(rnd.mul_down(xl, yl), rnd.mul_up(xu, yu), true);
+ else // P * Z
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ else // Z * ?
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator*(const T& x, const interval<T, Policies>& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ const T& yl = y.lower();
+ const T& yu = y.upper();
+ // x is supposed not to be infinite
+ if (interval_lib::user::is_neg(x))
+ return I(rnd.mul_down(x, yu), rnd.mul_up(x, yl), true);
+ else if (interval_lib::user::is_zero(x))
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ else
+ return I(rnd.mul_down(x, yl), rnd.mul_up(x, yu), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y)
+{ return y * x; }
+
+template<class T, class Policies> inline
+interval<T, Policies> operator/(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ if (zero_in(y))
+ if (!interval_lib::user::is_zero(y.lower()))
+ if (!interval_lib::user::is_zero(y.upper()))
+ return interval_lib::detail::div_zero(x);
+ else
+ return interval_lib::detail::div_negative(x, y.lower());
+ else
+ if (!interval_lib::user::is_zero(y.upper()))
+ return interval_lib::detail::div_positive(x, y.upper());
+ else
+ return interval<T, Policies>::empty();
+ else
+ return interval_lib::detail::div_non_zero(x, y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator/(const T& x, const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ if (zero_in(y))
+ if (!interval_lib::user::is_zero(y.lower()))
+ if (!interval_lib::user::is_zero(y.upper()))
+ return interval_lib::detail::div_zero<T, Policies>(x);
+ else
+ return interval_lib::detail::div_negative<T, Policies>(x, y.lower());
+ else
+ if (!interval_lib::user::is_zero(y.upper()))
+ return interval_lib::detail::div_positive<T, Policies>(x, y.upper());
+ else
+ return interval<T, Policies>::empty();
+ else
+ return interval_lib::detail::div_non_zero(x, y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y)
+{
+ if (interval_lib::detail::test_input(x, y) || interval_lib::user::is_zero(y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ if (interval_lib::user::is_neg(y))
+ return interval<T, Policies>(rnd.div_down(xu, y), rnd.div_up(xl, y), true);
+ else
+ return interval<T, Policies>(rnd.div_down(xl, y), rnd.div_up(xu, y), true);
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ARITH_HPP
--- /dev/null
+/* Boost interval/arith2.hpp template implementation file
+ *
+ * This header provides some auxiliary arithmetic
+ * functions: fmod, sqrt, square, pov, inverse and
+ * a multi-interval division.
+ *
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ARITH2_HPP
+#define BOOST_NUMERIC_INTERVAL_ARITH2_HPP
+
+#include <boost/config.hpp>
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/numeric/interval/detail/division.hpp>
+#include <boost/numeric/interval/arith.hpp>
+#include <boost/numeric/interval/policies.hpp>
+#include <algorithm>
+#include <cassert>
+#include <boost/config/no_tr1/cmath.hpp>
+
+namespace boost {
+namespace numeric {
+
+template<class T, class Policies> inline
+interval<T, Policies> fmod(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
+ T const &yb = interval_lib::user::is_neg(x.lower()) ? y.lower() : y.upper();
+ T n = rnd.int_down(rnd.div_down(x.lower(), yb));
+ return (const I&)x - n * (const I&)y;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> fmod(const interval<T, Policies>& x, const T& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
+ T n = rnd.int_down(rnd.div_down(x.lower(), y));
+ return (const I&)x - n * I(y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> fmod(const T& x, const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<interval<T, Policies> >::type I;
+ T const &yb = interval_lib::user::is_neg(x) ? y.lower() : y.upper();
+ T n = rnd.int_down(rnd.div_down(x, yb));
+ return x - n * (const I&)y;
+}
+
+namespace interval_lib {
+
+template<class T, class Policies> inline
+interval<T, Policies> division_part1(const interval<T, Policies>& x,
+ const interval<T, Policies>& y, bool& b)
+{
+ typedef interval<T, Policies> I;
+ b = false;
+ if (detail::test_input(x, y))
+ return I::empty();
+ if (zero_in(y))
+ if (!user::is_zero(y.lower()))
+ if (!user::is_zero(y.upper()))
+ return detail::div_zero_part1(x, y, b);
+ else
+ return detail::div_negative(x, y.lower());
+ else
+ if (!user::is_zero(y.upper()))
+ return detail::div_positive(x, y.upper());
+ else
+ return I::empty();
+ else
+ return detail::div_non_zero(x, y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> division_part2(const interval<T, Policies>& x,
+ const interval<T, Policies>& y, bool b = true)
+{
+ if (!b) return interval<T, Policies>::empty();
+ return detail::div_zero_part2(x, y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> multiplicative_inverse(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (detail::test_input(x))
+ return I::empty();
+ T one = static_cast<T>(1);
+ typename Policies::rounding rnd;
+ if (zero_in(x)) {
+ typedef typename Policies::checking checking;
+ if (!user::is_zero(x.lower()))
+ if (!user::is_zero(x.upper()))
+ return I::whole();
+ else
+ return I(checking::neg_inf(), rnd.div_up(one, x.lower()), true);
+ else
+ if (!user::is_zero(x.upper()))
+ return I(rnd.div_down(one, x.upper()), checking::pos_inf(), true);
+ else
+ return I::empty();
+ } else
+ return I(rnd.div_down(one, x.upper()), rnd.div_up(one, x.lower()), true);
+}
+
+namespace detail {
+
+template<class T, class Rounding> inline
+T pow_dn(const T& x_, int pwr, Rounding& rnd) // x and pwr are positive
+{
+ T x = x_;
+ T y = (pwr & 1) ? x_ : static_cast<T>(1);
+ pwr >>= 1;
+ while (pwr > 0) {
+ x = rnd.mul_down(x, x);
+ if (pwr & 1) y = rnd.mul_down(x, y);
+ pwr >>= 1;
+ }
+ return y;
+}
+
+template<class T, class Rounding> inline
+T pow_up(const T& x_, int pwr, Rounding& rnd) // x and pwr are positive
+{
+ T x = x_;
+ T y = (pwr & 1) ? x_ : static_cast<T>(1);
+ pwr >>= 1;
+ while (pwr > 0) {
+ x = rnd.mul_up(x, x);
+ if (pwr & 1) y = rnd.mul_up(x, y);
+ pwr >>= 1;
+ }
+ return y;
+}
+
+} // namespace detail
+} // namespace interval_lib
+
+template<class T, class Policies> inline
+interval<T, Policies> pow(const interval<T, Policies>& x, int pwr)
+{
+ BOOST_USING_STD_MAX();
+ using interval_lib::detail::pow_dn;
+ using interval_lib::detail::pow_up;
+ typedef interval<T, Policies> I;
+
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+
+ if (pwr == 0)
+ if (interval_lib::user::is_zero(x.lower())
+ && interval_lib::user::is_zero(x.upper()))
+ return I::empty();
+ else
+ return I(static_cast<T>(1));
+ else if (pwr < 0)
+ return interval_lib::multiplicative_inverse(pow(x, -pwr));
+
+ typename Policies::rounding rnd;
+
+ if (interval_lib::user::is_neg(x.upper())) { // [-2,-1]
+ T yl = pow_dn(static_cast<T>(-x.upper()), pwr, rnd);
+ T yu = pow_up(static_cast<T>(-x.lower()), pwr, rnd);
+ if (pwr & 1) // [-2,-1]^1
+ return I(-yu, -yl, true);
+ else // [-2,-1]^2
+ return I(yl, yu, true);
+ } else if (interval_lib::user::is_neg(x.lower())) { // [-1,1]
+ if (pwr & 1) { // [-1,1]^1
+ return I(-pow_up(static_cast<T>(-x.lower()), pwr, rnd), pow_up(x.upper(), pwr, rnd), true);
+ } else { // [-1,1]^2
+ return I(static_cast<T>(0), pow_up(max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper()), pwr, rnd), true);
+ }
+ } else { // [1,2]
+ return I(pow_dn(x.lower(), pwr, rnd), pow_up(x.upper(), pwr, rnd), true);
+ }
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> sqrt(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x) || interval_lib::user::is_neg(x.upper()))
+ return I::empty();
+ typename Policies::rounding rnd;
+ T l = !interval_lib::user::is_pos(x.lower()) ? static_cast<T>(0) : rnd.sqrt_down(x.lower());
+ return I(l, rnd.sqrt_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> square(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ if (interval_lib::user::is_neg(xu))
+ return I(rnd.mul_down(xu, xu), rnd.mul_up(xl, xl), true);
+ else if (interval_lib::user::is_pos(x.lower()))
+ return I(rnd.mul_down(xl, xl), rnd.mul_up(xu, xu), true);
+ else
+ return I(static_cast<T>(0), (-xl > xu ? rnd.mul_up(xl, xl) : rnd.mul_up(xu, xu)), true);
+}
+
+namespace interval_lib {
+namespace detail {
+
+template< class I > inline
+I root_aux(typename I::base_type const &x, int k) // x and k are bigger than one
+{
+ typedef typename I::base_type T;
+ T tk(k);
+ I y(static_cast<T>(1), x, true);
+ for(;;) {
+ T y0 = median(y);
+ I yy = intersect(y, y0 - (pow(I(y0, y0, true), k) - x) / (tk * pow(y, k - 1)));
+ if (equal(y, yy)) return y;
+ y = yy;
+ }
+}
+
+template< class I > inline // x is positive and k bigger than one
+typename I::base_type root_aux_dn(typename I::base_type const &x, int k)
+{
+ typedef typename I::base_type T;
+ typedef typename I::traits_type Policies;
+ typename Policies::rounding rnd;
+ T one(1);
+ if (x > one) return root_aux<I>(x, k).lower();
+ if (x == one) return one;
+ return rnd.div_down(one, root_aux<I>(rnd.div_up(one, x), k).upper());
+}
+
+template< class I > inline // x is positive and k bigger than one
+typename I::base_type root_aux_up(typename I::base_type const &x, int k)
+{
+ typedef typename I::base_type T;
+ typedef typename I::traits_type Policies;
+ typename Policies::rounding rnd;
+ T one(1);
+ if (x > one) return root_aux<I>(x, k).upper();
+ if (x == one) return one;
+ return rnd.div_up(one, root_aux<I>(rnd.div_down(one, x), k).lower());
+}
+
+} // namespace detail
+} // namespace interval_lib
+
+template< class T, class Policies > inline
+interval<T, Policies> nth_root(interval<T, Policies> const &x, int k)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x)) return I::empty();
+ assert(k > 0);
+ if (k == 1) return x;
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<I>::type R;
+ if (!interval_lib::user::is_pos(x.upper())) {
+ if (interval_lib::user::is_zero(x.upper())) {
+ T zero(0);
+ if (!(k & 1) || interval_lib::user::is_zero(x.lower())) // [-1,0]^/2 or [0,0]
+ return I(zero, zero, true);
+ else // [-1,0]^/3
+ return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k), zero, true);
+ } else if (!(k & 1)) // [-2,-1]^/2
+ return I::empty();
+ else { // [-2,-1]^/3
+ return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k),
+ -interval_lib::detail::root_aux_dn<R>(-x.upper(), k), true);
+ }
+ }
+ T u = interval_lib::detail::root_aux_up<R>(x.upper(), k);
+ if (!interval_lib::user::is_pos(x.lower()))
+ if (!(k & 1) || interval_lib::user::is_zero(x.lower())) // [-1,1]^/2 or [0,1]
+ return I(static_cast<T>(0), u, true);
+ else // [-1,1]^/3
+ return I(-interval_lib::detail::root_aux_up<R>(-x.lower(), k), u, true);
+ else // [1,2]
+ return I(interval_lib::detail::root_aux_dn<R>(x.lower(), k), u, true);
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ARITH2_HPP
--- /dev/null
+/* Boost interval/arith3.hpp template implementation file
+ *
+ * This headers provides arithmetical functions
+ * which compute an interval given some base
+ * numbers. The resulting interval encloses the
+ * real result of the arithmetic operation.
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ARITH3_HPP
+#define BOOST_NUMERIC_INTERVAL_ARITH3_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+template<class I> inline
+I add(const typename I::base_type& x, const typename I::base_type& y)
+{
+ typedef typename I::traits_type Policies;
+ if (detail::test_input<typename I::base_type, Policies>(x, y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.add_down(x, y), rnd.add_up(x, y), true);
+}
+
+template<class I> inline
+I sub(const typename I::base_type& x, const typename I::base_type& y)
+{
+ typedef typename I::traits_type Policies;
+ if (detail::test_input<typename I::base_type, Policies>(x, y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.sub_down(x, y), rnd.sub_up(x, y), true);
+}
+
+template<class I> inline
+I mul(const typename I::base_type& x, const typename I::base_type& y)
+{
+ typedef typename I::traits_type Policies;
+ if (detail::test_input<typename I::base_type, Policies>(x, y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.mul_down(x, y), rnd.mul_up(x, y), true);
+}
+
+template<class I> inline
+I div(const typename I::base_type& x, const typename I::base_type& y)
+{
+ typedef typename I::traits_type Policies;
+ if (detail::test_input<typename I::base_type, Policies>(x, y) || user::is_zero(y))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.div_down(x, y), rnd.div_up(x, y), true);
+}
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ARITH3_HPP
--- /dev/null
+/* Boost interval/checking.hpp template implementation file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_CHECKING_HPP
+#define BOOST_NUMERIC_INTERVAL_CHECKING_HPP
+
+#include <stdexcept>
+#include <string>
+#include <cassert>
+#include <boost/limits.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+struct exception_create_empty
+{
+ void operator()()
+ {
+ throw std::runtime_error("boost::interval: empty interval created");
+ }
+};
+
+struct exception_invalid_number
+{
+ void operator()()
+ {
+ throw std::invalid_argument("boost::interval: invalid number");
+ }
+};
+
+template<class T>
+struct checking_base
+{
+ static T pos_inf()
+ {
+ assert(std::numeric_limits<T>::has_infinity);
+ return std::numeric_limits<T>::infinity();
+ }
+ static T neg_inf()
+ {
+ assert(std::numeric_limits<T>::has_infinity);
+ return -std::numeric_limits<T>::infinity();
+ }
+ static T nan()
+ {
+ assert(std::numeric_limits<T>::has_quiet_NaN);
+ return std::numeric_limits<T>::quiet_NaN();
+ }
+ static bool is_nan(const T& x)
+ {
+ return std::numeric_limits<T>::has_quiet_NaN && (x != x);
+ }
+ static T empty_lower()
+ {
+ return (std::numeric_limits<T>::has_quiet_NaN ?
+ std::numeric_limits<T>::quiet_NaN() : static_cast<T>(1));
+ }
+ static T empty_upper()
+ {
+ return (std::numeric_limits<T>::has_quiet_NaN ?
+ std::numeric_limits<T>::quiet_NaN() : static_cast<T>(0));
+ }
+ static bool is_empty(const T& l, const T& u)
+ {
+ return !(l <= u); // safety for partial orders
+ }
+};
+
+template<class T, class Checking = checking_base<T>,
+ class Exception = exception_create_empty>
+struct checking_no_empty: Checking
+{
+ static T nan()
+ {
+ assert(false);
+ return Checking::nan();
+ }
+ static T empty_lower()
+ {
+ Exception()();
+ return Checking::empty_lower();
+ }
+ static T empty_upper()
+ {
+ Exception()();
+ return Checking::empty_upper();
+ }
+ static bool is_empty(const T&, const T&)
+ {
+ return false;
+ }
+};
+
+template<class T, class Checking = checking_base<T> >
+struct checking_no_nan: Checking
+{
+ static bool is_nan(const T&)
+ {
+ return false;
+ }
+};
+
+template<class T, class Checking = checking_base<T>,
+ class Exception = exception_invalid_number>
+struct checking_catch_nan: Checking
+{
+ static bool is_nan(const T& x)
+ {
+ if (Checking::is_nan(x)) Exception()();
+ return false;
+ }
+};
+
+template<class T>
+struct checking_strict:
+ checking_no_nan<T, checking_no_empty<T> >
+{};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_CHECKING_HPP
--- /dev/null
+/* Boost interval/compare.hpp template implementation file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_HPP
+
+#include <boost/numeric/interval/compare/certain.hpp>
+#include <boost/numeric/interval/compare/possible.hpp>
+#include <boost/numeric/interval/compare/explicit.hpp>
+#include <boost/numeric/interval/compare/lexicographic.hpp>
+#include <boost/numeric/interval/compare/set.hpp>
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_HPP
--- /dev/null
+/* Boost interval/compare/certain.hpp template implementation file
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_CERTAIN_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_CERTAIN_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace compare {
+namespace certain {
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() < y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator<(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() < y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() <= y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator<=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() <= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() > y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator>(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() > y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() >= y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator>=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() >= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator==(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() == y.lower() && x.lower() == y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator==(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() == y && x.lower() == y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator!=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() < y.lower() || x.lower() > y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator!=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() < y || x.lower() > y;
+}
+
+} // namespace certain
+} // namespace compare
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_CERTAIN_HPP
--- /dev/null
+/* Boost interval/compare/explicit.hpp template implementation file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_EXPLICIT_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_EXPLICIT_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+/*
+ * Certainly... operations
+ */
+
+template<class T, class Policies1, class Policies2> inline
+bool cerlt(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() < y.lower();
+}
+
+template<class T, class Policies> inline
+bool cerlt(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() < y;
+}
+
+template<class T, class Policies> inline
+bool cerlt(const T& x, const interval<T, Policies>& y)
+{
+ return x < y.lower();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool cerle(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() <= y.lower();
+}
+
+template<class T, class Policies> inline
+bool cerle(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() <= y;
+}
+
+template<class T, class Policies> inline
+bool cerle(const T& x, const interval<T, Policies>& y)
+{
+ return x <= y.lower();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool cergt(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.lower() > y.upper();
+}
+
+template<class T, class Policies> inline
+bool cergt(const interval<T, Policies>& x, const T& y)
+{
+ return x.lower() > y;
+}
+
+template<class T, class Policies> inline
+bool cergt(const T& x, const interval<T, Policies>& y)
+{
+ return x > y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool cerge(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.lower() >= y.upper();
+}
+
+template<class T, class Policies> inline
+bool cerge(const interval<T, Policies>& x, const T& y)
+{
+ return x.lower() >= y;
+}
+
+template<class T, class Policies> inline
+bool cerge(const T& x, const interval<T, Policies>& y)
+{
+ return x >= y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool cereq(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.lower() == y.upper() && y.lower() == x.upper();
+}
+
+template<class T, class Policies> inline
+bool cereq(const interval<T, Policies>& x, const T& y)
+{
+ return x.lower() == y && x.upper() == y;
+}
+
+template<class T, class Policies> inline
+bool cereq(const T& x, const interval<T, Policies>& y)
+{
+ return x == y.lower() && x == y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool cerne(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() < y.lower() || y.upper() < x.lower();
+}
+
+template<class T, class Policies> inline
+bool cerne(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() < y || y < x.lower();
+}
+
+template<class T, class Policies> inline
+bool cerne(const T& x, const interval<T, Policies>& y)
+{
+ return x < y.lower() || y.upper() < x;
+}
+
+/*
+ * Possibly... comparisons
+ */
+
+template<class T, class Policies1, class Policies2> inline
+bool poslt(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.lower() < y.upper();
+}
+
+template<class T, class Policies> inline
+bool poslt(const interval<T, Policies>& x, const T& y)
+{
+ return x.lower() < y;
+}
+
+template<class T, class Policies> inline
+bool poslt(const T& x, const interval<T, Policies>& y)
+{
+ return x < y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool posle(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.lower() <= y.upper();
+}
+
+template<class T, class Policies> inline
+bool posle(const interval<T, Policies>& x, const T& y)
+{
+ return x.lower() <= y;
+}
+
+template<class T, class Policies> inline
+bool posle(const T& x, const interval<T, Policies>& y)
+{
+ return x <= y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool posgt(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() > y.lower();
+}
+
+template<class T, class Policies> inline
+bool posgt(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() > y;
+}
+
+template<class T, class Policies> inline
+bool posgt(const T& x, const interval<T, Policies> & y)
+{
+ return x > y.lower();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool posge(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() >= y.lower();
+}
+
+template<class T, class Policies> inline
+bool posge(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() >= y;
+}
+
+template<class T, class Policies> inline
+bool posge(const T& x, const interval<T, Policies>& y)
+{
+ return x >= y.lower();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool poseq(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() >= y.lower() && y.upper() >= x.lower();
+}
+
+template<class T, class Policies> inline
+bool poseq(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() >= y && y >= x.lower();
+}
+
+template<class T, class Policies> inline
+bool poseq(const T& x, const interval<T, Policies>& y)
+{
+ return x >= y.lower() && y.upper() >= x;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool posne(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return x.upper() != y.lower() || y.upper() != x.lower();
+}
+
+template<class T, class Policies> inline
+bool posne(const interval<T, Policies>& x, const T& y)
+{
+ return x.upper() != y || y != x.lower();
+}
+
+template<class T, class Policies> inline
+bool posne(const T& x, const interval<T, Policies>& y)
+{
+ return x != y.lower() || y.upper() != x;
+}
+
+} // namespace interval_lib
+} // namespace numeric
+} //namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_EXPLICIT_HPP
--- /dev/null
+/* Boost interval/compare/lexicographic.hpp template implementation file
+ *
+ * Copyright 2002-2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_LEXICOGRAPHIC_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_LEXICOGRAPHIC_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace compare {
+namespace lexicographic {
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ const T& yl = y.lower();
+ return xl < yl || (xl == yl && x.upper() < y.upper());
+}
+
+template<class T, class Policies> inline
+bool operator<(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() < y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ const T& yl = y.lower();
+ return xl < yl || (xl == yl && x.upper() <= y.upper());
+}
+
+template<class T, class Policies> inline
+bool operator<=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ return xl < y || (xl == y && x.upper() <= y);
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ const T& yl = y.lower();
+ return xl > yl || (xl == yl && x.upper() > y.upper());
+}
+
+template<class T, class Policies> inline
+bool operator>(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ return xl > y || (xl == y && x.upper() > y);
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ const T& xl = x.lower();
+ const T& yl = y.lower();
+ return xl > yl || (xl == yl && x.upper() >= y.upper());
+}
+
+template<class T, class Policies> inline
+bool operator>=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() >= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator==(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() == y.lower() && x.upper() == y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator==(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() == y && x.upper() == y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator!=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() != y.lower() || x.upper() != y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator!=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() != y || x.upper() != y;
+}
+
+} // namespace lexicographic
+} // namespace compare
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_LEXICOGRAPHIC_HPP
--- /dev/null
+/* Boost interval/compare/possible.hpp template implementation file
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_POSSIBLE_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_POSSIBLE_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace compare {
+namespace possible {
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() < y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator<(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() < y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() <= y.upper();
+}
+
+template<class T, class Policies> inline
+bool operator<=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() <= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() > y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator>(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() > y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() >= y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator>=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.upper() >= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator==(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() <= y.upper() && x.upper() >= y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator==(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() <= y && x.upper() >= y;
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator!=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() != y.upper() || x.upper() != y.lower();
+}
+
+template<class T, class Policies> inline
+bool operator!=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ return x.lower() != y || x.upper() != y;
+}
+
+} // namespace possible
+} // namespace compare
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_POSSIBLE_HPP
--- /dev/null
+/* Boost interval/compare/set.hpp template implementation file
+ *
+ * Copyright 2002-2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_SET_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_SET_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/utility.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace compare {
+namespace set {
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return proper_subset(x, y);
+}
+
+template<class T, class Policies> inline
+bool operator<(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator<=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return subset(x, y);
+}
+
+template<class T, class Policies> inline
+bool operator<=(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return proper_subset(y, x);
+}
+
+template<class T, class Policies> inline
+bool operator>(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator>=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return subset(y, x);
+}
+
+template<class T, class Policies> inline
+bool operator>=(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator==(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return equal(y, x);
+}
+
+template<class T, class Policies> inline
+bool operator==(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool operator!=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ return !equal(y, x);
+}
+
+template<class T, class Policies> inline
+bool operator!=(const interval<T, Policies>& x, const T& y)
+{
+ throw comparison_error();
+}
+
+} // namespace set
+} // namespace compare
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_SET_HPP
--- /dev/null
+/* Boost interval/compare/tribool.hpp template implementation file
+ *
+ * Copyright 2002-2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_COMPARE_TRIBOOL_HPP
+#define BOOST_NUMERIC_INTERVAL_COMPARE_TRIBOOL_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/logic/tribool.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace compare {
+namespace tribool {
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator<(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() < y.lower()) return true;
+ if (x.lower() >= y.upper()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator<(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() < y) return true;
+ if (x.lower() >= y) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator<=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() <= y.lower()) return true;
+ if (x.lower() > y.upper()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator<=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() <= y) return true;
+ if (x.lower() > y) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator>(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.lower() > y.upper()) return true;
+ if (x.upper() <= y.lower()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator>(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.lower() > y) return true;
+ if (x.upper() <= y) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator>=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.lower() >= y.upper()) return true;
+ if (x.upper() < y.lower()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator>=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.lower() >= y) return true;
+ if (x.upper() < y) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator==(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() == y.lower() && x.lower() == y.upper()) return true;
+ if (x.upper() < y.lower() || x.lower() > y.upper()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator==(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() == y && x.lower() == y) return true;
+ if (x.upper() < y || x.lower() > y) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies1, class Policies2> inline
+logic::tribool operator!=(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() < y.lower() || x.lower() > y.upper()) return true;
+ if (x.upper() == y.lower() && x.lower() == y.upper()) return false;
+ return logic::indeterminate;
+}
+
+template<class T, class Policies> inline
+logic::tribool operator!=(const interval<T, Policies>& x, const T& y)
+{
+ if (detail::test_input(x, y)) throw comparison_error();
+ if (x.upper() < y || x.lower() > y) return true;
+ if (x.upper() == y && x.lower() == y) return false;
+ return logic::indeterminate;
+}
+
+} // namespace tribool
+} // namespace compare
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+
+#endif // BOOST_NUMERIC_INTERVAL_COMPARE_TRIBOOL_HPP
--- /dev/null
+/* Boost interval/constants.hpp template implementation file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_CONSTANTS_HPP
+#define BOOST_NUMERIC_INTERVAL_CONSTANTS_HPP
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace constants {
+
+// These constants should be exactly computed.
+// Decimal representations wouldn't do it since the standard doesn't
+// specify the rounding (even nearest) that should be used.
+
+static const float pi_f_l = 13176794.0f/(1<<22);
+static const float pi_f_u = 13176795.0f/(1<<22);
+static const double pi_d_l = (3373259426.0 + 273688.0 / (1<<21)) / (1<<30);
+static const double pi_d_u = (3373259426.0 + 273689.0 / (1<<21)) / (1<<30);
+
+template<class T> inline T pi_lower() { return 3; }
+template<class T> inline T pi_upper() { return 4; }
+template<class T> inline T pi_half_lower() { return 1; }
+template<class T> inline T pi_half_upper() { return 2; }
+template<class T> inline T pi_twice_lower() { return 6; }
+template<class T> inline T pi_twice_upper() { return 7; }
+
+template<> inline float pi_lower<float>() { return pi_f_l; }
+template<> inline float pi_upper<float>() { return pi_f_u; }
+template<> inline float pi_half_lower<float>() { return pi_f_l / 2; }
+template<> inline float pi_half_upper<float>() { return pi_f_u / 2; }
+template<> inline float pi_twice_lower<float>() { return pi_f_l * 2; }
+template<> inline float pi_twice_upper<float>() { return pi_f_u * 2; }
+
+template<> inline double pi_lower<double>() { return pi_d_l; }
+template<> inline double pi_upper<double>() { return pi_d_u; }
+template<> inline double pi_half_lower<double>() { return pi_d_l / 2; }
+template<> inline double pi_half_upper<double>() { return pi_d_u / 2; }
+template<> inline double pi_twice_lower<double>() { return pi_d_l * 2; }
+template<> inline double pi_twice_upper<double>() { return pi_d_u * 2; }
+
+template<> inline long double pi_lower<long double>() { return pi_d_l; }
+template<> inline long double pi_upper<long double>() { return pi_d_u; }
+template<> inline long double pi_half_lower<long double>() { return pi_d_l / 2; }
+template<> inline long double pi_half_upper<long double>() { return pi_d_u / 2; }
+template<> inline long double pi_twice_lower<long double>() { return pi_d_l * 2; }
+template<> inline long double pi_twice_upper<long double>() { return pi_d_u * 2; }
+
+} // namespace constants
+
+template<class I> inline
+I pi()
+{
+ typedef typename I::base_type T;
+ return I(constants::pi_lower<T>(),
+ constants::pi_upper<T>(), true);
+}
+
+template<class I> inline
+I pi_half()
+{
+ typedef typename I::base_type T;
+ return I(constants::pi_half_lower<T>(),
+ constants::pi_half_upper<T>(), true);
+}
+
+template<class I> inline
+I pi_twice()
+{
+ typedef typename I::base_type T;
+ return I(constants::pi_twice_lower<T>(),
+ constants::pi_twice_upper<T>(), true);
+}
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_CONSTANTS_HPP
--- /dev/null
+/* Boost interval/detail/alpha_rounding_control.hpp file
+ *
+ * Copyright 2005 Felix Höfling, Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP
+
+#if !defined(alpha) && !defined(__alpha__)
+#error This header only works on Alpha CPUs.
+#endif
+
+#if defined(__GNUC__) || defined(__digital__) || defined(__DECCXX)
+
+#include <float.h> // write_rnd() and read_rnd()
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+namespace detail {
+#if defined(__GNUC__ )
+ typedef union {
+ ::boost::long_long_type imode;
+ double dmode;
+ } rounding_mode_struct;
+
+ // set bits 59-58 (DYN),
+ // clear all exception bits and disable overflow (51) and inexact exceptions (62)
+ static const rounding_mode_struct mode_upward = { 0x4C08000000000000LL };
+ static const rounding_mode_struct mode_downward = { 0x4408000000000000LL };
+ static const rounding_mode_struct mode_to_nearest = { 0x4808000000000000LL };
+ static const rounding_mode_struct mode_toward_zero = { 0x4008000000000000LL };
+
+ struct alpha_rounding_control
+ {
+ typedef double rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode mode)
+ { __asm__ __volatile__ ("mt_fpcr %0" : : "f"(mode)); }
+
+ static void get_rounding_mode(rounding_mode& mode)
+ { __asm__ __volatile__ ("mf_fpcr %0" : "=f"(mode)); }
+
+ static void downward() { set_rounding_mode(mode_downward.dmode); }
+ static void upward() { set_rounding_mode(mode_upward.dmode); }
+ static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); }
+ static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); }
+ };
+#elif defined(__digital__) || defined(__DECCXX)
+
+#if defined(__DECCXX) && !(defined(__FLT_ROUNDS) && __FLT_ROUNDS == -1)
+#error Dynamic rounding mode not enabled. See cxx man page for details.
+#endif
+
+ struct alpha_rounding_control
+ {
+ typedef unsigned int rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode& mode) { write_rnd(mode); }
+ static void get_rounding_mode(rounding_mode& mode) { mode = read_rnd(); }
+
+ static void downward() { set_rounding_mode(FP_RND_RM); }
+ static void upward() { set_rounding_mode(FP_RND_RP); }
+ static void to_nearest() { set_rounding_mode(FP_RND_RN); }
+ static void toward_zero() { set_rounding_mode(FP_RND_RZ); }
+ };
+#endif
+} // namespace detail
+
+extern "C" {
+ float rintf(float);
+ double rint(double);
+ long double rintl(long double);
+}
+
+template<>
+struct rounding_control<float>:
+ detail::alpha_rounding_control
+{
+ static float force_rounding(const float r)
+ { volatile float _r = r; return _r; }
+ static float to_int(const float& x) { return rintf(x); }
+};
+
+template<>
+struct rounding_control<double>:
+ detail::alpha_rounding_control
+{
+ static const double & force_rounding(const double& r) { return r; }
+ static double to_int(const double& r) { return rint(r); }
+};
+
+template<>
+struct rounding_control<long double>:
+ detail::alpha_rounding_control
+{
+ static const long double & force_rounding(const long double& r) { return r; }
+ static long double to_int(const long double& r) { return rintl(r); }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+#endif
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_ALPHA_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/bcc_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_BCC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_BCC_ROUNDING_CONTROL_HPP
+
+#ifndef __BORLANDC__
+# error This header is only intended for Borland C++.
+#endif
+
+#ifndef _M_IX86
+# error This header only works on x86 CPUs.
+#endif
+
+#include <float.h> // Borland C++ rounding control
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+#ifndef BOOST_NUMERIC_INTERVAL_KEEP_EXCEPTIONS_FOR_BCC
+extern "C" { unsigned int _RTLENTRY _fm_init(void); }
+
+struct borland_workaround {
+ borland_workaround() { _fm_init(); }
+};
+
+static borland_workaround borland_workaround_exec;
+#endif // BOOST_NUMERIC_INTERVAL_KEEP_EXCEPTIONS_FOR_BCC
+
+__inline double rint(double)
+{ __emit__(0xD9); __emit__(0xFC); /* asm FRNDINT */ }
+
+struct x86_rounding
+{
+ typedef unsigned int rounding_mode;
+ static void get_rounding_mode(rounding_mode& mode)
+ { mode = _control87(0, 0); }
+ static void set_rounding_mode(const rounding_mode mode)
+ { _control87(mode, 0xffff); }
+ static double to_int(const double& x) { return rint(x); }
+};
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_BCC_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/bugs.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_BUGS
+#define BOOST_NUMERIC_INTERVAL_DETAIL_BUGS
+
+#include <boost/config.hpp>
+
+#if defined(__GLIBC__) && (defined(__USE_MISC) || defined(__USE_XOPEN_EXTENDED) || defined(__USE_ISOC99)) && !defined(__ICC)
+# define BOOST_HAS_INV_HYPERBOLIC
+#endif
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+# define BOOST_NUMERIC_INTERVAL_using_math(a) using ::a
+# ifdef BOOST_HAS_INV_HYPERBOLIC
+# define BOOST_NUMERIC_INTERVAL_using_ahyp(a) using ::a
+# endif
+#else
+# define BOOST_NUMERIC_INTERVAL_using_math(a) using std::a
+# if defined(BOOST_HAS_INV_HYPERBOLIC)
+# if defined(__GLIBCPP__) || defined(__GLIBCXX__)
+# define BOOST_NUMERIC_INTERVAL_using_ahyp(a) using ::a
+# else
+# define BOOST_NUMERIC_INTERVAL_using_ahyp(a) using std::a
+# endif
+# endif
+#endif
+
+#if defined(__COMO__) || defined(BOOST_INTEL)
+# define BOOST_NUMERIC_INTERVAL_using_max(a) using std::a
+#elif defined(BOOST_NO_STDC_NAMESPACE)
+# define BOOST_NUMERIC_INTERVAL_using_max(a) using ::a
+#else
+# define BOOST_NUMERIC_INTERVAL_using_max(a) using std::a
+#endif
+
+#ifndef BOOST_NUMERIC_INTERVAL_using_ahyp
+# define BOOST_NUMERIC_INTERVAL_using_ahyp(a)
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ <= 2)
+// cf PR c++/1981 for a description of the bug
+#include <algorithm>
+#include <boost/config/no_tr1/cmath.hpp>
+namespace boost {
+namespace numeric {
+ using std::min;
+ using std::max;
+ using std::sqrt;
+ using std::exp;
+ using std::log;
+ using std::cos;
+ using std::tan;
+ using std::asin;
+ using std::acos;
+ using std::atan;
+ using std::ceil;
+ using std::floor;
+ using std::sinh;
+ using std::cosh;
+ using std::tanh;
+# undef BOOST_NUMERIC_INTERVAL_using_max
+# undef BOOST_NUMERIC_INTERVAL_using_math
+# define BOOST_NUMERIC_INTERVAL_using_max(a)
+# define BOOST_NUMERIC_INTERVAL_using_math(a)
+# undef BOOST_NUMERIC_INTERVAL_using_ahyp
+# define BOOST_NUMERIC_INTERVAL_using_ahyp(a)
+} // namespace numeric
+} // namespace boost
+#endif
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_BUGS
--- /dev/null
+/* Boost interval/detail/c99_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_C99_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_C99_ROUNDING_CONTROL_HPP
+
+#include <boost/numeric/interval/detail/c99sub_rounding_control.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+template<>
+struct rounding_control<float>:
+ detail::c99_rounding_control
+{
+ static float force_rounding(float const &r)
+ { volatile float r_ = r; return r_; }
+};
+
+template<>
+struct rounding_control<double>:
+ detail::c99_rounding_control
+{
+ static double force_rounding(double const &r)
+ { volatile double r_ = r; return r_; }
+};
+
+template<>
+struct rounding_control<long double>:
+ detail::c99_rounding_control
+{
+ static long double force_rounding(long double const &r)
+ { volatile long double r_ = r; return r_; }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_C99_ROUNDING_CONTROL_HPP
--- /dev/null
+/* Boost interval/detail/c99sub_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_C99SUB_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_C99SUB_ROUNDING_CONTROL_HPP
+
+#include <boost/detail/fenv.hpp> // ISO C 99 rounding mode control
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+extern "C" { double rint(double); }
+
+struct c99_rounding_control
+{
+ typedef int rounding_mode;
+
+ static void set_rounding_mode(rounding_mode mode) { fesetround(mode); }
+ static void get_rounding_mode(rounding_mode &mode) { mode = fegetround(); }
+ static void downward() { set_rounding_mode(FE_DOWNWARD); }
+ static void upward() { set_rounding_mode(FE_UPWARD); }
+ static void to_nearest() { set_rounding_mode(FE_TONEAREST); }
+ static void toward_zero() { set_rounding_mode(FE_TOWARDZERO); }
+
+ template<class T>
+ static T to_int(const T& r) { return rint(r); }
+};
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_C99SUB_ROUBDING_CONTROL_HPP
--- /dev/null
+/* Boost interval/detail/division.hpp file
+ *
+ * Copyright 2003 Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/rounded_arith.hpp>
+#include <algorithm>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+template<class T, class Policies> inline
+interval<T, Policies> div_non_zero(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ // assert(!in_zero(y));
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ const T& yl = y.lower();
+ const T& yu = y.upper();
+ if (::boost::numeric::interval_lib::user::is_neg(xu))
+ if (::boost::numeric::interval_lib::user::is_neg(yu))
+ return I(rnd.div_down(xu, yl), rnd.div_up(xl, yu), true);
+ else
+ return I(rnd.div_down(xl, yl), rnd.div_up(xu, yu), true);
+ else if (::boost::numeric::interval_lib::user::is_neg(xl))
+ if (::boost::numeric::interval_lib::user::is_neg(yu))
+ return I(rnd.div_down(xu, yu), rnd.div_up(xl, yu), true);
+ else
+ return I(rnd.div_down(xl, yl), rnd.div_up(xu, yl), true);
+ else
+ if (::boost::numeric::interval_lib::user::is_neg(yu))
+ return I(rnd.div_down(xu, yu), rnd.div_up(xl, yl), true);
+ else
+ return I(rnd.div_down(xl, yu), rnd.div_up(xu, yl), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_non_zero(const T& x, const interval<T, Policies>& y)
+{
+ // assert(!in_zero(y));
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ const T& yl = y.lower();
+ const T& yu = y.upper();
+ if (::boost::numeric::interval_lib::user::is_neg(x))
+ return I(rnd.div_down(x, yl), rnd.div_up(x, yu), true);
+ else
+ return I(rnd.div_down(x, yu), rnd.div_up(x, yl), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_positive(const interval<T, Policies>& x, const T& yu)
+{
+ // assert(::boost::numeric::interval_lib::user::is_pos(yu));
+ if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
+ ::boost::numeric::interval_lib::user::is_zero(x.upper()))
+ return x;
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(xu))
+ return I(checking::neg_inf(), rnd.div_up(xu, yu), true);
+ else if (::boost::numeric::interval_lib::user::is_neg(xl))
+ return I(checking::neg_inf(), checking::pos_inf(), true);
+ else
+ return I(rnd.div_down(xl, yu), checking::pos_inf(), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_positive(const T& x, const T& yu)
+{
+ // assert(::boost::numeric::interval_lib::user::is_pos(yu));
+ typedef interval<T, Policies> I;
+ if (::boost::numeric::interval_lib::user::is_zero(x))
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ typename Policies::rounding rnd;
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(x))
+ return I(checking::neg_inf(), rnd.div_up(x, yu), true);
+ else
+ return I(rnd.div_down(x, yu), checking::pos_inf(), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_negative(const interval<T, Policies>& x, const T& yl)
+{
+ // assert(::boost::numeric::interval_lib::user::is_neg(yl));
+ if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
+ ::boost::numeric::interval_lib::user::is_zero(x.upper()))
+ return x;
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(xu))
+ return I(rnd.div_down(xu, yl), checking::pos_inf(), true);
+ else if (::boost::numeric::interval_lib::user::is_neg(xl))
+ return I(checking::neg_inf(), checking::pos_inf(), true);
+ else
+ return I(checking::neg_inf(), rnd.div_up(xl, yl), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_negative(const T& x, const T& yl)
+{
+ // assert(::boost::numeric::interval_lib::user::is_neg(yl));
+ typedef interval<T, Policies> I;
+ if (::boost::numeric::interval_lib::user::is_zero(x))
+ return I(static_cast<T>(0), static_cast<T>(0), true);
+ typename Policies::rounding rnd;
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(x))
+ return I(rnd.div_down(x, yl), checking::pos_inf(), true);
+ else
+ return I(checking::neg_inf(), rnd.div_up(x, yl), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_zero(const interval<T, Policies>& x)
+{
+ if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
+ ::boost::numeric::interval_lib::user::is_zero(x.upper()))
+ return x;
+ else return interval<T, Policies>::whole();
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_zero(const T& x)
+{
+ if (::boost::numeric::interval_lib::user::is_zero(x))
+ return interval<T, Policies>(static_cast<T>(0), static_cast<T>(0), true);
+ else return interval<T, Policies>::whole();
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_zero_part1(const interval<T, Policies>& x,
+ const interval<T, Policies>& y, bool& b)
+{
+ // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()));
+ if (::boost::numeric::interval_lib::user::is_zero(x.lower()) && ::boost::numeric::interval_lib::user::is_zero(x.upper()))
+ { b = false; return x; }
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ const T& xl = x.lower();
+ const T& xu = x.upper();
+ const T& yl = y.lower();
+ const T& yu = y.upper();
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(xu))
+ { b = true; return I(checking::neg_inf(), rnd.div_up(xu, yu), true); }
+ else if (::boost::numeric::interval_lib::user::is_neg(xl))
+ { b = false; return I(checking::neg_inf(), checking::pos_inf(), true); }
+ else
+ { b = true; return I(checking::neg_inf(), rnd.div_up(xl, yl), true); }
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> div_zero_part2(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()) && (div_zero_part1(x, y, b), b));
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ typedef typename Policies::checking checking;
+ if (::boost::numeric::interval_lib::user::is_neg(x.upper()))
+ return I(rnd.div_down(x.upper(), y.lower()), checking::pos_inf(), true);
+ else
+ return I(rnd.div_down(x.lower(), y.upper()), checking::pos_inf(), true);
+}
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
--- /dev/null
+/* Boost interval/detail/ia64_rounding_control.hpp file
+ *
+ * Copyright 2006-2007 Boris Gubenko
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_IA64_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_IA64_ROUNDING_CONTROL_HPP
+
+#if !defined(ia64) && !defined(__ia64) && !defined(__ia64__)
+#error This header only works on ia64 CPUs.
+#endif
+
+#if defined(__hpux)
+
+# include <fenv.h>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+
+ struct ia64_rounding_control
+ {
+ typedef unsigned int rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode& mode) {
+fesetround(mode); }
+ static void get_rounding_mode(rounding_mode& mode) { mode = fegetround(); }
+
+ static void downward() { set_rounding_mode(FE_DOWNWARD); }
+ static void upward() { set_rounding_mode(FE_UPWARD); }
+ static void to_nearest() { set_rounding_mode(FE_TONEAREST); }
+ static void toward_zero() { set_rounding_mode(FE_TOWARDZERO); }
+ };
+
+} // namespace detail
+
+extern "C" {
+ float rintf(float);
+ double rint(double);
+ long double rintl(long double);
+}
+
+template<>
+struct rounding_control<float>:
+ detail::ia64_rounding_control
+{
+ static float force_rounding(const float r)
+ { volatile float _r = r; return _r; }
+ static float to_int(const float& x) { return rintf(x); }
+};
+
+template<>
+struct rounding_control<double>:
+ detail::ia64_rounding_control
+{
+ static const double & force_rounding(const double& r) { return r; }
+ static double to_int(const double& r) { return rint(r); }
+};
+
+template<>
+struct rounding_control<long double>:
+ detail::ia64_rounding_control
+{
+ static const long double & force_rounding(const long double& r) { return r; }
+ static long double to_int(const long double& r) { return rintl(r); }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+
+#endif /* __hpux */
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_IA64_ROUNDING_CONTROL_HPP */
+
--- /dev/null
+/* Boost interval/detail/interval_prototype.hpp file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_INTERVAL_PROTOTYPE_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_INTERVAL_PROTOTYPE_HPP
+
+namespace boost {
+namespace numeric {
+
+namespace interval_lib {
+
+template<class T> struct rounded_math;
+template<class T> struct checking_strict;
+class comparison_error;
+template<class Rounding, class Checking> struct policies;
+
+/*
+ * default policies class
+ */
+
+template<class T>
+struct default_policies
+{
+ typedef policies<rounded_math<T>, checking_strict<T> > type;
+};
+
+} // namespace interval_lib
+
+template<class T, class Policies = typename interval_lib::default_policies<T>::type >
+class interval;
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_INTERVAL_PROTOTYPE_HPP
--- /dev/null
+/* Boost interval/detail/msvc_rounding_control.hpp file
+ *
+ * Copyright 2000 Maarten Keijzer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP
+
+#ifndef _MSC_VER
+# error This header is only intended for MSVC, but might work for Borland as well
+#endif
+
+#include <float.h> // MSVC rounding control
+
+// Although the function is called _control87, it seems to work for
+// other FPUs too, so it does not have to be changed to _controlfp.
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+#if BOOST_MSVC < 1400 || defined(WIN64)
+extern "C" { double rint(double); }
+#else
+inline double rint(double x)
+{
+_asm FLD [x] ;
+_asm FRNDINT ;
+//_asm RET ;
+}
+#endif
+
+struct x86_rounding
+{
+ static unsigned int hard2msvc(unsigned short m) {
+ unsigned int n = 0;
+ if (m & 0x01) n |= _EM_INVALID;
+ if (m & 0x02) n |= _EM_DENORMAL;
+ if (m & 0x04) n |= _EM_ZERODIVIDE;
+ if (m & 0x08) n |= _EM_OVERFLOW;
+ if (m & 0x10) n |= _EM_UNDERFLOW;
+ if (m & 0x20) n |= _EM_INEXACT;
+ switch (m & 0x300) {
+ case 0x000: n |= _PC_24; break;
+ case 0x200: n |= _PC_53; break;
+ case 0x300: n |= _PC_64; break;
+ }
+ switch (m & 0xC00) {
+ case 0x000: n |= _RC_NEAR; break;
+ case 0x400: n |= _RC_DOWN; break;
+ case 0x800: n |= _RC_UP; break;
+ case 0xC00: n |= _RC_CHOP; break;
+ }
+ if (m & 0x1000) n |= _IC_AFFINE; // only useful on 287
+ return n;
+ }
+
+ static unsigned short msvc2hard(unsigned int n) {
+ unsigned short m = 0;
+ if (n & _EM_INVALID) m |= 0x01;
+ if (n & _EM_DENORMAL) m |= 0x02;
+ if (n & _EM_ZERODIVIDE) m |= 0x04;
+ if (n & _EM_OVERFLOW) m |= 0x08;
+ if (n & _EM_UNDERFLOW) m |= 0x10;
+ if (n & _EM_INEXACT) m |= 0x20;
+ switch (n & _MCW_RC) {
+ case _RC_NEAR: m |= 0x000; break;
+ case _RC_DOWN: m |= 0x400; break;
+ case _RC_UP: m |= 0x800; break;
+ case _RC_CHOP: m |= 0xC00; break;
+ }
+ switch (n & _MCW_PC) {
+ case _PC_24: m |= 0x000; break;
+ case _PC_53: m |= 0x200; break;
+ case _PC_64: m |= 0x300; break;
+ }
+ if ((n & _MCW_IC) == _IC_AFFINE) m |= 0x1000;
+ return m;
+ }
+
+ typedef unsigned short rounding_mode;
+ static void get_rounding_mode(rounding_mode& mode)
+ { mode = msvc2hard(_control87(0, 0)); }
+ static void set_rounding_mode(const rounding_mode mode)
+ { _control87(hard2msvc(mode), _MCW_EM | _MCW_RC | _MCW_PC | _MCW_IC); }
+ static double to_int(const double& x) { return rint(x); }
+};
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_MSVC_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/ppc_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2005 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP
+
+#if !defined(powerpc) && !defined(__powerpc__) && !defined(__ppc__)
+#error This header only works on PPC CPUs.
+#endif
+
+#if defined(__GNUC__ ) || (__IBMCPP__ >= 700)
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+typedef union {
+ ::boost::long_long_type imode;
+ double dmode;
+} rounding_mode_struct;
+
+static const rounding_mode_struct mode_upward = { 0xFFF8000000000002LL };
+static const rounding_mode_struct mode_downward = { 0xFFF8000000000003LL };
+static const rounding_mode_struct mode_to_nearest = { 0xFFF8000000000000LL };
+static const rounding_mode_struct mode_toward_zero = { 0xFFF8000000000001LL };
+
+struct ppc_rounding_control
+{
+ typedef double rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode mode)
+ { __asm__ __volatile__ ("mtfsf 255,%0" : : "f"(mode)); }
+
+ static void get_rounding_mode(rounding_mode& mode)
+ { __asm__ __volatile__ ("mffs %0" : "=f"(mode)); }
+
+ static void downward() { set_rounding_mode(mode_downward.dmode); }
+ static void upward() { set_rounding_mode(mode_upward.dmode); }
+ static void to_nearest() { set_rounding_mode(mode_to_nearest.dmode); }
+ static void toward_zero() { set_rounding_mode(mode_toward_zero.dmode); }
+};
+
+} // namespace detail
+
+// Do not declare the following C99 symbols if <math.h> provides them.
+// Otherwise, conflicts may occur, due to differences between prototypes.
+#if !defined(_ISOC99_SOURCE) && !defined(__USE_ISOC99)
+extern "C" {
+ float rintf(float);
+ double rint(double);
+}
+#endif
+
+template<>
+struct rounding_control<float>:
+ detail::ppc_rounding_control
+{
+ static float force_rounding(const float r)
+ {
+ float tmp;
+ __asm__ __volatile__ ("frsp %0, %1" : "=f" (tmp) : "f" (r));
+ return tmp;
+ }
+ static float to_int(const float& x) { return rintf(x); }
+};
+
+template<>
+struct rounding_control<double>:
+ detail::ppc_rounding_control
+{
+ static const double & force_rounding(const double& r) { return r; }
+ static double to_int(const double& r) { return rint(r); }
+};
+
+template<>
+struct rounding_control<long double>:
+ detail::ppc_rounding_control
+{
+ static const long double & force_rounding(const long double& r) { return r; }
+ static long double to_int(const long double& r) { return rint(r); }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+#endif
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_PPC_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/sparc_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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 basic code in this file was kindly provided by Jeremy Siek.
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_SPARC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_SPARC_ROUNDING_CONTROL_HPP
+
+#if !defined(sparc) && !defined(__sparc__)
+# error This header is only intended for SPARC CPUs.
+#endif
+
+#ifdef __SUNPRO_CC
+# include <ieeefp.h>
+#endif
+
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+struct sparc_rounding_control
+{
+ typedef unsigned int rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode& mode)
+ {
+# if defined(__GNUC__)
+ __asm__ __volatile__("ld %0, %%fsr" : : "m"(mode));
+# elif defined (__SUNPRO_CC)
+ fpsetround(fp_rnd(mode));
+# elif defined(__KCC)
+ asm("sethi %hi(mode), %o1");
+ asm("ld [%o1+%lo(mode)], %fsr");
+# else
+# error Unsupported compiler for Sparc rounding control.
+# endif
+ }
+
+ static void get_rounding_mode(rounding_mode& mode)
+ {
+# if defined(__GNUC__)
+ __asm__ __volatile__("st %%fsr, %0" : "=m"(mode));
+# elif defined (__SUNPRO_CC)
+ mode = fpgetround();
+# elif defined(__KCC)
+# error KCC on Sun SPARC get_round_mode: please fix me
+ asm("st %fsr, [mode]");
+# else
+# error Unsupported compiler for Sparc rounding control.
+# endif
+ }
+
+#if defined(__SUNPRO_CC)
+ static void downward() { set_rounding_mode(FP_RM); }
+ static void upward() { set_rounding_mode(FP_RP); }
+ static void to_nearest() { set_rounding_mode(FP_RN); }
+ static void toward_zero() { set_rounding_mode(FP_RZ); }
+#else
+ static void downward() { set_rounding_mode(0xc0000000); }
+ static void upward() { set_rounding_mode(0x80000000); }
+ static void to_nearest() { set_rounding_mode(0x00000000); }
+ static void toward_zero() { set_rounding_mode(0x40000000); }
+#endif
+};
+
+} // namespace detail
+
+extern "C" {
+ float rintf(float);
+ double rint(double);
+}
+
+template<>
+struct rounding_control<float>:
+ detail::sparc_rounding_control
+{
+ static const float& force_rounding(const float& x) { return x; }
+ static float to_int(const float& x) { return rintf(x); }
+};
+
+template<>
+struct rounding_control<double>:
+ detail::sparc_rounding_control
+{
+ static const double& force_rounding(const double& x) { return x; }
+ static double to_int(const double& x) { return rint(x); }
+};
+
+template<>
+struct rounding_control<long double>:
+ detail::sparc_rounding_control
+{
+ static const long double& force_rounding(const long double& x) { return x; }
+ static long double to_int(const long double& x) { return rint(x); }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_SPARC_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/test_input.hpp file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_TEST_INPUT_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_TEST_INPUT_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace user {
+
+template<class T> inline
+bool is_zero(T const &v) { return v == static_cast<T>(0); }
+
+template<class T> inline
+bool is_neg (T const &v) { return v < static_cast<T>(0); }
+
+template<class T> inline
+bool is_pos (T const &v) { return v > static_cast<T>(0); }
+
+} // namespace user
+
+namespace detail {
+
+template<class T, class Policies> inline
+bool test_input(const interval<T, Policies>& x) {
+ typedef typename Policies::checking checking;
+ return checking::is_empty(x.lower(), x.upper());
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool test_input(const interval<T, Policies1>& x, const interval<T, Policies2>& y) {
+ typedef typename Policies1::checking checking1;
+ typedef typename Policies2::checking checking2;
+ return checking1::is_empty(x.lower(), x.upper()) ||
+ checking2::is_empty(y.lower(), y.upper());
+}
+
+template<class T, class Policies> inline
+bool test_input(const T& x, const interval<T, Policies>& y) {
+ typedef typename Policies::checking checking;
+ return checking::is_nan(x) || checking::is_empty(y.lower(), y.upper());
+}
+
+template<class T, class Policies> inline
+bool test_input(const interval<T, Policies>& x, const T& y) {
+ typedef typename Policies::checking checking;
+ return checking::is_empty(x.lower(), x.upper()) || checking::is_nan(y);
+}
+
+template<class T, class Policies> inline
+bool test_input(const T& x) {
+ typedef typename Policies::checking checking;
+ return checking::is_nan(x);
+}
+
+template<class T, class Policies> inline
+bool test_input(const T& x, const T& y) {
+ typedef typename Policies::checking checking;
+ return checking::is_nan(x) || checking::is_nan(y);
+}
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_DETAIL_TEST_INPUT_HPP
--- /dev/null
+/* Boost interval/detail/x86_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP
+
+#ifdef __GNUC__
+# include <boost/numeric/interval/detail/x86gcc_rounding_control.hpp>
+#elif defined(__BORLANDC__)
+# include <boost/numeric/interval/detail/bcc_rounding_control.hpp>
+#elif defined(_MSC_VER)
+# include <boost/numeric/interval/detail/msvc_rounding_control.hpp>
+#elif defined(__MWERKS__) || defined(__ICC) || defined (__SUNPRO_CC)
+# define BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM
+# include <boost/numeric/interval/detail/c99sub_rounding_control.hpp>
+#else
+# error Unsupported C++ compiler.
+#endif
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+namespace detail {
+
+#ifdef BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM
+typedef c99_rounding_control x86_rounding_control;
+#undef BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM
+#else
+struct fpu_rounding_modes
+{
+ unsigned short to_nearest;
+ unsigned short downward;
+ unsigned short upward;
+ unsigned short toward_zero;
+};
+
+// exceptions masked, extended precision
+// hardware default is 0x037f (0x1000 only has a meaning on 287)
+static const fpu_rounding_modes rnd_mode = { 0x137f, 0x177f, 0x1b7f, 0x1f7f };
+
+struct x86_rounding_control: x86_rounding
+{
+ static void to_nearest() { set_rounding_mode(rnd_mode.to_nearest); }
+ static void downward() { set_rounding_mode(rnd_mode.downward); }
+ static void upward() { set_rounding_mode(rnd_mode.upward); }
+ static void toward_zero() { set_rounding_mode(rnd_mode.toward_zero); }
+};
+#endif // BOOST_NUMERIC_INTERVAL_USE_C99_SUBSYSTEM
+
+} // namespace detail
+
+template<>
+struct rounding_control<float>: detail::x86_rounding_control
+{
+ static float force_rounding(const float& r)
+ { volatile float r_ = r; return r_; }
+};
+
+template<>
+struct rounding_control<double>: detail::x86_rounding_control
+{
+ /*static double force_rounding(double r)
+ { asm volatile ("" : "+m"(r) : ); return r; }*/
+ static double force_rounding(const double& r)
+ { volatile double r_ = r; return r_; }
+};
+
+namespace detail {
+
+template<bool>
+struct x86_rounding_control_long_double;
+
+template<>
+struct x86_rounding_control_long_double<false>: x86_rounding_control
+{
+ static long double force_rounding(long double const &r)
+ { volatile long double r_ = r; return r_; }
+};
+
+template<>
+struct x86_rounding_control_long_double<true>: x86_rounding_control
+{
+ static long double const &force_rounding(long double const &r)
+ { return r; }
+};
+
+} // namespace detail
+
+template<>
+struct rounding_control<long double>:
+ detail::x86_rounding_control_long_double< (sizeof(long double) >= 10) >
+{};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_X86_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/detail/x86gcc_rounding_control.hpp file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_X86GCC_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_DETAIL_X86GCC_ROUNDING_CONTROL_HPP
+
+#ifndef __GNUC__
+# error This header only works with GNU CC.
+#endif
+
+#ifndef __i386__
+# error This header only works on x86 CPUs.
+#endif
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+namespace detail {
+
+struct x86_rounding
+{
+ typedef unsigned short rounding_mode;
+
+ static void set_rounding_mode(const rounding_mode& mode)
+ { __asm__ __volatile__ ("fldcw %0" : : "m"(mode)); }
+
+ static void get_rounding_mode(rounding_mode& mode)
+ { __asm__ __volatile__ ("fnstcw %0" : "=m"(mode)); }
+
+ template<class T>
+ static T to_int(T r)
+ {
+ T r_;
+ __asm__ ("frndint" : "=&t"(r_) : "0"(r));
+ return r_;
+ }
+};
+
+} // namespace detail
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif /* BOOST_NUMERIC_INTERVAL_DETAIL_X86GCC_ROUNDING_CONTROL_HPP */
--- /dev/null
+/* Boost interval/ext/integer.hpp template implementation file
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_EXT_INTEGER_HPP
+#define BOOST_NUMERIC_INTERVAL_EXT_INTEGER_HPP
+
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+
+namespace boost {
+namespace numeric {
+
+template<class T, class Policies> inline
+interval<T, Policies> operator+ (const interval<T, Policies>& x, int y)
+{
+ return x + static_cast<T>(y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator+ (int x, const interval<T, Policies>& y)
+{
+ return static_cast<T>(x) + y;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator- (const interval<T, Policies>& x, int y)
+{
+ return x - static_cast<T>(y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator- (int x, const interval<T, Policies>& y)
+{
+ return static_cast<T>(x) - y;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator* (const interval<T, Policies>& x, int y)
+{
+ return x * static_cast<T>(y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator* (int x, const interval<T, Policies>& y)
+{
+ return static_cast<T>(x) * y;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator/ (const interval<T, Policies>& x, int y)
+{
+ return x / static_cast<T>(y);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> operator/ (int x, const interval<T, Policies>& y)
+{
+ return static_cast<T>(x) / y;
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_EXT_INTEGER_HPP
--- /dev/null
+/* Boost interval/detail/x86gcc_rounding_control.hpp file
+ *
+ * This header provides a rounding control policy
+ * that avoids flushing results to memory. In
+ * order for this optimization to be reliable, it
+ * should be used only when no underflow or
+ * overflow would happen without it. Indeed, only
+ * values in range are correctly rounded.
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_EXT_X86_FAST_ROUNDING_CONTROL_HPP
+#define BOOST_NUMERIC_INTERVAL_EXT_X86_FAST_ROUNDING_CONTROL_HPP
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+namespace detail {
+
+// exceptions masked, expected precision (the mask is 0x0300)
+static const fpu_rounding_modes rnd_mode_f = { 0x107f, 0x147f, 0x187f, 0x1c7f };
+static const fpu_rounding_modes rnd_mode_d = { 0x127f, 0x167f, 0x1a7f, 0x1e7f };
+static const fpu_rounding_modes rnd_mode_l = { 0x137f, 0x177f, 0x1b7f, 0x1f7f };
+
+} // namespace detail
+
+template<class T>
+struct x86_fast_rounding_control;
+
+template<>
+struct x86_fast_rounding_control<float>: detail::x86_rounding
+{
+ static void to_nearest() { set_rounding_mode(detail::rnd_mode_f.to_nearest); }
+ static void downward() { set_rounding_mode(detail::rnd_mode_f.downward); }
+ static void upward() { set_rounding_mode(detail::rnd_mode_f.upward); }
+ static void toward_zero() { set_rounding_mode(detail::rnd_mode_f.toward_zero); }
+ static const float& force_rounding(const float& r) { return r; }
+};
+
+template<>
+struct x86_fast_rounding_control<double>: detail::x86_rounding
+{
+ static void to_nearest() { set_rounding_mode(detail::rnd_mode_d.to_nearest); }
+ static void downward() { set_rounding_mode(detail::rnd_mode_d.downward); }
+ static void upward() { set_rounding_mode(detail::rnd_mode_d.upward); }
+ static void toward_zero() { set_rounding_mode(detail::rnd_mode_d.toward_zero); }
+ static const double& force_rounding(const double& r) { return r; }
+};
+
+template<>
+struct x86_fast_rounding_control<long double>: detail::x86_rounding
+{
+ static void to_nearest() { set_rounding_mode(detail::rnd_mode_l.to_nearest); }
+ static void downward() { set_rounding_mode(detail::rnd_mode_l.downward); }
+ static void upward() { set_rounding_mode(detail::rnd_mode_l.upward); }
+ static void toward_zero() { set_rounding_mode(detail::rnd_mode_l.toward_zero); }
+ static const long double& force_rounding(const long double& r) { return r; }
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_EXT_X86_FAST_ROUNDING_CONTROL_HPP
--- /dev/null
+/* Boost interval/hw_rounding.hpp template implementation file
+ *
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2005 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_HW_ROUNDING_HPP
+#define BOOST_NUMERIC_INTERVAL_HW_ROUNDING_HPP
+
+#include <boost/numeric/interval/rounding.hpp>
+#include <boost/numeric/interval/rounded_arith.hpp>
+
+#define BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+
+// define appropriate specialization of rounding_control for built-in types
+#if defined(__x86_64__) && (defined(__USE_ISOC99) || defined(__APPLE__))
+# include <boost/numeric/interval/detail/c99_rounding_control.hpp>
+#elif defined(__i386__) || defined(_M_IX86) || defined(__BORLANDC__) || defined(_M_X64)
+# include <boost/numeric/interval/detail/x86_rounding_control.hpp>
+#elif defined(powerpc) || defined(__powerpc__) || defined(__ppc__)
+# include <boost/numeric/interval/detail/ppc_rounding_control.hpp>
+#elif defined(sparc) || defined(__sparc__)
+# include <boost/numeric/interval/detail/sparc_rounding_control.hpp>
+#elif defined(alpha) || defined(__alpha__)
+# include <boost/numeric/interval/detail/alpha_rounding_control.hpp>
+#elif defined(ia64) || defined(__ia64) || defined(__ia64__)
+# include <boost/numeric/interval/detail/ia64_rounding_control.hpp>
+#endif
+
+#if defined(BOOST_NUMERIC_INTERVAL_NO_HARDWARE) && (defined(__USE_ISOC99) || defined(__MSL__))
+# include <boost/numeric/interval/detail/c99_rounding_control.hpp>
+#endif
+
+#if defined(BOOST_NUMERIC_INTERVAL_NO_HARDWARE)
+# undef BOOST_NUMERIC_INTERVAL_NO_HARDWARE
+# error Boost.Numeric.Interval: Please specify rounding control mechanism.
+#endif
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+/*
+ * Three specializations of rounded_math<T>
+ */
+
+template<>
+struct rounded_math<float>
+ : save_state<rounded_arith_opp<float> >
+{};
+
+template<>
+struct rounded_math<double>
+ : save_state<rounded_arith_opp<double> >
+{};
+
+template<>
+struct rounded_math<long double>
+ : save_state<rounded_arith_opp<long double> >
+{};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_HW_ROUNDING_HPP
--- /dev/null
+/* Boost interval/interval.hpp header file
+ *
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
+#define BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
+
+#include <stdexcept>
+#include <string>
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+
+namespace boost {
+namespace numeric {
+
+namespace interval_lib {
+
+class comparison_error
+ : public std::runtime_error
+{
+public:
+ comparison_error()
+ : std::runtime_error("boost::interval: uncertain comparison")
+ { }
+};
+
+} // namespace interval_lib
+
+/*
+ * interval class
+ */
+
+template<class T, class Policies>
+class interval
+{
+private:
+ struct interval_holder;
+ struct number_holder;
+public:
+ typedef T base_type;
+ typedef Policies traits_type;
+
+ T const &lower() const;
+ T const &upper() const;
+
+ interval();
+ interval(T const &v);
+ template<class T1> interval(T1 const &v);
+ interval(T const &l, T const &u);
+ template<class T1, class T2> interval(T1 const &l, T2 const &u);
+ interval(interval<T, Policies> const &r);
+ template<class Policies1> interval(interval<T, Policies1> const &r);
+ template<class T1, class Policies1> interval(interval<T1, Policies1> const &r);
+
+ interval &operator=(T const &v);
+ template<class T1> interval &operator=(T1 const &v);
+ interval &operator=(interval<T, Policies> const &r);
+ template<class Policies1> interval &operator=(interval<T, Policies1> const &r);
+ template<class T1, class Policies1> interval &operator=(interval<T1, Policies1> const &r);
+
+ void assign(const T& l, const T& u);
+
+ static interval empty();
+ static interval whole();
+ static interval hull(const T& x, const T& y);
+
+ interval& operator+= (const T& r);
+ interval& operator+= (const interval& r);
+ interval& operator-= (const T& r);
+ interval& operator-= (const interval& r);
+ interval& operator*= (const T& r);
+ interval& operator*= (const interval& r);
+ interval& operator/= (const T& r);
+ interval& operator/= (const interval& r);
+
+ bool operator< (const interval_holder& r) const;
+ bool operator> (const interval_holder& r) const;
+ bool operator<= (const interval_holder& r) const;
+ bool operator>= (const interval_holder& r) const;
+ bool operator== (const interval_holder& r) const;
+ bool operator!= (const interval_holder& r) const;
+
+ bool operator< (const number_holder& r) const;
+ bool operator> (const number_holder& r) const;
+ bool operator<= (const number_holder& r) const;
+ bool operator>= (const number_holder& r) const;
+ bool operator== (const number_holder& r) const;
+ bool operator!= (const number_holder& r) const;
+
+ // the following is for internal use only, it is not a published interface
+ // nevertheless, it's public because friends don't always work correctly.
+ interval(const T& l, const T& u, bool): low(l), up(u) {}
+ void set_empty();
+ void set_whole();
+ void set(const T& l, const T& u);
+
+private:
+ struct interval_holder {
+ template<class Policies2>
+ interval_holder(const interval<T, Policies2>& r)
+ : low(r.lower()), up(r.upper())
+ {
+ typedef typename Policies2::checking checking2;
+ if (checking2::is_empty(low, up))
+ throw interval_lib::comparison_error();
+ }
+
+ const T& low;
+ const T& up;
+ };
+
+ struct number_holder {
+ number_holder(const T& r) : val(r)
+ {
+ typedef typename Policies::checking checking;
+ if (checking::is_nan(r))
+ throw interval_lib::comparison_error();
+ }
+
+ const T& val;
+ };
+
+ typedef typename Policies::checking checking;
+ typedef typename Policies::rounding rounding;
+
+ T low;
+ T up;
+};
+
+template<class T, class Policies> inline
+interval<T, Policies>::interval():
+ low(static_cast<T>(0)), up(static_cast<T>(0))
+{}
+
+template<class T, class Policies> inline
+interval<T, Policies>::interval(T const &v): low(v), up(v)
+{
+ if (checking::is_nan(v)) set_empty();
+}
+
+template<class T, class Policies> template<class T1> inline
+interval<T, Policies>::interval(T1 const &v)
+{
+ if (checking::is_nan(v)) set_empty();
+ else {
+ rounding rnd;
+ low = rnd.conv_down(v);
+ up = rnd.conv_up (v);
+ }
+}
+
+template<class T, class Policies> template<class T1, class T2> inline
+interval<T, Policies>::interval(T1 const &l, T2 const &u)
+{
+ if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u)) set_empty();
+ else {
+ rounding rnd;
+ low = rnd.conv_down(l);
+ up = rnd.conv_up (u);
+ }
+}
+
+template<class T, class Policies> inline
+interval<T, Policies>::interval(T const &l, T const &u): low(l), up(u)
+{
+ if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
+ set_empty();
+}
+
+
+template<class T, class Policies> inline
+interval<T, Policies>::interval(interval<T, Policies> const &r): low(r.lower()), up(r.upper())
+{}
+
+template<class T, class Policies> template<class Policies1> inline
+interval<T, Policies>::interval(interval<T, Policies1> const &r): low(r.lower()), up(r.upper())
+{
+ typedef typename Policies1::checking checking1;
+ if (checking1::is_empty(r.lower(), r.upper())) set_empty();
+}
+
+template<class T, class Policies> template<class T1, class Policies1> inline
+interval<T, Policies>::interval(interval<T1, Policies1> const &r)
+{
+ typedef typename Policies1::checking checking1;
+ if (checking1::is_empty(r.lower(), r.upper())) set_empty();
+ else {
+ rounding rnd;
+ low = rnd.conv_down(r.lower());
+ up = rnd.conv_up (r.upper());
+ }
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> &interval<T, Policies>::operator=(T const &v)
+{
+ if (checking::is_nan(v)) set_empty();
+ else low = up = v;
+ return *this;
+}
+
+template<class T, class Policies> template<class T1> inline
+interval<T, Policies> &interval<T, Policies>::operator=(T1 const &v)
+{
+ if (checking::is_nan(v)) set_empty();
+ else {
+ rounding rnd;
+ low = rnd.conv_down(v);
+ up = rnd.conv_up (v);
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies> const &r)
+{
+ low = r.lower();
+ up = r.upper();
+ return *this;
+}
+
+template<class T, class Policies> template<class Policies1> inline
+interval<T, Policies> &interval<T, Policies>::operator=(interval<T, Policies1> const &r)
+{
+ typedef typename Policies1::checking checking1;
+ if (checking1::is_empty(r.lower(), r.upper())) set_empty();
+ else {
+ low = r.lower();
+ up = r.upper();
+ }
+ return *this;
+}
+
+template<class T, class Policies> template<class T1, class Policies1> inline
+interval<T, Policies> &interval<T, Policies>::operator=(interval<T1, Policies1> const &r)
+{
+ typedef typename Policies1::checking checking1;
+ if (checking1::is_empty(r.lower(), r.upper())) set_empty();
+ else {
+ rounding rnd;
+ low = rnd.conv_down(r.lower());
+ up = rnd.conv_up (r.upper());
+ }
+ return *this;
+}
+
+template<class T, class Policies> inline
+void interval<T, Policies>::assign(const T& l, const T& u)
+{
+ if (checking::is_nan(l) || checking::is_nan(u) || !(l <= u))
+ set_empty();
+ else set(l, u);
+}
+
+template<class T, class Policies> inline
+void interval<T, Policies>::set(const T& l, const T& u)
+{
+ low = l;
+ up = u;
+}
+
+template<class T, class Policies> inline
+void interval<T, Policies>::set_empty()
+{
+ low = checking::empty_lower();
+ up = checking::empty_upper();
+}
+
+template<class T, class Policies> inline
+void interval<T, Policies>::set_whole()
+{
+ low = checking::neg_inf();
+ up = checking::pos_inf();
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> interval<T, Policies>::hull(const T& x, const T& y)
+{
+ bool bad_x = checking::is_nan(x);
+ bool bad_y = checking::is_nan(y);
+ if (bad_x)
+ if (bad_y) return interval::empty();
+ else return interval(y, y, true);
+ else
+ if (bad_y) return interval(x, x, true);
+ if (x <= y) return interval(x, y, true);
+ else return interval(y, x, true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> interval<T, Policies>::empty()
+{
+ return interval<T, Policies>(checking::empty_lower(),
+ checking::empty_upper(), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> interval<T, Policies>::whole()
+{
+ return interval<T, Policies>(checking::neg_inf(), checking::pos_inf(), true);
+}
+
+template<class T, class Policies> inline
+const T& interval<T, Policies>::lower() const
+{
+ return low;
+}
+
+template<class T, class Policies> inline
+const T& interval<T, Policies>::upper() const
+{
+ return up;
+}
+
+/*
+ * interval/interval comparisons
+ */
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator< (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up < r.low) return true;
+ else if (low >= r.up) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator> (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (low > r.up) return true;
+ else if (up <= r.low) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator<= (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up <= r.low) return true;
+ else if (low > r.up) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator>= (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (low >= r.up) return true;
+ else if (up < r.low) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator== (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up == r.low && low == r.up) return true;
+ else if (up < r.low || low > r.up) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator!= (const interval_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up < r.low || low > r.up) return true;
+ else if (up == r.low && low == r.up) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+/*
+ * interval/number comparisons
+ */
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator< (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up < r.val) return true;
+ else if (low >= r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator> (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (low > r.val) return true;
+ else if (up <= r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator<= (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up <= r.val) return true;
+ else if (low > r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator>= (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (low >= r.val) return true;
+ else if (up < r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator== (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up == r.val && low == r.val) return true;
+ else if (up < r.val || low > r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+template<class T, class Policies> inline
+bool interval<T, Policies>::operator!= (const number_holder& r) const
+{
+ if (!checking::is_empty(low, up)) {
+ if (up < r.val || low > r.val) return true;
+ else if (up == r.val && low == r.val) return false;
+ }
+ throw interval_lib::comparison_error();
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_INTERVAL_HPP
--- /dev/null
+/* Boost interval/io.hpp header file
+ *
+ * This file is only meant to provide a quick
+ * implementation of the output operator. It is
+ * provided for test programs that aren't even
+ * interested in the precision of the results.
+ * A real progam should define its own operators
+ * and never include this header.
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_IO_HPP
+#define BOOST_NUMERIC_INTERVAL_IO_HPP
+
+#include <boost/numeric/interval/interval.hpp>
+#include <boost/numeric/interval/utility.hpp>
+#include <ostream>
+
+namespace boost {
+namespace numeric {
+
+template<class CharType, class CharTraits, class T, class Policies>
+std::basic_ostream<CharType, CharTraits> &operator<<
+ (std::basic_ostream<CharType, CharTraits> &stream,
+ interval<T, Policies> const &value)
+{
+ if (empty(value))
+ return stream << "[]";
+ else
+ return stream << '[' << lower(value) << ',' << upper(value) << ']';
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_IO_HPP
--- /dev/null
+/* Boost interval/limits.hpp template implementation file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_LIMITS_HPP
+#define BOOST_NUMERIC_INTERVAL_LIMITS_HPP
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#include <boost/config.hpp>
+#include <boost/limits.hpp>
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+
+namespace std {
+
+template<class T, class Policies>
+class numeric_limits<boost::numeric::interval<T, Policies> >
+ : public numeric_limits<T>
+{
+private:
+ typedef boost::numeric::interval<T, Policies> I;
+ typedef numeric_limits<T> bl;
+public:
+ static I min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return I((bl::min)(), (bl::min)()); }
+ static I max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return I((bl::max)(), (bl::max)()); }
+ static I epsilon() throw() { return I(bl::epsilon(), bl::epsilon()); }
+
+ BOOST_STATIC_CONSTANT(float_round_style, round_style = round_indeterminate);
+ BOOST_STATIC_CONSTANT(bool, is_iec559 = false);
+
+ static I infinity () throw() { return I::whole(); }
+ static I quiet_NaN() throw() { return I::empty(); }
+ static I signaling_NaN() throw()
+ { return I(bl::signaling_NaN(), bl::signaling_Nan()); }
+ static I denorm_min() throw()
+ { return I(bl::denorm_min(), bl::denorm_min()); }
+private:
+ static I round_error(); // hide this on purpose, not yet implemented
+};
+
+} // namespace std
+
+#endif
+
+#endif // BOOST_NUMERIC_INTERVAL_LIMITS_HPP
--- /dev/null
+/* Boost interval/policies.hpp template implementation file
+ *
+ * Copyright 2003 Guillaume Melquiond
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_POLICIES_HPP
+#define BOOST_NUMERIC_INTERVAL_POLICIES_HPP
+
+#include <boost/numeric/interval/interval.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+/*
+ * policies class
+ */
+
+template<class Rounding, class Checking>
+struct policies
+{
+ typedef Rounding rounding;
+ typedef Checking checking;
+};
+
+/*
+ * policies switching classes
+ */
+
+template<class OldInterval, class NewRounding>
+class change_rounding
+{
+ typedef typename OldInterval::base_type T;
+ typedef typename OldInterval::traits_type p;
+ typedef typename p::checking checking;
+public:
+ typedef interval<T, policies<NewRounding, checking> > type;
+};
+
+template<class OldInterval, class NewChecking>
+class change_checking
+{
+ typedef typename OldInterval::base_type T;
+ typedef typename OldInterval::traits_type p;
+ typedef typename p::rounding rounding;
+public:
+ typedef interval<T, policies<rounding, NewChecking> > type;
+};
+
+/*
+ * Protect / unprotect: control whether the rounding mode is set/reset
+ * at each operation, rather than once and for all.
+ */
+
+template<class OldInterval>
+class unprotect
+{
+ typedef typename OldInterval::base_type T;
+ typedef typename OldInterval::traits_type p;
+ typedef typename p::rounding r;
+ typedef typename r::unprotected_rounding newRounding;
+public:
+ typedef typename change_rounding<OldInterval, newRounding>::type type;
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+
+#endif // BOOST_NUMERIC_INTERVAL_POLICIES_HPP
--- /dev/null
+/* Boost interval/rounded_arith.hpp template implementation file
+ *
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ROUNDED_ARITH_HPP
+#define BOOST_NUMERIC_INTERVAL_ROUNDED_ARITH_HPP
+
+#include <boost/numeric/interval/rounding.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/config/no_tr1/cmath.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+/*
+ * Three classes of rounding: exact, std, opp
+ * See documentation for details.
+ */
+
+template<class T, class Rounding>
+struct rounded_arith_exact: Rounding {
+ void init() { }
+ template<class U> T conv_down(U const &v) { return v; }
+ template<class U> T conv_up (U const &v) { return v; }
+ T add_down (const T& x, const T& y) { return x + y; }
+ T add_up (const T& x, const T& y) { return x + y; }
+ T sub_down (const T& x, const T& y) { return x - y; }
+ T sub_up (const T& x, const T& y) { return x - y; }
+ T mul_down (const T& x, const T& y) { return x * y; }
+ T mul_up (const T& x, const T& y) { return x * y; }
+ T div_down (const T& x, const T& y) { return x / y; }
+ T div_up (const T& x, const T& y) { return x / y; }
+ T median (const T& x, const T& y) { return (x + y) / 2; }
+ T sqrt_down(const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); return sqrt(x); }
+ T sqrt_up (const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); return sqrt(x); }
+ T int_down (const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(floor); return floor(x); }
+ T int_up (const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(ceil); return ceil(x); }
+};
+
+template<class T, class Rounding>
+struct rounded_arith_std: Rounding {
+# define BOOST_DN(EXPR) this->downward(); return this->force_rounding(EXPR)
+# define BOOST_NR(EXPR) this->to_nearest(); return this->force_rounding(EXPR)
+# define BOOST_UP(EXPR) this->upward(); return this->force_rounding(EXPR)
+ void init() { }
+ template<class U> T conv_down(U const &v) { BOOST_DN(v); }
+ template<class U> T conv_up (U const &v) { BOOST_UP(v); }
+ T add_down(const T& x, const T& y) { BOOST_DN(x + y); }
+ T sub_down(const T& x, const T& y) { BOOST_DN(x - y); }
+ T mul_down(const T& x, const T& y) { BOOST_DN(x * y); }
+ T div_down(const T& x, const T& y) { BOOST_DN(x / y); }
+ T add_up (const T& x, const T& y) { BOOST_UP(x + y); }
+ T sub_up (const T& x, const T& y) { BOOST_UP(x - y); }
+ T mul_up (const T& x, const T& y) { BOOST_UP(x * y); }
+ T div_up (const T& x, const T& y) { BOOST_UP(x / y); }
+ T median(const T& x, const T& y) { BOOST_NR((x + y) / 2); }
+ T sqrt_down(const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_DN(sqrt(x)); }
+ T sqrt_up (const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_UP(sqrt(x)); }
+ T int_down(const T& x) { this->downward(); return to_int(x); }
+ T int_up (const T& x) { this->upward(); return to_int(x); }
+# undef BOOST_DN
+# undef BOOST_NR
+# undef BOOST_UP
+};
+
+template<class T, class Rounding>
+struct rounded_arith_opp: Rounding {
+ void init() { this->upward(); }
+# define BOOST_DN(EXPR) \
+ this->downward(); \
+ T r = this->force_rounding(EXPR); \
+ this->upward(); \
+ return r
+# define BOOST_NR(EXPR) \
+ this->to_nearest(); \
+ T r = this->force_rounding(EXPR); \
+ this->upward(); \
+ return r
+# define BOOST_UP(EXPR) return this->force_rounding(EXPR)
+# define BOOST_UP_NEG(EXPR) return -this->force_rounding(EXPR)
+ template<class U> T conv_down(U const &v) { BOOST_UP_NEG(-v); }
+ template<class U> T conv_up (U const &v) { BOOST_UP(v); }
+ T add_down(const T& x, const T& y) { BOOST_UP_NEG((-x) - y); }
+ T sub_down(const T& x, const T& y) { BOOST_UP_NEG(y - x); }
+ T mul_down(const T& x, const T& y) { BOOST_UP_NEG(x * (-y)); }
+ T div_down(const T& x, const T& y) { BOOST_UP_NEG(x / (-y)); }
+ T add_up (const T& x, const T& y) { BOOST_UP(x + y); }
+ T sub_up (const T& x, const T& y) { BOOST_UP(x - y); }
+ T mul_up (const T& x, const T& y) { BOOST_UP(x * y); }
+ T div_up (const T& x, const T& y) { BOOST_UP(x / y); }
+ T median (const T& x, const T& y) { BOOST_NR((x + y) / 2); }
+ T sqrt_down(const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_DN(sqrt(x)); }
+ T sqrt_up (const T& x)
+ { BOOST_NUMERIC_INTERVAL_using_math(sqrt); BOOST_UP(sqrt(x)); }
+ T int_down(const T& x) { return -to_int(-x); }
+ T int_up (const T& x) { return to_int(x); }
+# undef BOOST_DN
+# undef BOOST_NR
+# undef BOOST_UP
+# undef BOOST_UP_NEG
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ROUNDED_ARITH_HPP
--- /dev/null
+/* Boost interval/rounded_transc.hpp template implementation file
+ *
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ROUNDED_TRANSC_HPP
+#define BOOST_NUMERIC_INTERVAL_ROUNDED_TRANSC_HPP
+
+#include <boost/numeric/interval/rounding.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/config/no_tr1/cmath.hpp>
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+template<class T, class Rounding>
+struct rounded_transc_exact: Rounding
+{
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) { BOOST_NUMERIC_INTERVAL_using_math(f); return f(x); } \
+ T f##_up (const T& x) { BOOST_NUMERIC_INTERVAL_using_math(f); return f(x); }
+ BOOST_NUMERIC_INTERVAL_new_func(exp)
+ BOOST_NUMERIC_INTERVAL_new_func(log)
+ BOOST_NUMERIC_INTERVAL_new_func(sin)
+ BOOST_NUMERIC_INTERVAL_new_func(cos)
+ BOOST_NUMERIC_INTERVAL_new_func(tan)
+ BOOST_NUMERIC_INTERVAL_new_func(asin)
+ BOOST_NUMERIC_INTERVAL_new_func(acos)
+ BOOST_NUMERIC_INTERVAL_new_func(atan)
+ BOOST_NUMERIC_INTERVAL_new_func(sinh)
+ BOOST_NUMERIC_INTERVAL_new_func(cosh)
+ BOOST_NUMERIC_INTERVAL_new_func(tanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) { BOOST_NUMERIC_INTERVAL_using_ahyp(f); return f(x); } \
+ T f##_up (const T& x) { BOOST_NUMERIC_INTERVAL_using_ahyp(f); return f(x); }
+ BOOST_NUMERIC_INTERVAL_new_func(asinh)
+ BOOST_NUMERIC_INTERVAL_new_func(acosh)
+ BOOST_NUMERIC_INTERVAL_new_func(atanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+};
+
+template<class T, class Rounding>
+struct rounded_transc_std: Rounding
+{
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->downward(); return this->force_rounding(f(x)); } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->upward(); return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(exp)
+ BOOST_NUMERIC_INTERVAL_new_func(log)
+ BOOST_NUMERIC_INTERVAL_new_func(sin)
+ BOOST_NUMERIC_INTERVAL_new_func(cos)
+ BOOST_NUMERIC_INTERVAL_new_func(tan)
+ BOOST_NUMERIC_INTERVAL_new_func(asin)
+ BOOST_NUMERIC_INTERVAL_new_func(acos)
+ BOOST_NUMERIC_INTERVAL_new_func(atan)
+ BOOST_NUMERIC_INTERVAL_new_func(sinh)
+ BOOST_NUMERIC_INTERVAL_new_func(cosh)
+ BOOST_NUMERIC_INTERVAL_new_func(tanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ this->downward(); return this->force_rounding(f(x)); } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ this->upward(); return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(asinh)
+ BOOST_NUMERIC_INTERVAL_new_func(acosh)
+ BOOST_NUMERIC_INTERVAL_new_func(atanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+};
+
+template<class T, class Rounding>
+struct rounded_transc_opp: Rounding
+{
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ this->downward(); T y = this->force_rounding(f(x)); \
+ this->upward(); return y; } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(exp)
+ BOOST_NUMERIC_INTERVAL_new_func(log)
+ BOOST_NUMERIC_INTERVAL_new_func(cos)
+ BOOST_NUMERIC_INTERVAL_new_func(acos)
+ BOOST_NUMERIC_INTERVAL_new_func(cosh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ return -this->force_rounding(-f(x)); } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_math(f); \
+ return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(sin)
+ BOOST_NUMERIC_INTERVAL_new_func(tan)
+ BOOST_NUMERIC_INTERVAL_new_func(asin)
+ BOOST_NUMERIC_INTERVAL_new_func(atan)
+ BOOST_NUMERIC_INTERVAL_new_func(sinh)
+ BOOST_NUMERIC_INTERVAL_new_func(tanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ this->downward(); T y = this->force_rounding(f(x)); \
+ this->upward(); return y; } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(asinh)
+ BOOST_NUMERIC_INTERVAL_new_func(atanh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+# define BOOST_NUMERIC_INTERVAL_new_func(f) \
+ T f##_down(const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ return -this->force_rounding(-f(x)); } \
+ T f##_up (const T& x) \
+ { BOOST_NUMERIC_INTERVAL_using_ahyp(f); \
+ return this->force_rounding(f(x)); }
+ BOOST_NUMERIC_INTERVAL_new_func(acosh)
+# undef BOOST_NUMERIC_INTERVAL_new_func
+};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ROUNDED_TRANSC_HPP
--- /dev/null
+/* Boost interval/rounding.hpp template implementation file
+ *
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_ROUNDING_HPP
+#define BOOST_NUMERIC_INTERVAL_ROUNDING_HPP
+
+namespace boost {
+namespace numeric {
+namespace interval_lib {
+
+/*
+ * Default rounding_control class (does nothing)
+ */
+
+template<class T>
+struct rounding_control
+{
+ typedef int rounding_mode;
+ static void get_rounding_mode(rounding_mode&) {}
+ static void set_rounding_mode(rounding_mode) {}
+ static void upward() {}
+ static void downward() {}
+ static void to_nearest() {}
+ static const T& to_int(const T& x) { return x; }
+ static const T& force_rounding(const T& x) { return x; }
+};
+
+/*
+ * A few rounding control classes (exact/std/opp: see documentation)
+ * rounded_arith_* control the rounding of the arithmetic operators
+ * rounded_transc_* control the rounding of the transcendental functions
+ */
+
+template<class T, class Rounding = rounding_control<T> >
+struct rounded_arith_exact;
+
+template<class T, class Rounding = rounding_control<T> >
+struct rounded_arith_std;
+
+template<class T, class Rounding = rounding_control<T> >
+struct rounded_arith_opp;
+
+template<class T, class Rounding>
+struct rounded_transc_dummy;
+
+template<class T, class Rounding = rounded_arith_exact<T> >
+struct rounded_transc_exact;
+
+template<class T, class Rounding = rounded_arith_std<T> >
+struct rounded_transc_std;
+
+template<class T, class Rounding = rounded_arith_opp<T> >
+struct rounded_transc_opp;
+
+/*
+ * State-saving classes: allow to set and reset rounding control
+ */
+
+namespace detail {
+
+template<class Rounding>
+struct save_state_unprotected: Rounding
+{
+ typedef save_state_unprotected<Rounding> unprotected_rounding;
+};
+
+} // namespace detail
+
+template<class Rounding>
+struct save_state: Rounding
+{
+ typename Rounding::rounding_mode mode;
+ save_state() {
+ this->get_rounding_mode(mode);
+ this->init();
+ }
+ ~save_state() { this->set_rounding_mode(mode); }
+ typedef detail::save_state_unprotected<Rounding> unprotected_rounding;
+};
+
+template<class Rounding>
+struct save_state_nothing: Rounding
+{
+ typedef save_state_nothing<Rounding> unprotected_rounding;
+};
+
+template<class T>
+struct rounded_math: save_state_nothing<rounded_arith_exact<T> >
+{};
+
+} // namespace interval_lib
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_ROUNDING_HPP
--- /dev/null
+/* Boost interval/transc.hpp template implementation file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_TRANSC_HPP
+#define BOOST_NUMERIC_INTERVAL_TRANSC_HPP
+
+#include <boost/config.hpp>
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/rounding.hpp>
+#include <boost/numeric/interval/constants.hpp>
+#include <boost/numeric/interval/arith.hpp>
+#include <boost/numeric/interval/arith2.hpp>
+#include <algorithm>
+
+namespace boost {
+namespace numeric {
+
+template<class T, class Policies> inline
+interval<T, Policies> exp(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.exp_down(x.lower()), rnd.exp_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> log(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x) ||
+ !interval_lib::user::is_pos(x.upper()))
+ return I::empty();
+ typename Policies::rounding rnd;
+ typedef typename Policies::checking checking;
+ T l = !interval_lib::user::is_pos(x.lower())
+ ? checking::neg_inf() : rnd.log_down(x.lower());
+ return I(l, rnd.log_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> cos(const interval<T, Policies>& x)
+{
+ if (interval_lib::detail::test_input(x))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ typedef interval<T, Policies> I;
+ typedef typename interval_lib::unprotect<I>::type R;
+
+ // get lower bound within [0, pi]
+ const R pi2 = interval_lib::pi_twice<R>();
+ R tmp = fmod((const R&)x, pi2);
+ if (width(tmp) >= pi2.lower())
+ return I(static_cast<T>(-1), static_cast<T>(1), true); // we are covering a full period
+ if (tmp.lower() >= interval_lib::constants::pi_upper<T>())
+ return -cos(tmp - interval_lib::pi<R>());
+ T l = tmp.lower();
+ T u = tmp.upper();
+
+ BOOST_USING_STD_MIN();
+ // separate into monotone subintervals
+ if (u <= interval_lib::constants::pi_lower<T>())
+ return I(rnd.cos_down(u), rnd.cos_up(l), true);
+ else if (u <= pi2.lower())
+ return I(static_cast<T>(-1), rnd.cos_up(min BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.sub_down(pi2.lower(), u), l)), true);
+ else
+ return I(static_cast<T>(-1), static_cast<T>(1), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> sin(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<I>::type R;
+ I r = cos((const R&)x - interval_lib::pi_half<R>());
+ (void)&rnd;
+ return r;
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> tan(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ typedef typename interval_lib::unprotect<I>::type R;
+
+ // get lower bound within [-pi/2, pi/2]
+ const R pi = interval_lib::pi<R>();
+ R tmp = fmod((const R&)x, pi);
+ const T pi_half_d = interval_lib::constants::pi_half_lower<T>();
+ if (tmp.lower() >= pi_half_d)
+ tmp -= pi;
+ if (tmp.lower() <= -pi_half_d || tmp.upper() >= pi_half_d)
+ return I::whole();
+ return I(rnd.tan_down(tmp.lower()), rnd.tan_up(tmp.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> asin(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x)
+ || x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
+ return I::empty();
+ typename Policies::rounding rnd;
+ T l = (x.lower() <= static_cast<T>(-1))
+ ? -interval_lib::constants::pi_half_upper<T>()
+ : rnd.asin_down(x.lower());
+ T u = (x.upper() >= static_cast<T>(1) )
+ ? interval_lib::constants::pi_half_upper<T>()
+ : rnd.asin_up (x.upper());
+ return I(l, u, true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> acos(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x)
+ || x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
+ return I::empty();
+ typename Policies::rounding rnd;
+ T l = (x.upper() >= static_cast<T>(1) )
+ ? static_cast<T>(0)
+ : rnd.acos_down(x.upper());
+ T u = (x.lower() <= static_cast<T>(-1))
+ ? interval_lib::constants::pi_upper<T>()
+ : rnd.acos_up (x.lower());
+ return I(l, u, true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> atan(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.atan_down(x.lower()), rnd.atan_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> sinh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.sinh_down(x.lower()), rnd.sinh_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> cosh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ if (interval_lib::user::is_neg(x.upper()))
+ return I(rnd.cosh_down(x.upper()), rnd.cosh_up(x.lower()), true);
+ else if (!interval_lib::user::is_neg(x.lower()))
+ return I(rnd.cosh_down(x.lower()), rnd.cosh_up(x.upper()), true);
+ else
+ return I(static_cast<T>(1), rnd.cosh_up(-x.lower() > x.upper() ? x.lower() : x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> tanh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.tanh_down(x.lower()), rnd.tanh_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> asinh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ typename Policies::rounding rnd;
+ return I(rnd.asinh_down(x.lower()), rnd.asinh_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> acosh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x) || x.upper() < static_cast<T>(1))
+ return I::empty();
+ typename Policies::rounding rnd;
+ T l = x.lower() <= static_cast<T>(1) ? static_cast<T>(0) : rnd.acosh_down(x.lower());
+ return I(l, rnd.acosh_up(x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> atanh(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x)
+ || x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
+ return I::empty();
+ typename Policies::rounding rnd;
+ typedef typename Policies::checking checking;
+ T l = (x.lower() <= static_cast<T>(-1))
+ ? checking::neg_inf() : rnd.atanh_down(x.lower());
+ T u = (x.upper() >= static_cast<T>(1) )
+ ? checking::pos_inf() : rnd.atanh_up (x.upper());
+ return I(l, u, true);
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_TRANSC_HPP
--- /dev/null
+/* Boost interval/utility.hpp template implementation file
+ *
+ * Copyright 2000 Jens Maurer
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ *
+ * 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)
+ */
+
+#ifndef BOOST_NUMERIC_INTERVAL_UTILITY_HPP
+#define BOOST_NUMERIC_INTERVAL_UTILITY_HPP
+
+#include <boost/config.hpp>
+#include <boost/numeric/interval/detail/interval_prototype.hpp>
+#include <boost/numeric/interval/detail/test_input.hpp>
+#include <boost/numeric/interval/detail/bugs.hpp>
+#include <algorithm>
+#include <utility>
+
+/*
+ * Implementation of simple functions
+ */
+
+namespace boost {
+namespace numeric {
+
+/*
+ * Utility Functions
+ */
+
+template<class T, class Policies> inline
+const T& lower(const interval<T, Policies>& x)
+{
+ return x.lower();
+}
+
+template<class T, class Policies> inline
+const T& upper(const interval<T, Policies>& x)
+{
+ return x.upper();
+}
+
+template<class T, class Policies> inline
+T checked_lower(const interval<T, Policies>& x)
+{
+ if (empty(x)) {
+ typedef typename Policies::checking checking;
+ return checking::nan();
+ }
+ return x.lower();
+}
+
+template<class T, class Policies> inline
+T checked_upper(const interval<T, Policies>& x)
+{
+ if (empty(x)) {
+ typedef typename Policies::checking checking;
+ return checking::nan();
+ }
+ return x.upper();
+}
+
+template<class T, class Policies> inline
+T width(const interval<T, Policies>& x)
+{
+ if (interval_lib::detail::test_input(x)) return static_cast<T>(0);
+ typename Policies::rounding rnd;
+ return rnd.sub_up(x.upper(), x.lower());
+}
+
+template<class T, class Policies> inline
+T median(const interval<T, Policies>& x)
+{
+ if (interval_lib::detail::test_input(x)) {
+ typedef typename Policies::checking checking;
+ return checking::nan();
+ }
+ typename Policies::rounding rnd;
+ return rnd.median(x.lower(), x.upper());
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> widen(const interval<T, Policies>& x, const T& v)
+{
+ if (interval_lib::detail::test_input(x))
+ return interval<T, Policies>::empty();
+ typename Policies::rounding rnd;
+ return interval<T, Policies>(rnd.sub_down(x.lower(), v),
+ rnd.add_up (x.upper(), v), true);
+}
+
+/*
+ * Set-like operations
+ */
+
+template<class T, class Policies> inline
+bool empty(const interval<T, Policies>& x)
+{
+ return interval_lib::detail::test_input(x);
+}
+
+template<class T, class Policies> inline
+bool zero_in(const interval<T, Policies>& x)
+{
+ if (interval_lib::detail::test_input(x)) return false;
+ return (!interval_lib::user::is_pos(x.lower())) &&
+ (!interval_lib::user::is_neg(x.upper()));
+}
+
+template<class T, class Policies> inline
+bool in_zero(const interval<T, Policies>& x) // DEPRECATED
+{
+ return zero_in<T, Policies>(x);
+}
+
+template<class T, class Policies> inline
+bool in(const T& x, const interval<T, Policies>& y)
+{
+ if (interval_lib::detail::test_input(x, y)) return false;
+ return y.lower() <= x && x <= y.upper();
+}
+
+template<class T, class Policies> inline
+bool subset(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ if (empty(x)) return true;
+ return !empty(y) && y.lower() <= x.lower() && x.upper() <= y.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool proper_subset(const interval<T, Policies1>& x,
+ const interval<T, Policies2>& y)
+{
+ if (empty(y)) return false;
+ if (empty(x)) return true;
+ return y.lower() <= x.lower() && x.upper() <= y.upper() &&
+ (y.lower() != x.lower() || x.upper() != y.upper());
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool overlap(const interval<T, Policies1>& x,
+ const interval<T, Policies2>& y)
+{
+ if (interval_lib::detail::test_input(x, y)) return false;
+ return (x.lower() <= y.lower() && y.lower() <= x.upper()) ||
+ (y.lower() <= x.lower() && x.lower() <= y.upper());
+}
+
+template<class T, class Policies> inline
+bool singleton(const interval<T, Policies>& x)
+{
+ return !empty(x) && x.lower() == x.upper();
+}
+
+template<class T, class Policies1, class Policies2> inline
+bool equal(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
+{
+ if (empty(x)) return empty(y);
+ return !empty(y) && x.lower() == y.lower() && x.upper() == y.upper();
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> intersect(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ BOOST_USING_STD_MIN();
+ BOOST_USING_STD_MAX();
+ if (interval_lib::detail::test_input(x, y))
+ return interval<T, Policies>::empty();
+ const T& l = max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower());
+ const T& u = min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper());
+ if (l <= u) return interval<T, Policies>(l, u, true);
+ else return interval<T, Policies>::empty();
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> hull(const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ BOOST_USING_STD_MIN();
+ BOOST_USING_STD_MAX();
+ bool bad_x = interval_lib::detail::test_input(x);
+ bool bad_y = interval_lib::detail::test_input(y);
+ if (bad_x)
+ if (bad_y) return interval<T, Policies>::empty();
+ else return y;
+ else
+ if (bad_y) return x;
+ return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()),
+ max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> hull(const interval<T, Policies>& x, const T& y)
+{
+ BOOST_USING_STD_MIN();
+ BOOST_USING_STD_MAX();
+ bool bad_x = interval_lib::detail::test_input(x);
+ bool bad_y = interval_lib::detail::test_input<T, Policies>(y);
+ if (bad_y)
+ if (bad_x) return interval<T, Policies>::empty();
+ else return x;
+ else
+ if (bad_x) return interval<T, Policies>(y, y, true);
+ return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y),
+ max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> hull(const T& x, const interval<T, Policies>& y)
+{
+ BOOST_USING_STD_MIN();
+ BOOST_USING_STD_MAX();
+ bool bad_x = interval_lib::detail::test_input<T, Policies>(x);
+ bool bad_y = interval_lib::detail::test_input(y);
+ if (bad_x)
+ if (bad_y) return interval<T, Policies>::empty();
+ else return y;
+ else
+ if (bad_y) return interval<T, Policies>(x, x, true);
+ return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()),
+ max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
+}
+
+template<class T> inline
+interval<T> hull(const T& x, const T& y)
+{
+ return interval<T>::hull(x, y);
+}
+
+template<class T, class Policies> inline
+std::pair<interval<T, Policies>, interval<T, Policies> >
+bisect(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return std::pair<I,I>(I::empty(), I::empty());
+ const T m = median(x);
+ return std::pair<I,I>(I(x.lower(), m, true), I(m, x.upper(), true));
+}
+
+/*
+ * Elementary functions
+ */
+
+template<class T, class Policies> inline
+T norm(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x)) {
+ typedef typename Policies::checking checking;
+ return checking::nan();
+ }
+ BOOST_USING_STD_MAX();
+ return max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper());
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> abs(const interval<T, Policies>& x)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x))
+ return I::empty();
+ if (!interval_lib::user::is_neg(x.lower())) return x;
+ if (!interval_lib::user::is_pos(x.upper())) return -x;
+ BOOST_USING_STD_MAX();
+ return I(static_cast<T>(0), max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MAX();
+ return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MAX();
+ return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MAX();
+ return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
+ const interval<T, Policies>& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MIN();
+ return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MIN();
+ return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
+}
+
+template<class T, class Policies> inline
+interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
+{
+ typedef interval<T, Policies> I;
+ if (interval_lib::detail::test_input(x, y))
+ return I::empty();
+ BOOST_USING_STD_MIN();
+ return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
+}
+
+} // namespace numeric
+} // namespace boost
+
+#endif // BOOST_NUMERIC_INTERVAL_UTILITY_HPP
--- /dev/null
+//
+// Copyright (c) 2010 Athanasios Iliopoulos
+//
+// 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)
+//
+
+#ifndef ASSIGNMENT_HPP
+#define ASSIGNMENT_HPP
+#include <boost/numeric/ublas/vector_expression.hpp>
+#include <boost/numeric/ublas/matrix_expression.hpp>
+
+/*! \file assignment.hpp
+ \brief uBlas assignment operator <<=.
+*/
+
+namespace boost { namespace numeric { namespace ublas {
+
+/** \brief A CRTP and Barton-Nackman trick index manipulator wrapper class.
+ *
+ * This class is not meant to be used directly.
+ */
+template <class TV>
+class index_manipulator {
+public:
+ typedef TV type;
+ BOOST_UBLAS_INLINE
+ const type &operator () () const {
+ return *static_cast<const type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ type &operator () () {
+ return *static_cast<type *> (this);
+ }
+};
+
+/** \brief A move_to vector index manipulator.
+ *
+ * When member function \c manip is called the referenced
+ * index will be set to the manipulators' index.
+ *
+ * \sa move_to(T i)
+ */
+template <typename T>
+class vector_move_to_manip: public index_manipulator<vector_move_to_manip<T> > {
+public:
+ BOOST_UBLAS_INLINE
+ vector_move_to_manip(const T &k): i(k) { }
+
+ template <typename V>
+ BOOST_UBLAS_INLINE
+ void manip(V &k) const { k=i; }
+private:
+ T i;
+};
+
+/** \brief An object generator that returns a move_to vector index manipulator
+ *
+ * \param i The element number the manipulator will move to when \c manip member function is called
+ * \return A move_to vector manipulator
+ *
+ * Example usage:
+ * \code
+ * vector<double> a(6, 0);
+ * a <<= 1, 2, move_to(5), 3;
+ * \endcode
+ * will result in:
+ * \code
+ * 1 2 0 0 0 3
+ * \endcode
+ *
+ * \tparam T Size type
+ * \sa move_to()
+ */
+template <typename T>
+BOOST_UBLAS_INLINE vector_move_to_manip<T> move_to(T i) {
+ return vector_move_to_manip<T>(i);
+}
+
+/** \brief A static move to vector manipulator.
+ *
+ * When member function \c manip is called the referenced
+ * index will be set to the manipulators' index
+ *
+ * \sa move_to(T i) and move_to()
+*/
+template <std::size_t I>
+class static_vector_move_to_manip: public index_manipulator<static_vector_move_to_manip<I> > {
+public:
+ template <typename V>
+ BOOST_UBLAS_INLINE
+ void manip(V &k) const { k=I; }
+};
+
+/** \brief An object generator that returns a static move_to vector index manipulator.
+ *
+ * Typically faster than the dynamic version, but can be used only when the
+ * values are known at compile time.
+ *
+ * \return A static move_to vector manipulator
+ *
+ * Example usage:
+ * \code
+ * vector<double> a(6, 0);
+ * a <<= 1, 2, move_to<5>(), 3;
+ * \endcode
+ * will result in:
+ * \code
+ * 1 2 0 0 0 3
+ * \endcode
+ *
+ * \tparam I The number of elements the manipulator will traverse the index when \c manip function is called
+ */
+template <std::size_t I>
+BOOST_UBLAS_INLINE static_vector_move_to_manip<I> move_to() {
+ return static_vector_move_to_manip<I>();
+}
+
+/** \brief A move vector index manipulator.
+ *
+ * When member function traverse is called the manipulators'
+ * index will be added to the referenced index.
+ *
+ * \see move(T i)
+ */
+template <typename T>
+class vector_move_manip: public index_manipulator<vector_move_manip<T> > {
+public:
+ BOOST_UBLAS_INLINE
+ vector_move_manip(const T &k): i(k) { }
+
+ template <typename V>
+ BOOST_UBLAS_INLINE void manip(V &k) const { k+=i; }
+private:
+ T i;
+};
+
+/**
+* \brief An object generator that returns a move vector index manipulator
+*
+* \tparam T Size type
+* \param i The number of elements the manipulator will traverse the index when \c manip
+* member function is called. Negative values can be used.
+* \return A move vector manipulator
+*
+* Example usage:
+* \code
+* vector<double> a(6, 0);
+* a <<= 1, 2, move(3), 3;
+* \endcode
+* will result in:
+* \code
+* 1 2 0 0 0 3
+* \endcode
+*
+*/
+template <typename T>
+BOOST_UBLAS_INLINE vector_move_manip<T> move(T i) {
+ return vector_move_manip<T>(i);
+}
+
+/**
+* \brief A static move vector manipulator
+*
+* When member function \c manip is called the manipulators
+* index will be added to the referenced index
+*
+* \sa move()
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+template <std::size_t I>
+class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
+public:
+ template <typename V>
+ BOOST_UBLAS_INLINE void manip(V &k) const { k+=I; }
+};
+
+/**
+* \brief An object generator that returns a static move vector index manipulator.
+*
+* Typically faster than the dynamic version, but can be used only when the
+* values are known at compile time.
+* \tparam I The Number of elements the manipulator will traverse the index when \c manip
+* function is called.Negative values can be used.
+* \return A static move vector manipulator
+*
+* Example usage:
+* \code
+* vector<double> a(6, 0);
+* a <<= 1, 2, move<3>(), 3;
+* \endcode
+* will result in:
+* \code
+* 1 2 0 0 0 3
+* \endcode
+*
+* \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() {
+ return static_vector_move_manip<I>();
+}
+
+/**
+* \brief A move_to matrix manipulator
+*
+* When member function \c manip is called the referenced
+* index will be set to the manipulators' index
+*
+* \sa move_to(T i, T j)
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+template <typename T>
+class matrix_move_to_manip: public index_manipulator<matrix_move_to_manip<T> > {
+public:
+ BOOST_UBLAS_INLINE
+ matrix_move_to_manip(T k, T l): i(k), j(l) { }
+
+ template <typename V1, typename V2>
+ BOOST_UBLAS_INLINE
+ void manip(V1 &k, V2 &l) const {
+ k=i;
+ l=j;
+ }
+private:
+ T i, j;
+};
+
+/**
+* \brief An object generator that returns a "move_to" matrix index manipulator
+*
+* \tparam size type
+* \param i The row number the manipulator will move to when \c manip
+* member function is called
+* \param j The column number the manipulator will move to when \c manip
+* member function is called
+* \return A move matrix manipulator
+*
+* Example usage:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, move_to(A.size1()-1, A.size1()-1), 3;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 0 0 0
+* 0 0 3
+* \endcode
+* \sa move_to(T i, T j) and static_matrix_move_to_manip
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+template <typename T>
+BOOST_UBLAS_INLINE matrix_move_to_manip<T> move_to(T i, T j) {
+ return matrix_move_to_manip<T>(i, j);
+}
+
+
+/**
+* \brief A static move_to matrix manipulator
+* When member function traverse is called the referenced
+* index will be set to the manipulators' index
+*
+* \sa move_to()
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+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>
+ BOOST_UBLAS_INLINE
+ void manip(V &k, K &l) const {
+ k=I;
+ l=J;
+ }
+};
+
+/**
+* \brief An object generator that returns a static move_to matrix index manipulator.
+*
+* Typically faster than the dynamic version, but can be used only when the
+* values are known at compile time.
+* \tparam I The row number the manipulator will set the matrix assigner index to.
+* \tparam J The column number the manipulator will set the matrix assigner index to.
+* \return A static move_to matrix manipulator
+*
+* Example usage:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, move_to<2,2>, 3;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 0 0 0
+* 0 0 3
+* \endcode
+* \sa move_to(T i, T j) and static_matrix_move_to_manip
+*/
+template <std::size_t I, std::size_t J>
+BOOST_UBLAS_INLINE static_matrix_move_to_manip<I, J> move_to() {
+ return static_matrix_move_to_manip<I, J>();
+}
+
+/**
+* \brief A move matrix index manipulator.
+*
+* When member function \c manip is called the manipulator's
+* index will be added to the referenced' index.
+*
+* \sa move(T i, T j)
+*/
+template <typename T>
+class matrix_move_manip: public index_manipulator<matrix_move_manip<T> > {
+public:
+ BOOST_UBLAS_INLINE
+ matrix_move_manip(T k, T l): i(k), j(l) { }
+
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V &k, K &l) const {
+ k+=i;
+ l+=j;
+ }
+private:
+ T i, j;
+};
+
+/**
+* \brief An object generator that returns a move matrix index manipulator
+*
+* \tparam size type
+* \param i The number of rows the manipulator will traverse the index when "manip"
+* member function is called
+* \param j The number of columns the manipulator will traverse the index when "manip"
+* member function is called
+* \return A move matrix manipulator
+*
+* Example:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, move(1,0),
+* 3,;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 0 0 3
+* 0 0 0
+* \endcode
+*/
+template <typename T>
+BOOST_UBLAS_INLINE matrix_move_manip<T> move(T i, T j) {
+ return matrix_move_manip<T>(i, j);
+}
+
+/**
+* \brief A static move matrix index manipulator.
+*
+* When member function traverse is called the manipulator's
+* index will be added to the referenced' index.
+*
+* \sa move()
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+template <std::size_t I, std::size_t J>
+class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
+public:
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V &k, K &l) const {
+ k+=I;
+ l+=J;
+ }
+};
+
+/**
+* \brief An object generator that returns a static "move" matrix index manipulator.
+*
+* Typically faster than the dynamic version, but can be used only when the
+* values are known at compile time. Negative values can be used.
+* \tparam I The number of rows the manipulator will trasverse the matrix assigner index.
+* \tparam J The number of columns the manipulator will trasverse the matrix assigner index.
+* \tparam size type
+* \return A static move matrix manipulator
+*
+* Example:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, move<1,0>(),
+* 3,;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 0 0 3
+* 0 0 0
+* \endcode
+*
+* \sa move_to()
+*
+* \todo Doxygen has some problems with similar template functions. Correct that.
+*/
+template <std::size_t I, std::size_t J>
+BOOST_UBLAS_INLINE static_matrix_move_manip<I, J> move() {
+ return static_matrix_move_manip<I, J>();
+}
+
+/**
+* \brief A begining of row manipulator
+*
+* When member function \c manip is called the referenced
+* index will be be set to the begining of the row (i.e. column = 0)
+*
+* \sa begin1()
+*/
+class begin1_manip: public index_manipulator<begin1_manip > {
+public:
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V & k, K &/*l*/) const {
+ k=0;
+ }
+};
+
+/**
+* \brief An object generator that returns a begin1 manipulator.
+*
+* The resulted manipulator will traverse the index to the begining
+* of the current column when its' \c manip member function is called.
+*
+* \return A begin1 matrix index manipulator
+*
+* Example usage:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, next_row(),
+* 3, 4, begin1(), 1;
+* \endcode
+* will result in:
+* \code
+* 1 2 1
+* 3 4 0
+* 0 0 0
+* \endcode
+* \sa begin2()
+*/
+BOOST_UBLAS_INLINE begin1_manip begin1() {
+ return begin1_manip();
+}
+
+/**
+* \brief A begining of column manipulator
+*
+* When member function \c manip is called the referenced
+* index will be be set to the begining of the column (i.e. row = 0).
+*
+*
+* \sa begin2()
+*/
+class begin2_manip: public index_manipulator<begin2_manip > {
+public:
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V &/*k*/, K &l) const {
+ l=0;
+ }
+};
+
+/**
+* \brief An object generator that returns a begin2 manipulator to be used to traverse a matrix.
+*
+* The resulted manipulator will traverse the index to the begining
+* of the current row when its' \c manip member function is called.
+*
+* \return A begin2 matrix manipulator
+*
+* Example:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, move<1,0>(),
+* 3, begin2(), 1;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 1 0 3
+* 0 0 0
+* \endcode
+* \sa begin1() begin2_manip
+*/
+BOOST_UBLAS_INLINE begin2_manip begin2() {
+ return begin2_manip();
+}
+
+
+/**
+* \brief A next row matrix manipulator.
+*
+* When member function traverse is called the referenced
+* index will be traveresed to the begining of next row.
+*
+* \sa next_row()
+*/
+class next_row_manip: public index_manipulator<next_row_manip> {
+public:
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V &k, K &l) const {
+ k++;
+ l=0;
+ }
+};
+
+/**
+* \brief An object generator that returns a next_row manipulator.
+*
+* The resulted manipulator will traverse the index to the begining
+* of the next row when it's manip member function is called.
+*
+* \return A next_row matrix manipulator.
+*
+* Example:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, next_row(),
+* 3, 4;
+* \endcode
+* will result in:
+* \code
+* 1 2 0
+* 3 4 0
+* 0 0 0
+* \endcode
+* \sa next_column()
+*/
+BOOST_UBLAS_INLINE next_row_manip next_row() {
+ return next_row_manip();
+}
+
+/**
+* \brief A next column matrix manipulator.
+*
+* When member function traverse is called the referenced
+* index will be traveresed to the begining of next column.
+*
+* \sa next_column()
+*/
+class next_column_manip: public index_manipulator<next_column_manip> {
+public:
+ template <typename V, typename K>
+ BOOST_UBLAS_INLINE
+ void manip(V &k, K &l) const {
+ k=0;
+ l++;
+ }
+};
+
+/**
+* \brief An object generator that returns a next_row manipulator.
+*
+* The resulted manipulator will traverse the index to the begining
+* of the next column when it's manip member function is called.
+*
+* \return A next_column matrix manipulator.
+*
+* Example:
+* \code:
+* matrix<double> A(3, 3, 0);
+* A <<= 1, 2, 0,
+* 3, next_column(), 4;
+* \endcode
+* will result in:
+* \code
+* 1 2 4
+* 3 0 0
+* 0 0 0
+* \endcode
+*
+*/
+BOOST_UBLAS_INLINE next_column_manip next_column() {
+ return next_column_manip();
+}
+
+/**
+* \brief A wrapper for fill policy classes
+*
+*/
+template <class T>
+class fill_policy_wrapper {
+public:
+ typedef T type;
+};
+
+// Collection of the fill policies
+namespace fill_policy {
+
+ /**
+ * \brief An index assign policy
+ *
+ * This policy is used to for the simplified ublas assign through
+ * normal indexing.
+ *
+ *
+ */
+ class index_assign :public fill_policy_wrapper<index_assign> {
+ public:
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const V &v) {
+ e()(i) = v;
+ }
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const S &j, const V &v) {
+ e()(i, j) = v;
+ }
+ };
+
+ /**
+ * \brief An index plus assign policy
+ *
+ * This policy is used when the assignment is desired to be followed
+ * by an addition.
+ *
+ *
+ */
+ class index_plus_assign :public fill_policy_wrapper<index_plus_assign> {
+ public:
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const V &v) {
+ e()(i) += v;
+ }
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const S &j, const V &v) {
+ e()(i, j) += v;
+ }
+ };
+
+ /**
+ * \brief An index minus assign policy
+ *
+ * This policy is used when the assignment is desired to be followed
+ * by a substraction.
+ *
+ *
+ */
+ class index_minus_assign :public fill_policy_wrapper<index_minus_assign> {
+ public:
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const V &v) {
+ e()(i) -= v;
+ }
+ template <class T, typename S, typename V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const S &j, const V &v) {
+ e()(i, j) -= v;
+ }
+ };
+
+ /**
+ * \brief The sparse push_back fill policy.
+ *
+ * This policy is adequate for sparse types, when fast filling is required, where indexing
+ * assign is pretty slow.
+
+ * It is important to note that push_back assign cannot be used to add elements before elements
+ * already existing in a sparse container. To achieve that please use the sparse_insert fill policy.
+ */
+ class sparse_push_back :public fill_policy_wrapper<sparse_push_back > {
+ public:
+ template <class T, class S, class V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const V &v) {
+ e().push_back(i, v);
+ }
+ template <class T, class S, class V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const S &j, const V &v) {
+ e().push_back(i,j, v);
+ }
+ };
+
+ /**
+ * \brief The sparse insert fill policy.
+ *
+ * This policy is adequate for sparse types, when fast filling is required, where indexing
+ * assign is pretty slow. It is slower than sparse_push_back fill policy, but it can be used to
+ * insert elements anywhere inside the container.
+ */
+ class sparse_insert :public fill_policy_wrapper<sparse_insert> {
+ public:
+ template <class T, class S, class V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const V &v) {
+ e().insert_element(i, v);
+ }
+ template <class T, class S, class V>
+ BOOST_UBLAS_INLINE
+ static void apply(T &e, const S &i, const S &j, const V &v) {
+ e().insert_element(i,j, v);
+ }
+ };
+
+}
+
+/** \brief A wrapper for traverse policy classes
+*
+*/
+template <class T>
+class traverse_policy_wrapper {
+public:
+ typedef T type;
+};
+
+// Collection of the traverse policies
+namespace traverse_policy {
+
+
+ /**
+ * \brief The no wrap policy.
+ *
+ * The no wrap policy does not allow wrapping when assigning to a matrix
+ */
+ struct no_wrap {
+ /**
+ * \brief Element wrap method
+ */
+ template <class S1, class S2, class S3>
+ BOOST_UBLAS_INLINE
+ static void apply1(const S1 &/*s*/, S2 &/*i*/, S3 &/*j*/) {
+ }
+
+ /**
+ * \brief Matrix block wrap method
+ */
+ template <class S1, class S2, class S3>
+ BOOST_UBLAS_INLINE
+ static void apply2(const S1 &/*s1*/, const S1 &/*s2*/, S2 &/*i1*/, S3 &/*i2*/) {
+ }
+ };
+
+ /**
+ * \brief The wrap policy.
+ *
+ * The wrap policy enables element wrapping when assigning to a matrix
+ */
+ struct wrap {
+ /**
+ * \brief Element wrap method
+ */
+ template <class S1, class S2, class S3>
+ BOOST_UBLAS_INLINE
+ static void apply1(const S1 &s, S2 &i1, S3 &i2) {
+ if (i2>=s) {
+ i1++;
+ i2=0;
+ }
+ }
+
+ /**
+ * \brief Matrix block wrap method
+ */
+ template <class S1, class S2, class S3>
+ BOOST_UBLAS_INLINE
+ static void apply2(const S1 &s1, const S1 &s2, S2 &i1, S3 &i2) {
+ if (i2>=s2) i2=0; // Wrap to the next block
+ else i1-=s1; // Move up (or right) one block
+ }
+ };
+
+ /**
+ * \brief The row_by_row traverse policy
+ *
+ * This policy is used when the assignment is desired to happen
+ * row_major wise for performance or other reasons.
+ *
+ * This is the default behaviour. To change it globally please define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
+ * in the compilation options or in an adequate header file.
+ *
+ * Please see EXAMPLES_LINK for usage information.
+ *
+ * \todo Add examples link
+ */
+ template <class Wrap = wrap>
+ class by_row_policy :public traverse_policy_wrapper<by_row_policy<Wrap> > {
+ public:
+ template <typename S1, typename S2>
+ BOOST_UBLAS_INLINE
+ static void advance(S1 &/*i*/, S2 &j) { j++;}
+
+ template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
+ BOOST_UBLAS_INLINE
+ static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &/*i0*/, const S3 &j0, S4 &k, S5 &l) {
+ 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
+ // an assigner object.
+ // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
+ // outside the if statement.
+ if (k>=e().size1()) {
+ j=j0+e().size2();
+ Wrap::apply2(e().size1(), me().size2(), i, j);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template <class E, typename S1, typename S2>
+ BOOST_UBLAS_INLINE
+ static void apply_wrap(const E& e, S1 &i, S2 &j) {
+ Wrap::apply1(e().size2(), i, j);
+ }
+ };
+
+ /**
+ * \brief The column_by_column traverse policy
+ *
+ * This policy is used when the assignment is desired to happen
+ * column_major wise, for performance or other reasons.
+ *
+ * This is the NOT the default behaviour. To set this as the default define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
+ * in the compilation options or in an adequate header file.
+ *
+ * Please see EXAMPLES_LINK for usage information.
+ *
+ * \todo Add examples link
+ */
+ template <class Wrap = wrap>
+ class by_column_policy :public traverse_policy_wrapper<by_column_policy<Wrap> > {
+ public:
+ template <typename S1, typename S2>
+ BOOST_UBLAS_INLINE
+ static void advance(S1 &i, S2 &/*j*/) { i++;}
+
+ template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
+ BOOST_UBLAS_INLINE
+ static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &i0, const S3 &/*j0*/, S4 &k, S5 &l) {
+ 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
+ // an assigner object.
+ // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
+ // outside the if statement.
+ if (l>=e().size2()) {
+ i=i0+e().size1();
+ Wrap::apply2(e().size2(), me().size1(), j, i);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template <class E, typename S1, typename S2>
+ BOOST_UBLAS_INLINE
+ static void apply_wrap(const E& e, S1 &i, S2 &j) {
+ Wrap::apply1(e().size1(), j, i);
+ }
+ };
+}
+#ifndef BOOST_UBLAS_DEFAULT_NO_WRAP_POLICY
+ typedef traverse_policy::wrap DEFAULT_WRAP_POLICY;
+#else
+ typedef traverse_policy::no_wrap DEFAULT_WRAP_POLICY;
+#endif
+
+#ifndef BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
+ typedef traverse_policy::by_row_policy<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
+#else
+ typedef traverse_policy::by_column<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
+#endif
+
+ // Traverse policy namespace
+namespace traverse_policy {
+
+ by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
+ return by_row_policy<DEFAULT_WRAP_POLICY>();
+ }
+
+ by_row_policy<wrap> by_row_wrap() {
+ return by_row_policy<wrap>();
+ }
+
+ by_row_policy<no_wrap> by_row_no_wrap() {
+ return by_row_policy<no_wrap>();
+ }
+
+ by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
+ return by_column_policy<DEFAULT_WRAP_POLICY>();
+ }
+
+ by_column_policy<wrap> by_column_wrap() {
+ return by_column_policy<wrap>();
+ }
+
+ by_column_policy<no_wrap> by_column_no_wrap() {
+ return by_column_policy<no_wrap>();
+ }
+
+}
+
+/**
+* \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
+*
+* This object is meant to be created by appropriate object generators.
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, class Fill_Policy = fill_policy::index_assign>
+class vector_expression_assigner {
+public:
+ typedef typename E::expression_type::value_type value_type;
+ typedef typename E::expression_type::size_type size_type;
+
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner(E &e):ve(e), i(0) {
+ }
+
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner(size_type k, E &e):ve(e), i(k) {
+ // Overloaded like that so it can be differentiated from (E, val).
+ // Otherwise there would be an ambiquity when value_type == size_type.
+ }
+
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner(E &e, value_type val):ve(e), i(0) {
+ operator,(val);
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(e), i(0) {
+ operator,(nve);
+ }
+
+ template <typename T>
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(e), i(0) {
+ operator,(ta);
+ }
+
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner &operator, (const value_type& val) {
+ apply(val);
+ return *this;
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner &operator, (const vector_expression<AE> &nve) {
+ for (typename AE::size_type k = 0; k!= nve().size(); k++)
+ operator,(nve()(k));
+ return *this;
+ }
+
+ template <typename T>
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner &operator, (const index_manipulator<T> &ta) {
+ ta().manip(i);
+ return *this;
+ }
+
+ template <class T>
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner<E, T> operator, (fill_policy_wrapper<T>) const {
+ return vector_expression_assigner<E, T>(i, ve);
+ }
+
+private:
+ BOOST_UBLAS_INLINE
+ vector_expression_assigner &apply(const typename E::expression_type::value_type& val) {
+ Fill_Policy::apply(ve, i++, val);
+ return *this;
+ }
+
+private:
+ E &ve;
+ size_type i;
+};
+
+/*
+// The following static assigner is about 30% slower than the dynamic one, probably due to the recursive creation of assigner objects.
+// It remains commented here for future reference.
+
+template <class E, std::size_t I=0>
+class static_vector_expression_assigner {
+public:
+ typedef typename E::expression_type::value_type value_type;
+ typedef typename E::expression_type::size_type size_type;
+
+ BOOST_UBLAS_INLINE
+ static_vector_expression_assigner(E &e):ve(e) {
+ }
+
+ BOOST_UBLAS_INLINE
+ static_vector_expression_assigner(E &e, value_type val):ve(e) {
+ operator,(val);
+ }
+
+ BOOST_UBLAS_INLINE
+ static_vector_expression_assigner<E, I+1> operator, (const value_type& val) {
+ return apply(val);
+ }
+
+private:
+ BOOST_UBLAS_INLINE
+ static_vector_expression_assigner<E, I+1> apply(const typename E::expression_type::value_type& val) {
+ ve()(I)=val;
+ return static_vector_expression_assigner<E, I+1>(ve);
+ }
+
+private:
+ E &ve;
+};
+
+template <class E>
+BOOST_UBLAS_INLINE
+static_vector_expression_assigner<vector_expression<E>, 1 > test_static(vector_expression<E> &v, const typename E::value_type &val) {
+ v()(0)=val;
+ return static_vector_expression_assigner<vector_expression<E>, 1 >(v);
+}
+*/
+
+
+/**
+* \brief A vector_expression_assigner generator used with operator<<= for simple types
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E>
+BOOST_UBLAS_INLINE
+vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const typename E::value_type &val) {
+ return vector_expression_assigner<vector_expression<E> >(v,val);
+}
+
+/**
+* \brief ! A vector_expression_assigner generator used with operator<<= for vector expressions
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E1, class E2>
+BOOST_UBLAS_INLINE
+vector_expression_assigner<vector_expression<E1> > operator<<=(vector_expression<E1> &v, const vector_expression<E2> &ve) {
+ return vector_expression_assigner<vector_expression<E1> >(v,ve);
+}
+
+/**
+* \brief A vector_expression_assigner generator used with operator<<= for traverse manipulators
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, typename T>
+BOOST_UBLAS_INLINE
+vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const index_manipulator<T> &nv) {
+ return vector_expression_assigner<vector_expression<E> >(v,nv);
+}
+
+/**
+* \brief A vector_expression_assigner generator used with operator<<= for choice of fill policy
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, typename T>
+BOOST_UBLAS_INLINE
+vector_expression_assigner<vector_expression<E>, T> operator<<=(vector_expression<E> &v, fill_policy_wrapper<T>) {
+ return vector_expression_assigner<vector_expression<E>, T>(v);
+}
+
+/**
+* \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
+*
+* This object is meant to be created by appropriate object generators.
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, class Fill_Policy = fill_policy::index_assign, class Traverse_Policy = DEFAULT_TRAVERSE_POLICY >
+class matrix_expression_assigner {
+public:
+ typedef typename E::expression_type::size_type size_type;
+
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e): me(e), i(0), j(0) {
+ }
+
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e, size_type k, size_type l): me(e), i(k), j(l) {
+ }
+
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(e), i(0), j(0) {
+ operator,(val);
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e, const vector_expression<AE> &nve):me(e), i(0), j(0) {
+ operator,(nve);
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e, const matrix_expression<AE> &nme):me(e), i(0), j(0) {
+ operator,(nme);
+ }
+
+ template <typename T>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner(E &e, const index_manipulator<T> &ta):me(e), i(0), j(0) {
+ operator,(ta);
+ }
+
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &operator, (const typename E::expression_type::value_type& val) {
+ Traverse_Policy::apply_wrap(me, i ,j);
+ return apply(val);
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &operator, (const vector_expression<AE> &nve) {
+ for (typename AE::size_type k = 0; k!= nve().size(); k++) {
+ operator,(nve()(k));
+ }
+ return *this;
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &operator, (const matrix_expression<AE> &nme) {
+ return apply(nme);
+ }
+
+ template <typename T>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &operator, (const index_manipulator<T> &ta) {
+ ta().manip(i, j);
+ return *this;
+ }
+
+ template <class T>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner<E, T, Traverse_Policy> operator, (fill_policy_wrapper<T>) const {
+ return matrix_expression_assigner<E, T, Traverse_Policy>(me, i, j);
+ }
+
+
+ template <class T>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner<E, Fill_Policy, T> operator, (traverse_policy_wrapper<T>) {
+ Traverse_Policy::apply_wrap(me, i ,j);
+ return matrix_expression_assigner<E, Fill_Policy, T>(me, i, j);
+ }
+
+private:
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &apply(const typename E::expression_type::value_type& val) {
+ Fill_Policy::apply(me, i, j, val);
+ Traverse_Policy::advance(i,j);
+ return *this;
+ }
+
+ template <class AE>
+ BOOST_UBLAS_INLINE
+ matrix_expression_assigner &apply(const matrix_expression<AE> &nme) {
+ size_type bi = i;
+ size_type bj = j;
+ typename AE::size_type k=0, l=0;
+ Fill_Policy::apply(me, i, j, nme()(k, l));
+ while (Traverse_Policy::next(nme, me, i, j, bi, bj, k, l))
+ Fill_Policy::apply(me, i, j, nme()(k, l));
+ return *this;
+ }
+
+private:
+ E &me;
+ size_type i, j;
+};
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for simple types
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const typename E::value_type &val) {
+ return matrix_expression_assigner<matrix_expression<E> >(me,val);
+}
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for choice of fill policy
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, typename T>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E>, T> operator<<=(matrix_expression<E> &me, fill_policy_wrapper<T>) {
+ return matrix_expression_assigner<matrix_expression<E>, T>(me);
+}
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, typename T>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const index_manipulator<T> &ta) {
+ return matrix_expression_assigner<matrix_expression<E> >(me,ta);
+}
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E, typename T>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T> operator<<=(matrix_expression<E> &me, traverse_policy_wrapper<T>) {
+ return matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T>(me);
+}
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for vector expressions
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E1, class E2>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me, const vector_expression<E2> &ve) {
+ return matrix_expression_assigner<matrix_expression<E1> >(me,ve);
+}
+
+/**
+* \brief A matrix_expression_assigner generator used with operator<<= for matrix expressions
+*
+* Please see EXAMPLES_LINK for usage information.
+*
+* \todo Add examples link
+*/
+template <class E1, class E2>
+BOOST_UBLAS_INLINE
+matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me1, const matrix_expression<E2> &me2) {
+ return matrix_expression_assigner<matrix_expression<E1> >(me1,me2);
+}
+
+} } }
+
+#endif // ASSIGNMENT_HPP
--- /dev/null
+//
+// 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_BANDED_
+#define _BOOST_UBLAS_BANDED_
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/detail/temporary.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief A banded matrix of values of type \c T.
+ *
+ * For a \f$(mxn)\f$-dimensional banded matrix with \f$l\f$ lower and \f$u\f$ upper diagonals and
+ * \f$0 \leq i < m\f$ and \f$0 \leq j < n\f$, if \f$i>j+l\f$ or \f$i<j-u\f$ then \f$b_{i,j}=0\f$.
+ * The default storage for banded matrices is packed. Orientation and storage can also be specified.
+ * Default is \c row_major and and unbounded_array. It is \b not required by the storage to initialize
+ * elements of the matrix.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
+ * \tparam A the type of Storage array. Default is \c unbounded_array
+ */
+ template<class T, class L, class A>
+ class banded_matrix:
+ public matrix_container<banded_matrix<T, L, A> > {
+
+ typedef T *pointer;
+ typedef L layout_type;
+ typedef banded_matrix<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef A array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, A> vector_temporary_type;
+ typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
+ typedef packed_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ banded_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0),
+ lower_ (0), upper_ (0), data_ (0) {}
+ BOOST_UBLAS_INLINE
+ banded_matrix (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2),
+ lower_ (lower), upper_ (upper), data_ ((std::max) (size1, size2) * (lower + 1 + upper)) {
+ }
+ BOOST_UBLAS_INLINE
+ banded_matrix (size_type size1, size_type size2, size_type lower, size_type upper, const array_type &data):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2),
+ lower_ (lower), upper_ (upper), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ banded_matrix (const banded_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_),
+ lower_ (m.lower_), upper_ (m.upper_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix (const matrix_expression<AE> &ae, size_type lower = 0, size_type upper = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
+ lower_ (lower), upper_ (upper),
+ data_ ((std::max) (size1_, size2_) * (lower_ + 1 + upper_)) {
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type lower () const {
+ return lower_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type upper () const {
+ return upper_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0, bool preserve = true) {
+ if (preserve) {
+ self_type temporary (size1, size2, lower, upper);
+ detail::matrix_resize_preserve<layout_type> (*this, temporary);
+ }
+ else {
+ data ().resize ((std::max) (size1, size2) * (lower + 1 + upper));
+ size1_ = size1;
+ size2_ = size2;
+ lower_ = lower;
+ upper_ = upper;
+ }
+ }
+
+ BOOST_UBLAS_INLINE
+ void resize_packed_preserve (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0) {
+ size1_ = size1;
+ size2_ = size2;
+ lower_ = lower;
+ upper_ = upper;
+ data ().resize ((std::max) (size1, size2) * (lower + 1 + upper), value_type ());
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ const size_type k = (std::max) (i, j);
+ const size_type l = lower_ + j - i;
+ if (k < (std::max) (size1_, size2_) &&
+ l < lower_ + 1 + upper_)
+ return data () [layout_type::element (k, (std::max) (size1_, size2_),
+ l, lower_ + 1 + upper_)];
+#else
+ const size_type k = j;
+ const size_type l = upper_ + i - j;
+ if (k < size2_ &&
+ l < lower_ + 1 + upper_)
+ return data () [layout_type::element (k, size2_,
+ l, lower_ + 1 + upper_)];
+#endif
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ const size_type k = (std::max) (i, j);
+ const size_type l = lower_ + j - i;
+ return data () [layout_type::element (k, (std::max) (size1_, size2_),
+ l, lower_ + 1 + upper_)];
+#else
+ const size_type k = j;
+ const size_type l = upper_ + i - j;
+ return data () [layout_type::element (k, size2_,
+ l, lower_ + 1 + upper_)];
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ const size_type k = (std::max) (i, j);
+ const size_type l = lower_ + j - i;
+ if (! (k < (std::max) (size1_, size2_) &&
+ l < lower_ + 1 + upper_) ) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return data () [layout_type::element (k, (std::max) (size1_, size2_),
+ l, lower_ + 1 + upper_)];
+#else
+ const size_type k = j;
+ const size_type l = upper_ + i - j;
+ if (! (k < size2_ &&
+ l < lower_ + 1 + upper_) ) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return data () [layout_type::element (k, size2_,
+ l, lower_ + 1 + upper_)];
+#endif
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (operator () (i, j) = t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ operator () (i, j) = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ std::fill (data ().begin (), data ().end (), value_type/*zero*/());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ banded_matrix &operator = (const banded_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ lower_ = m.lower_;
+ upper_ = m.upper_;
+ data () = m.data ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ banded_matrix &assign_temporary (banded_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae, lower_, upper_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae, lower_, upper_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae, lower_, upper_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ banded_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ banded_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (banded_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ std::swap (lower_, m.lower_);
+ std::swap (upper_, m.upper_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (banded_matrix &m1, banded_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
+ i = (std::max) (i, lower_i);
+ size_type upper_i = (std::min) (j + 1 + lower_, size1_);
+ i = (std::min) (i, upper_i);
+ }
+ return const_iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1) {
+ size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
+ i = (std::max) (i, lower_i);
+ size_type upper_i = (std::min) (j + 1 + lower_, size1_);
+ i = (std::min) (i, upper_i);
+ }
+ return iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
+ j = (std::max) (j, lower_j);
+ size_type upper_j = (std::min) (i + 1 + upper_, size2_);
+ j = (std::min) (j, upper_j);
+ }
+ return const_iterator2 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1) {
+ size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
+ j = (std::max) (j, lower_j);
+ size_type upper_j = (std::min) (i + 1 + upper_, size2_);
+ j = (std::min) (j, upper_j);
+ }
+ return iterator2 (*this, i, j);
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<banded_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename banded_matrix::value_type value_type;
+ typedef typename banded_matrix::difference_type difference_type;
+ typedef typename banded_matrix::const_reference reference;
+ typedef const typename banded_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<banded_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename banded_matrix::value_type value_type;
+ typedef typename banded_matrix::difference_type difference_type;
+ typedef typename banded_matrix::reference reference;
+ typedef typename banded_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) ().at_element (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<banded_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename banded_matrix::value_type value_type;
+ typedef typename banded_matrix::difference_type difference_type;
+ typedef typename banded_matrix::const_reference reference;
+ typedef const typename banded_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<banded_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename banded_matrix::value_type value_type;
+ typedef typename banded_matrix::difference_type difference_type;
+ typedef typename banded_matrix::reference reference;
+ typedef typename banded_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) ().at_element (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ size_type lower_;
+ size_type upper_;
+ array_type data_;
+ typedef const value_type const_value_type;
+ static const_value_type zero_;
+ };
+
+ template<class T, class L, class A>
+ typename banded_matrix<T, L, A>::const_value_type banded_matrix<T, L, A>::zero_ = value_type/*zero*/();
+
+
+ /** \brief A diagonal matrix of values of type \c T, which is a specialization of a banded matrix
+ *
+ * For a \f$(m\times m)\f$-dimensional diagonal matrix, \f$0 \leq i < m\f$ and \f$0 \leq j < m\f$,
+ * if \f$i\neq j\f$ then \f$b_{i,j}=0\f$. The default storage for diagonal matrices is packed.
+ * Orientation and storage can also be specified. Default is \c row major \c unbounded_array.
+ *
+ * As a specialization of a banded matrix, the constructor of the diagonal matrix creates
+ * a banded matrix with 0 upper and lower diagonals around the main diagonal and the matrix is
+ * obviously a square matrix. Operations are optimized based on these 2 assumptions. It is
+ * \b not required by the storage to initialize elements of the matrix.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
+ * \tparam A the type of Storage array. Default is \c unbounded_array
+ */
+ template<class T, class L, class A>
+ class diagonal_matrix:
+ public banded_matrix<T, L, A> {
+ public:
+ typedef typename A::size_type size_type;
+ typedef banded_matrix<T, L, A> matrix_type;
+ typedef A array_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ diagonal_matrix ():
+ matrix_type () {}
+ BOOST_UBLAS_INLINE
+ diagonal_matrix (size_type size):
+ matrix_type (size, size) {}
+ BOOST_UBLAS_INLINE
+ diagonal_matrix (size_type size, const array_type& data):
+ matrix_type (size, size, 0, 0, data) {}
+ BOOST_UBLAS_INLINE
+ diagonal_matrix (size_type size1, size_type size2):
+ matrix_type (size1, size2) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ diagonal_matrix (const matrix_expression<AE> &ae):
+ matrix_type (ae) {}
+ BOOST_UBLAS_INLINE
+ ~diagonal_matrix () {}
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ diagonal_matrix &operator = (const diagonal_matrix &m) {
+ matrix_type::operator = (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ diagonal_matrix &operator = (const matrix_expression<AE> &ae) {
+ matrix_type::operator = (ae);
+ return *this;
+ }
+ };
+
+ /** \brief A banded matrix adaptator: convert a any matrix into a banded matrix expression
+ *
+ * For a \f$(m\times n)\f$-dimensional matrix, the \c banded_adaptor will provide a banded matrix
+ * with \f$l\f$ lower and \f$u\f$ upper diagonals and \f$0 \leq i < m\f$ and \f$0 \leq j < n\f$,
+ * if \f$i>j+l\f$ or \f$i<j-u\f$ then \f$b_{i,j}=0\f$.
+ *
+ * Storage and location are based on those of the underlying matrix. This is important because
+ * a \c banded_adaptor does not copy the matrix data to a new place. Therefore, modifying values
+ * in a \c banded_adaptor matrix will also modify the underlying matrix too.
+ *
+ * \tparam M the type of matrix used to generate a banded matrix
+ */
+ template<class M>
+ class banded_adaptor:
+ public matrix_expression<banded_adaptor<M> > {
+
+ typedef banded_adaptor<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef const M const_matrix_type;
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ // Replaced by _temporary_traits to avoid type requirements on M
+ //typedef typename M::vector_temporary_type vector_temporary_type;
+ //typedef typename M::matrix_temporary_type matrix_temporary_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ packed_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ banded_adaptor (matrix_type &data, size_type lower = 0, size_type upper = 0):
+ matrix_expression<self_type> (),
+ data_ (data), lower_ (lower), upper_ (upper) {}
+ BOOST_UBLAS_INLINE
+ banded_adaptor (const banded_adaptor &m):
+ matrix_expression<self_type> (),
+ data_ (m.data_), lower_ (m.lower_), upper_ (m.upper_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return data_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return data_.size2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type lower () const {
+ return lower_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type upper () const {
+ return upper_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = lower_ + j - i;
+ if (k < (std::max) (size1 (), size2 ()) &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#else
+ size_type k = j;
+ size_type l = upper_ + i - j;
+ if (k < size2 () &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#endif
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = lower_ + j - i;
+ if (k < (std::max) (size1 (), size2 ()) &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#else
+ size_type k = j;
+ size_type l = upper_ + i - j;
+ if (k < size2 () &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#endif
+#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
+ bad_index ().raise ();
+#endif
+ return const_cast<reference>(zero_);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = lower_ + j - i;
+ if (k < (std::max) (size1 (), size2 ()) &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#else
+ size_type k = j;
+ size_type l = upper_ + i - j;
+ if (k < size2 () &&
+ l < lower_ + 1 + upper_)
+ return data () (i, j);
+#endif
+#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
+ bad_index ().raise ();
+#endif
+ return const_cast<reference>(zero_);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ banded_adaptor &operator = (const banded_adaptor &m) {
+ matrix_assign<scalar_assign> (*this, m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ banded_adaptor &assign_temporary (banded_adaptor &m) {
+ *this = m;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ banded_adaptor &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ banded_adaptor& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ banded_adaptor& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const banded_adaptor &ba) const {
+ return (*this).data ().same_closure (ba.data ());
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (banded_adaptor &m) {
+ if (this != &m) {
+ BOOST_UBLAS_CHECK (lower_ == m.lower_, bad_size ());
+ BOOST_UBLAS_CHECK (upper_ == m.upper_, bad_size ());
+ matrix_swap<scalar_swap> (*this, m);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (banded_adaptor &m1, banded_adaptor &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use the matrix iterator
+ typedef typename M::const_iterator1 const_subiterator1_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator1_type;
+ typedef typename M::const_iterator2 const_subiterator2_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
+ i = (std::max) (i, lower_i);
+ size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
+ i = (std::min) (i, upper_i);
+ }
+ return const_iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1) {
+ size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
+ i = (std::max) (i, lower_i);
+ size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
+ i = (std::min) (i, upper_i);
+ }
+ return iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
+ j = (std::max) (j, lower_j);
+ size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
+ j = (std::min) (j, upper_j);
+ }
+ return const_iterator2 (*this, data ().find2 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1) {
+ size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
+ j = (std::max) (j, lower_j);
+ size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
+ j = (std::min) (j, upper_j);
+ }
+ return iterator2 (*this, data ().find2 (rank, i, j));
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<banded_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ const_iterator1, value_type> {
+ public:
+ typedef typename const_subiterator1_type::value_type value_type;
+ typedef typename const_subiterator1_type::difference_type difference_type;
+ typedef typename const_subiterator1_type::reference reference;
+ typedef typename const_subiterator1_type::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (m), it1_ (it1) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = (*this) ().lower () + j - i;
+ if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it1_;
+#else
+ size_type k = j;
+ size_type l = (*this) ().upper () + i - j;
+ if (k < (*this) ().size2 () &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it1_;
+#endif
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<banded_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator1, value_type> {
+ public:
+ typedef typename subiterator1_type::value_type value_type;
+ typedef typename subiterator1_type::difference_type difference_type;
+ typedef typename subiterator1_type::reference reference;
+ typedef typename subiterator1_type::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator1_type &it1):
+ container_reference<self_type> (m), it1_ (it1) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = (*this) ().lower () + j - i;
+ if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it1_;
+#else
+ size_type k = j;
+ size_type l = (*this) ().upper () + i - j;
+ if (k < (*this) ().size2 () &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it1_;
+#endif
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<banded_adaptor>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename iterator_restrict_traits<typename const_subiterator2_type::iterator_category,
+ packed_random_access_iterator_tag>::iterator_category iterator_category;
+ typedef typename const_subiterator2_type::value_type value_type;
+ typedef typename const_subiterator2_type::difference_type difference_type;
+ typedef typename const_subiterator2_type::reference reference;
+ typedef typename const_subiterator2_type::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (m), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = (*this) ().lower () + j - i;
+ if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it2_;
+#else
+ size_type k = j;
+ size_type l = (*this) ().upper () + i - j;
+ if (k < (*this) ().size2 () &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it2_;
+#endif
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<banded_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator2, value_type> {
+ public:
+ typedef typename subiterator2_type::value_type value_type;
+ typedef typename subiterator2_type::difference_type difference_type;
+ typedef typename subiterator2_type::reference reference;
+ typedef typename subiterator2_type::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator2_type &it2):
+ container_reference<self_type> (m), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+#ifdef BOOST_UBLAS_OWN_BANDED
+ size_type k = (std::max) (i, j);
+ size_type l = (*this) ().lower () + j - i;
+ if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it2_;
+#else
+ size_type k = j;
+ size_type l = (*this) ().upper () + i - j;
+ if (k < (*this) ().size2 () &&
+ l < (*this) ().lower () + 1 + (*this) ().upper ())
+ return *it2_;
+#endif
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ size_type lower_;
+ size_type upper_;
+ typedef const value_type const_value_type;
+ static const_value_type zero_;
+ };
+
+ // Specialization for temporary_traits
+ template <class M>
+ struct vector_temporary_traits< banded_adaptor<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const banded_adaptor<M> >
+ : vector_temporary_traits< M > {} ;
+
+ template <class M>
+ struct matrix_temporary_traits< banded_adaptor<M> >
+ : matrix_temporary_traits< M > {} ;
+ template <class M>
+ struct matrix_temporary_traits< const banded_adaptor<M> >
+ : matrix_temporary_traits< M > {} ;
+
+
+ template<class M>
+ typename banded_adaptor<M>::const_value_type banded_adaptor<M>::zero_ = value_type/*zero*/();
+
+ /** \brief A diagonal matrix adaptator: convert a any matrix into a diagonal matrix expression
+ *
+ * For a \f$(m\times m)\f$-dimensional matrix, the \c diagonal_adaptor will provide a diagonal matrix
+ * with \f$0 \leq i < m\f$ and \f$0 \leq j < m\f$, if \f$i\neq j\f$ then \f$b_{i,j}=0\f$.
+ *
+ * Storage and location are based on those of the underlying matrix. This is important because
+ * a \c diagonal_adaptor does not copy the matrix data to a new place. Therefore, modifying values
+ * in a \c diagonal_adaptor matrix will also modify the underlying matrix too.
+ *
+ * \tparam M the type of matrix used to generate the diagonal matrix
+ */
+
+ template<class M>
+ class diagonal_adaptor:
+ public banded_adaptor<M> {
+ public:
+ typedef M matrix_type;
+ typedef banded_adaptor<M> adaptor_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ diagonal_adaptor ():
+ adaptor_type () {}
+ BOOST_UBLAS_INLINE
+ diagonal_adaptor (matrix_type &data):
+ adaptor_type (data) {}
+ BOOST_UBLAS_INLINE
+ ~diagonal_adaptor () {}
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ diagonal_adaptor &operator = (const diagonal_adaptor &m) {
+ adaptor_type::operator = (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ diagonal_adaptor &operator = (const matrix_expression<AE> &ae) {
+ adaptor_type::operator = (ae);
+ return *this;
+ }
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_BLAS_
+#define _BOOST_UBLAS_BLAS_
+
+#include <boost/numeric/ublas/traits.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+
+ /** Interface and implementation of BLAS level 1
+ * This includes functions which perform \b vector-vector operations.
+ * More information about BLAS can be found at
+ * <a href="http://en.wikipedia.org/wiki/BLAS">http://en.wikipedia.org/wiki/BLAS</a>
+ */
+ namespace blas_1 {
+
+ /** 1-Norm: \f$\sum_i |x_i|\f$ (also called \f$\mathcal{L}_1\f$ or Manhattan norm)
+ *
+ * \param v a vector or vector expression
+ * \return the 1-Norm with type of the vector's type
+ *
+ * \tparam V type of the vector (not needed by default)
+ */
+ template<class V>
+ typename type_traits<typename V::value_type>::real_type
+ asum (const V &v) {
+ return norm_1 (v);
+ }
+
+ /** 2-Norm: \f$\sum_i |x_i|^2\f$ (also called \f$\mathcal{L}_2\f$ or Euclidean norm)
+ *
+ * \param v a vector or vector expression
+ * \return the 2-Norm with type of the vector's type
+ *
+ * \tparam V type of the vector (not needed by default)
+ */
+ template<class V>
+ typename type_traits<typename V::value_type>::real_type
+ nrm2 (const V &v) {
+ return norm_2 (v);
+ }
+
+ /** Infinite-norm: \f$\max_i |x_i|\f$ (also called \f$\mathcal{L}_\infty\f$ norm)
+ *
+ * \param v a vector or vector expression
+ * \return the Infinite-Norm with type of the vector's type
+ *
+ * \tparam V type of the vector (not needed by default)
+ */
+ template<class V>
+ typename type_traits<typename V::value_type>::real_type
+ amax (const V &v) {
+ return norm_inf (v);
+ }
+
+ /** Inner product of vectors \f$v_1\f$ and \f$v_2\f$
+ *
+ * \param v1 first vector of the inner product
+ * \param v2 second vector of the inner product
+ * \return the inner product of the type of the most generic type of the 2 vectors
+ *
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2 type of second vector (not needed by default)
+ */
+ template<class V1, class V2>
+ typename promote_traits<typename V1::value_type, typename V2::value_type>::promote_type
+ dot (const V1 &v1, const V2 &v2) {
+ return inner_prod (v1, v2);
+ }
+
+ /** Copy vector \f$v_2\f$ to \f$v_1\f$
+ *
+ * \param v1 target vector
+ * \param v2 source vector
+ * \return a reference to the target vector
+ *
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2 type of second vector (not needed by default)
+ */
+ template<class V1, class V2>
+ V1 & copy (V1 &v1, const V2 &v2)
+ {
+ return v1.assign (v2);
+ }
+
+ /** Swap vectors \f$v_1\f$ and \f$v_2\f$
+ *
+ * \param v1 first vector
+ * \param v2 second vector
+ *
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2 type of second vector (not needed by default)
+ */
+ template<class V1, class V2>
+ void swap (V1 &v1, V2 &v2)
+ {
+ v1.swap (v2);
+ }
+
+ /** scale vector \f$v\f$ with scalar \f$t\f$
+ *
+ * \param v vector to be scaled
+ * \param t the scalar
+ * \return \c t*v
+ *
+ * \tparam V type of the vector (not needed by default)
+ * \tparam T type of the scalar (not needed by default)
+ */
+ template<class V, class T>
+ V & scal (V &v, const T &t)
+ {
+ return v *= t;
+ }
+
+ /** Compute \f$v_1= v_1 + t.v_2\f$
+ *
+ * \param v1 target and first vector
+ * \param t the scalar
+ * \param v2 second vector
+ * \return a reference to the first and target vector
+ *
+ * \tparam V1 type of the first vector (not needed by default)
+ * \tparam T type of the scalar (not needed by default)
+ * \tparam V2 type of the second vector (not needed by default)
+ */
+ template<class V1, class T, class V2>
+ V1 & axpy (V1 &v1, const T &t, const V2 &v2)
+ {
+ return v1.plus_assign (t * v2);
+ }
+
+ /** Performs rotation of points in the plane and assign the result to the first vector
+ *
+ * Each point is defined as a pair \c v1(i) and \c v2(i), being respectively
+ * the \f$x\f$ and \f$y\f$ coordinates. The parameters \c t1 and \t2 are respectively
+ * the cosine and sine of the angle of the rotation.
+ * Results are not returned but directly written into \c v1.
+ *
+ * \param t1 cosine of the rotation
+ * \param v1 vector of \f$x\f$ values
+ * \param t2 sine of the rotation
+ * \param v2 vector of \f$y\f$ values
+ *
+ * \tparam T1 type of the cosine value (not needed by default)
+ * \tparam V1 type of the \f$x\f$ vector (not needed by default)
+ * \tparam T2 type of the sine value (not needed by default)
+ * \tparam V2 type of the \f$y\f$ vector (not needed by default)
+ */
+ template<class T1, class V1, class T2, class V2>
+ void rot (const T1 &t1, V1 &v1, const T2 &t2, V2 &v2)
+ {
+ typedef typename promote_traits<typename V1::value_type, typename V2::value_type>::promote_type promote_type;
+ vector<promote_type> vt (t1 * v1 + t2 * v2);
+ v2.assign (- t2 * v1 + t1 * v2);
+ v1.assign (vt);
+ }
+
+ }
+
+ /** \brief Interface and implementation of BLAS level 2
+ * This includes functions which perform \b matrix-vector operations.
+ * More information about BLAS can be found at
+ * <a href="http://en.wikipedia.org/wiki/BLAS">http://en.wikipedia.org/wiki/BLAS</a>
+ */
+ namespace blas_2 {
+
+ /** \brief multiply vector \c v with triangular matrix \c m
+ *
+ * \param v a vector
+ * \param m a triangular matrix
+ * \return the result of the product
+ *
+ * \tparam V type of the vector (not needed by default)
+ * \tparam M type of the matrix (not needed by default)
+ */
+ template<class V, class M>
+ V & tmv (V &v, const M &m)
+ {
+ return v = prod (m, v);
+ }
+
+ /** \brief solve \f$m.x = v\f$ in place, where \c m is a triangular matrix
+ *
+ * \param v a vector
+ * \param m a matrix
+ * \param C (this parameter is not needed)
+ * \return a result vector from the above operation
+ *
+ * \tparam V type of the vector (not needed by default)
+ * \tparam M type of the matrix (not needed by default)
+ * \tparam C n/a
+ */
+ template<class V, class M, class C>
+ V & tsv (V &v, const M &m, C)
+ {
+ return v = solve (m, v, C ());
+ }
+
+ /** \brief compute \f$ v_1 = t_1.v_1 + t_2.(m.v_2)\f$, a general matrix-vector product
+ *
+ * \param v1 a vector
+ * \param t1 a scalar
+ * \param t2 another scalar
+ * \param m a matrix
+ * \param v2 another vector
+ * \return the vector \c v1 with the result from the above operation
+ *
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam T1 type of first scalar (not needed by default)
+ * \tparam T2 type of second scalar (not needed by default)
+ * \tparam M type of matrix (not needed by default)
+ * \tparam V2 type of second vector (not needed by default)
+ */
+ template<class V1, class T1, class T2, class M, class V2>
+ V1 & gmv (V1 &v1, const T1 &t1, const T2 &t2, const M &m, const V2 &v2)
+ {
+ return v1 = t1 * v1 + t2 * prod (m, v2);
+ }
+
+ /** \brief Rank 1 update: \f$ m = m + t.(v_1.v_2^T)\f$
+ *
+ * \param m a matrix
+ * \param t a scalar
+ * \param v1 a vector
+ * \param v2 another vector
+ * \return a matrix with the result from the above operation
+ *
+ * \tparam M type of matrix (not needed by default)
+ * \tparam T type of scalar (not needed by default)
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2type of second vector (not needed by default)
+ */
+ template<class M, class T, class V1, class V2>
+ M & gr (M &m, const T &t, const V1 &v1, const V2 &v2)
+ {
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ return m += t * outer_prod (v1, v2);
+#else
+ return m = m + t * outer_prod (v1, v2);
+#endif
+ }
+
+ /** \brief symmetric rank 1 update: \f$m = m + t.(v.v^T)\f$
+ *
+ * \param m a matrix
+ * \param t a scalar
+ * \param v a vector
+ * \return a matrix with the result from the above operation
+ *
+ * \tparam M type of matrix (not needed by default)
+ * \tparam T type of scalar (not needed by default)
+ * \tparam V type of vector (not needed by default)
+ */
+ template<class M, class T, class V>
+ M & sr (M &m, const T &t, const V &v)
+ {
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ return m += t * outer_prod (v, v);
+#else
+ return m = m + t * outer_prod (v, v);
+#endif
+ }
+
+ /** \brief hermitian rank 1 update: \f$m = m + t.(v.v^H)\f$
+ *
+ * \param m a matrix
+ * \param t a scalar
+ * \param v a vector
+ * \return a matrix with the result from the above operation
+ *
+ * \tparam M type of matrix (not needed by default)
+ * \tparam T type of scalar (not needed by default)
+ * \tparam V type of vector (not needed by default)
+ */
+ template<class M, class T, class V>
+ M & hr (M &m, const T &t, const V &v)
+ {
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ return m += t * outer_prod (v, conj (v));
+#else
+ return m = m + t * outer_prod (v, conj (v));
+#endif
+ }
+
+ /** \brief symmetric rank 2 update: \f$ m=m+ t.(v_1.v_2^T + v_2.v_1^T)\f$
+ *
+ * \param m a matrix
+ * \param t a scalar
+ * \param v1 a vector
+ * \param v2 another vector
+ * \return a matrix with the result from the above operation
+ *
+ * \tparam M type of matrix (not needed by default)
+ * \tparam T type of scalar (not needed by default)
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2type of second vector (not needed by default)
+ */
+ template<class M, class T, class V1, class V2>
+ M & sr2 (M &m, const T &t, const V1 &v1, const V2 &v2)
+ {
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ return m += t * (outer_prod (v1, v2) + outer_prod (v2, v1));
+#else
+ return m = m + t * (outer_prod (v1, v2) + outer_prod (v2, v1));
+#endif
+ }
+
+ /** \brief hermitian rank 2 update: \f$m=m+t.(v_1.v_2^H) + v_2.(t.v_1)^H)\f$
+ *
+ * \param m a matrix
+ * \param t a scalar
+ * \param v1 a vector
+ * \param v2 another vector
+ * \return a matrix with the result from the above operation
+ *
+ * \tparam M type of matrix (not needed by default)
+ * \tparam T type of scalar (not needed by default)
+ * \tparam V1 type of first vector (not needed by default)
+ * \tparam V2type of second vector (not needed by default)
+ */
+ template<class M, class T, class V1, class V2>
+ M & hr2 (M &m, const T &t, const V1 &v1, const V2 &v2)
+ {
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ return m += t * outer_prod (v1, conj (v2)) + type_traits<T>::conj (t) * outer_prod (v2, conj (v1));
+#else
+ return m = m + t * outer_prod (v1, conj (v2)) + type_traits<T>::conj (t) * outer_prod (v2, conj (v1));
+#endif
+ }
+
+ }
+
+ /** \brief Interface and implementation of BLAS level 3
+ * This includes functions which perform \b matrix-matrix operations.
+ * More information about BLAS can be found at
+ * <a href="http://en.wikipedia.org/wiki/BLAS">http://en.wikipedia.org/wiki/BLAS</a>
+ */
+ namespace blas_3 {
+
+ /** \brief triangular matrix multiplication \f$m_1=t.m_2.m_3\f$ where \f$m_2\f$ and \f$m_3\f$ are triangular
+ *
+ * \param m1 a matrix for storing result
+ * \param t a scalar
+ * \param m2 a triangular matrix
+ * \param m3 a triangular matrix
+ * \return the matrix \c m1
+ *
+ * \tparam M1 type of the result matrix (not needed by default)
+ * \tparam T type of the scalar (not needed by default)
+ * \tparam M2 type of the first triangular matrix (not needed by default)
+ * \tparam M3 type of the second triangular matrix (not needed by default)
+ *
+ */
+ template<class M1, class T, class M2, class M3>
+ M1 & tmm (M1 &m1, const T &t, const M2 &m2, const M3 &m3)
+ {
+ return m1 = t * prod (m2, m3);
+ }
+
+ /** \brief triangular solve \f$ m_2.x = t.m_1\f$ in place, \f$m_2\f$ is a triangular matrix
+ *
+ * \param m1 a matrix
+ * \param t a scalar
+ * \param m2 a triangular matrix
+ * \param C (not used)
+ * \return the \f$m_1\f$ matrix
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T type of the scalar (not needed by default)
+ * \tparam M2 type of the triangular matrix (not needed by default)
+ * \tparam C (n/a)
+ */
+ template<class M1, class T, class M2, class C>
+ M1 & tsm (M1 &m1, const T &t, const M2 &m2, C)
+ {
+ return m1 = solve (m2, t * m1, C ());
+ }
+
+ /** \brief general matrix multiplication \f$m_1=t_1.m_1 + t_2.m_2.m_3\f$
+ *
+ * \param m1 first matrix
+ * \param t1 first scalar
+ * \param t2 second scalar
+ * \param m2 second matrix
+ * \param m3 third matrix
+ * \return the matrix \c m1
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T1 type of the first scalar (not needed by default)
+ * \tparam T2 type of the second scalar (not needed by default)
+ * \tparam M2 type of the second matrix (not needed by default)
+ * \tparam M3 type of the third matrix (not needed by default)
+ */
+ template<class M1, class T1, class T2, class M2, class M3>
+ M1 & gmm (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
+ {
+ return m1 = t1 * m1 + t2 * prod (m2, m3);
+ }
+
+ /** \brief symmetric rank \a k update: \f$m_1=t.m_1+t_2.(m_2.m_2^T)\f$
+ *
+ * \param m1 first matrix
+ * \param t1 first scalar
+ * \param t2 second scalar
+ * \param m2 second matrix
+ * \return matrix \c m1
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T1 type of the first scalar (not needed by default)
+ * \tparam T2 type of the second scalar (not needed by default)
+ * \tparam M2 type of the second matrix (not needed by default)
+ * \todo use opb_prod()
+ */
+ template<class M1, class T1, class T2, class M2>
+ M1 & srk (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2)
+ {
+ return m1 = t1 * m1 + t2 * prod (m2, trans (m2));
+ }
+
+ /** \brief hermitian rank \a k update: \f$m_1=t.m_1+t_2.(m_2.m2^H)\f$
+ *
+ * \param m1 first matrix
+ * \param t1 first scalar
+ * \param t2 second scalar
+ * \param m2 second matrix
+ * \return matrix \c m1
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T1 type of the first scalar (not needed by default)
+ * \tparam T2 type of the second scalar (not needed by default)
+ * \tparam M2 type of the second matrix (not needed by default)
+ * \todo use opb_prod()
+ */
+ template<class M1, class T1, class T2, class M2>
+ M1 & hrk (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2)
+ {
+ return m1 = t1 * m1 + t2 * prod (m2, herm (m2));
+ }
+
+ /** \brief generalized symmetric rank \a k update: \f$m_1=t_1.m_1+t_2.(m_2.m3^T)+t_2.(m_3.m2^T)\f$
+ *
+ * \param m1 first matrix
+ * \param t1 first scalar
+ * \param t2 second scalar
+ * \param m2 second matrix
+ * \param m3 third matrix
+ * \return matrix \c m1
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T1 type of the first scalar (not needed by default)
+ * \tparam T2 type of the second scalar (not needed by default)
+ * \tparam M2 type of the second matrix (not needed by default)
+ * \tparam M3 type of the third matrix (not needed by default)
+ * \todo use opb_prod()
+ */
+ template<class M1, class T1, class T2, class M2, class M3>
+ M1 & sr2k (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
+ {
+ return m1 = t1 * m1 + t2 * (prod (m2, trans (m3)) + prod (m3, trans (m2)));
+ }
+
+ /** \brief generalized hermitian rank \a k update: * \f$m_1=t_1.m_1+t_2.(m_2.m_3^H)+(m_3.(t_2.m_2)^H)\f$
+ *
+ * \param m1 first matrix
+ * \param t1 first scalar
+ * \param t2 second scalar
+ * \param m2 second matrix
+ * \param m3 third matrix
+ * \return matrix \c m1
+ *
+ * \tparam M1 type of the first matrix (not needed by default)
+ * \tparam T1 type of the first scalar (not needed by default)
+ * \tparam T2 type of the second scalar (not needed by default)
+ * \tparam M2 type of the second matrix (not needed by default)
+ * \tparam M3 type of the third matrix (not needed by default)
+ * \todo use opb_prod()
+ */
+ template<class M1, class T1, class T2, class M2, class M3>
+ M1 & hr2k (M1 &m1, const T1 &t1, const T2 &t2, const M2 &m2, const M3 &m3)
+ {
+ return m1 =
+ t1 * m1
+ + t2 * prod (m2, herm (m3))
+ + type_traits<T2>::conj (t2) * prod (m3, herm (m2));
+ }
+
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_CONCEPTS_
+#define _BOOST_UBLAS_CONCEPTS_
+
+#include <boost/concept_check.hpp>
+
+// Concept checks based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+
+ template<class I>
+ struct Indexed1DIteratorConcept {
+ typedef I iterator_type;
+
+ void constraints () {
+ iterator_type it = iterator_type ();
+ // Index
+ it.index ();
+ }
+ };
+
+ template<class I>
+ struct IndexedBidirectional1DIteratorConcept {
+ typedef I iterator_type;
+
+ void constraints () {
+ function_requires< BidirectionalIteratorConcept<iterator_type> >();
+ function_requires< Indexed1DIteratorConcept<iterator_type> >();
+ }
+ };
+
+ template<class I>
+ struct Mutable_IndexedBidirectional1DIteratorConcept {
+ typedef I iterator_type;
+
+ void constraints () {
+ function_requires< Mutable_BidirectionalIteratorConcept<iterator_type> >();
+ function_requires< Indexed1DIteratorConcept<iterator_type> >();
+ }
+ };
+
+ template<class I>
+ struct IndexedRandomAccess1DIteratorConcept {
+ typedef I iterator_type;
+
+ void constraints () {
+ function_requires< RandomAccessIteratorConcept<iterator_type> >();
+ function_requires< Indexed1DIteratorConcept<iterator_type> >();
+ }
+ };
+
+ template<class I>
+ struct Mutable_IndexedRandomAccess1DIteratorConcept {
+ typedef I iterator_type;
+
+ void constraints () {
+ function_requires< Mutable_RandomAccessIteratorConcept<iterator_type> >();
+ function_requires< Indexed1DIteratorConcept<iterator_type> >();
+ }
+ };
+
+ template<class I>
+ struct Indexed2DIteratorConcept {
+ typedef I iterator_type;
+ typedef typename I::dual_iterator_type dual_iterator_type;
+ typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
+
+ void constraints () {
+ iterator_type it = iterator_type ();
+ // Indices
+ it.index1 ();
+ it.index2 ();
+ // Iterator begin/end
+ dual_iterator_type it_begin (it.begin ());
+ dual_iterator_type it_end (it.end ());
+ // Reverse iterator begin/end
+ dual_reverse_iterator_type it_rbegin (it.rbegin ());
+ dual_reverse_iterator_type it_rend (it.rend ());
+ ignore_unused_variable_warning (it_begin);
+ ignore_unused_variable_warning (it_end);
+ ignore_unused_variable_warning (it_rbegin);
+ ignore_unused_variable_warning (it_rend);
+ }
+ };
+
+ template<class I1, class I2>
+ struct IndexedBidirectional2DIteratorConcept {
+ typedef I1 subiterator1_type;
+ typedef I2 subiterator2_type;
+
+ void constraints () {
+ function_requires< BidirectionalIteratorConcept<subiterator1_type> >();
+ function_requires< BidirectionalIteratorConcept<subiterator2_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator1_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator2_type> >();
+ }
+ };
+
+ template<class I1, class I2>
+ struct Mutable_IndexedBidirectional2DIteratorConcept {
+ typedef I1 subiterator1_type;
+ typedef I2 subiterator2_type;
+
+ void constraints () {
+ function_requires< Mutable_BidirectionalIteratorConcept<subiterator1_type> >();
+ function_requires< Mutable_BidirectionalIteratorConcept<subiterator2_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator1_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator2_type> >();
+ }
+ };
+
+ template<class I1, class I2>
+ struct IndexedRandomAccess2DIteratorConcept {
+ typedef I1 subiterator1_type;
+ typedef I2 subiterator2_type;
+
+ void constraints () {
+ function_requires< RandomAccessIteratorConcept<subiterator1_type> >();
+ function_requires< RandomAccessIteratorConcept<subiterator2_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator1_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator2_type> >();
+ }
+ };
+
+ template<class I1, class I2>
+ struct Mutable_IndexedRandomAccess2DIteratorConcept {
+ typedef I1 subiterator1_type;
+ typedef I2 subiterator2_type;
+
+ void constraints () {
+ function_requires< Mutable_RandomAccessIteratorConcept<subiterator1_type> >();
+ function_requires< Mutable_RandomAccessIteratorConcept<subiterator2_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator1_type> >();
+ function_requires< Indexed2DIteratorConcept<subiterator2_type> >();
+ }
+ };
+
+ template<class C>
+ struct StorageArrayConcept {
+ typedef C container_type;
+ typedef typename C::size_type size_type;
+ typedef typename C::value_type value_type;
+
+ void constraints () {
+ function_requires< RandomAccessContainerConcept<container_type> >();
+ size_type n (0);
+ // Sizing constructor
+ container_type c = container_type (n);
+ // Initialised sizing constructor
+ container_type (n, value_type (5));
+ ignore_unused_variable_warning (c);
+ }
+ };
+
+ template<class C>
+ struct Mutable_StorageArrayConcept {
+ typedef C container_type;
+ typedef typename C::size_type size_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::iterator iterator_type;
+
+ void constraints () {
+ function_requires< Mutable_RandomAccessContainerConcept<container_type> > ();
+ size_type n (0);
+ // Sizing constructor
+ container_type c = container_type (n);
+ // Initialised sizing constructor
+ c = container_type (n, value_type (3));
+ // Resize
+ c.resize (n, value_type (5));
+ // Resize - none preserving
+ c.resize (n);
+ }
+ };
+
+ template<class C>
+ struct StorageSparseConcept {
+ typedef C container_type;
+ typedef typename C::size_type size_type;
+
+ void constraints () {
+ function_requires< ReversibleContainerConcept<container_type> > ();
+ }
+ };
+
+ template<class C>
+ struct Mutable_StorageSparseConcept {
+ typedef C container_type;
+ typedef typename C::size_type size_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::iterator iterator_type;
+
+ void constraints () {
+ // NOTE - Not Mutable_ReversibleContainerConcept
+ function_requires< ReversibleContainerConcept<container_type> >();
+ container_type c = container_type ();
+ value_type t = value_type ();
+ iterator_type it = iterator_type (), it1 = iterator_type (), it2 = iterator_type ();
+ // Insert
+ c.insert (it, t);
+ // Erase
+ c.erase (it);
+ // Range erase
+ c.erase (it1, it2);
+ // Clear
+ c.clear ();
+ }
+ };
+
+ template<class G>
+ struct IndexSetConcept {
+ typedef G generator_type;
+ typedef typename G::size_type size_type;
+ typedef typename G::value_type value_type;
+
+ void constraints () {
+ function_requires< AssignableConcept<generator_type> >();
+ function_requires< ReversibleContainerConcept<generator_type> >();
+ generator_type g = generator_type ();
+ size_type n (0);
+ value_type t;
+ // Element access
+ t = g (n);
+ ignore_unused_variable_warning (t);
+ }
+ };
+
+ /** \brief Scalar expression concept.
+ *
+ * requirements
+ * \li \c SE::value_type is the type of the scalar expression
+ * \li \c SE must be convertable to \c SE::value_type
+ * \li the constant \c SE::complexity must exist
+ *
+ * \param SE the type of the scalar expression
+ */
+ template<class SE>
+ struct ScalarExpressionConcept {
+ typedef SE scalar_expression_type;
+ typedef typename SE::value_type value_type;
+
+ static const unsigned complexity = SE::complexity;
+
+ void constraints () {
+ scalar_expression_type *sp;
+ scalar_expression_type s = *sp;
+ value_type t;
+ // Conversion
+ t = s;
+ ignore_unused_variable_warning (t);
+ }
+ };
+
+ /** \brief Vector expression concept.
+ *
+ * requirements
+ * \li \c VE::value_type is the type of the elements
+ * \li \c VE::const_reference The return type when accessing an element of a constant vector
+ * expression. Must be convertable to a \c value_type.
+ * \li \c VE::size_type is the (unsigned) type of the indices
+ * \li \c VE::difference_type is the (signed) type of distances between indices
+ * \li \c VE::category
+ *
+ * \li the constant \c SE::complexity must exist
+ *
+ * \param SE the type of the scalar expression
+ */
+ template<class VE>
+ struct VectorExpressionConcept {
+ typedef VE vector_expression_type;
+ typedef typename VE::type_category type_category;
+ typedef typename VE::size_type size_type;
+ typedef typename VE::difference_type difference_type;
+ typedef typename VE::value_type value_type;
+ typedef typename VE::const_reference const_reference;
+ typedef typename VE::const_iterator const_iterator_type;
+ typedef typename VE::const_reverse_iterator const_reverse_iterator_type;
+
+ void constraints () {
+ vector_expression_type *vp;
+ const vector_expression_type *cvp;
+ vector_expression_type v = *vp;
+ const vector_expression_type cv = *cvp;
+ size_type n (0), i (0);
+ value_type t;
+ // Find (internal?)
+ const_iterator_type cit (v.find (i));
+ // Beginning of range
+ const_iterator_type cit_begin (v.begin ());
+ // End of range
+ const_iterator_type cit_end (v.end ());
+ // Size
+ n = v.size ();
+ // Beginning of reverse range
+ const_reverse_iterator_type crit_begin (cv.rbegin ());
+ // End of reverse range
+ const_reverse_iterator_type crit_end (cv.rend ());
+ // Element access
+ t = v (i);
+ ignore_unused_variable_warning (n);
+ ignore_unused_variable_warning (cit);
+ ignore_unused_variable_warning (cit_begin);
+ ignore_unused_variable_warning (cit_end);
+ ignore_unused_variable_warning (crit_begin);
+ ignore_unused_variable_warning (crit_end);
+ ignore_unused_variable_warning (t);
+ }
+ };
+
+ template<class VE>
+ struct Mutable_VectorExpressionConcept {
+ typedef VE vector_expression_type;
+ typedef typename VE::size_type size_type;
+ typedef typename VE::value_type value_type;
+ typedef typename VE::iterator iterator_type;
+ typedef typename VE::reverse_iterator reverse_iterator_type;
+
+ void constraints () {
+ function_requires< AssignableConcept<vector_expression_type> >();
+ function_requires< VectorExpressionConcept<vector_expression_type> >();
+ vector_expression_type *vp;
+ vector_expression_type v = *vp, v1 = *vp, v2 = *vp;
+ size_type i (0);
+ value_type t = value_type ();
+ // Find (internal?)
+ iterator_type it (v.find (i));
+ // Beginning of range
+ iterator_type it_begin (v.begin ());
+ // End of range
+ iterator_type it_end (v.end ());
+ // Swap
+ v1.swap (v2);
+ // Beginning of reverse range
+ reverse_iterator_type rit_begin (v.rbegin ());
+ // End of reverse range
+ reverse_iterator_type rit_end (v.rend ());
+ // Assignments
+ v2 = v1;
+ v2.assign (v1);
+ v2 += v1;
+ v2.plus_assign (v1);
+ v2 -= v1;
+ v2.minus_assign (v1);
+ v *= t;
+ ignore_unused_variable_warning (it);
+ ignore_unused_variable_warning (it_begin);
+ ignore_unused_variable_warning (it_end);
+ ignore_unused_variable_warning (rit_begin);
+ ignore_unused_variable_warning (rit_end);
+ }
+ };
+
+ template<class ME>
+ struct MatrixExpressionConcept {
+ typedef ME matrix_expression_type;
+ typedef typename ME::type_category type_category;
+ typedef typename ME::size_type size_type;
+ typedef typename ME::value_type value_type;
+ typedef typename ME::const_iterator1 const_subiterator1_type;
+ typedef typename ME::const_iterator2 const_subiterator2_type;
+ typedef typename ME::const_reverse_iterator1 const_reverse_subiterator1_type;
+ typedef typename ME::const_reverse_iterator2 const_reverse_subiterator2_type;
+
+ void constraints () {
+ matrix_expression_type *mp;
+ const matrix_expression_type *cmp;
+ matrix_expression_type m = *mp;
+ const matrix_expression_type cm = *cmp;
+ size_type n (0), i (0), j (0);
+ value_type t;
+ // Find (internal?)
+ const_subiterator1_type cit1 (m.find1 (0, i, j));
+ const_subiterator2_type cit2 (m.find2 (0, i, j));
+ // Beginning of range
+ const_subiterator1_type cit1_begin (m.begin1 ());
+ const_subiterator2_type cit2_begin (m.begin2 ());
+ // End of range
+ const_subiterator1_type cit1_end (m.end1 ());
+ const_subiterator2_type cit2_end (m.end2 ());
+ // Size
+ n = m.size1 ();
+ n = m.size2 ();
+ // Beginning of reverse range
+ const_reverse_subiterator1_type crit1_begin (cm.rbegin1 ());
+ const_reverse_subiterator2_type crit2_begin (cm.rbegin2 ());
+ // End of reverse range
+ const_reverse_subiterator1_type crit1_end (cm.rend1 ());
+ const_reverse_subiterator2_type crit2_end (cm.rend2 ());
+ // Element access
+ t = m (i, j);
+ ignore_unused_variable_warning (n);
+ ignore_unused_variable_warning (cit1);
+ ignore_unused_variable_warning (cit2);
+ ignore_unused_variable_warning (cit1_begin);
+ ignore_unused_variable_warning (cit2_begin);
+ ignore_unused_variable_warning (cit1_end);
+ ignore_unused_variable_warning (cit2_end);
+ ignore_unused_variable_warning (crit1_begin);
+ ignore_unused_variable_warning (crit2_begin);
+ ignore_unused_variable_warning (crit1_end);
+ ignore_unused_variable_warning (crit2_end);
+ ignore_unused_variable_warning (t);
+ }
+ };
+
+ template<class ME>
+ struct Mutable_MatrixExpressionConcept {
+ typedef ME matrix_expression_type;
+ typedef typename ME::size_type size_type;
+ typedef typename ME::value_type value_type;
+ typedef typename ME::iterator1 subiterator1_type;
+ typedef typename ME::iterator2 subiterator2_type;
+ typedef typename ME::reverse_iterator1 reverse_subiterator1_type;
+ typedef typename ME::reverse_iterator2 reverse_subiterator2_type;
+
+ void constraints () {
+ function_requires< AssignableConcept<matrix_expression_type> >();
+ function_requires< MatrixExpressionConcept<matrix_expression_type> >();
+ matrix_expression_type *mp;
+ matrix_expression_type m = *mp, m1 = *mp, m2 = *mp;
+ size_type i (0), j (0);
+ value_type t = value_type ();
+ // Find (internal?)
+ subiterator1_type it1 (m.find1 (0, i, j));
+ subiterator2_type it2 (m.find2 (0, i, j));
+ // Beginning of range
+ subiterator1_type it1_begin (m.begin1 ());
+ subiterator2_type it2_begin (m.begin2 ());
+ // End of range
+ subiterator1_type it1_end (m.end1 ());
+ subiterator2_type it2_end (m.end2 ());
+ // Swap
+ m1.swap (m2);
+ // Beginning of reverse range
+ reverse_subiterator1_type rit1_begin (m.rbegin1 ());
+ reverse_subiterator2_type rit2_begin (m.rbegin2 ());
+ // End of reverse range
+ reverse_subiterator1_type rit1_end (m.rend1 ());
+ reverse_subiterator2_type rit2_end (m.rend2 ());
+ // Assignments
+ m2 = m1;
+ m2.assign (m1);
+ m2 += m1;
+ m2.plus_assign (m1);
+ m2 -= m1;
+ m2.minus_assign (m1);
+ m *= t;
+ ignore_unused_variable_warning (it1);
+ ignore_unused_variable_warning (it2);
+ ignore_unused_variable_warning (it1_begin);
+ ignore_unused_variable_warning (it2_begin);
+ ignore_unused_variable_warning (it1_end);
+ ignore_unused_variable_warning (it2_end);
+ ignore_unused_variable_warning (rit1_begin);
+ ignore_unused_variable_warning (rit2_begin);
+ ignore_unused_variable_warning (rit1_end);
+ ignore_unused_variable_warning (rit2_end);
+ }
+ };
+
+ template<class V>
+ struct VectorConcept {
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ typedef const value_type *const_pointer;
+
+ void constraints () {
+ function_requires< VectorExpressionConcept<vector_type> >();
+ size_type n (0);
+ size_type i (0);
+ // Sizing constructor
+ vector_type v (n);
+ // Element support
+ const_pointer p = v.find_element (i);
+
+ ignore_unused_variable_warning (p);
+ }
+ };
+
+ template<class V>
+ struct Mutable_VectorConcept {
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ typedef value_type *pointer;
+
+ void constraints () {
+ function_requires< VectorConcept<vector_type> >();
+ function_requires< DefaultConstructible<vector_type> >();
+ function_requires< Mutable_VectorExpressionConcept<vector_type> >();
+ size_type n (0);
+ value_type t = value_type ();
+ size_type i (0);
+ vector_type v;
+ // Element support
+ pointer p = v.find_element (i);
+ // Element assignment
+ value_type r = v.insert_element (i, t);
+ v.insert_element (i, t) = r;
+ // Zeroing
+ v.clear ();
+ // Resize
+ v.resize (n);
+
+ ignore_unused_variable_warning (p);
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class V>
+ struct SparseVectorConcept {
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+
+ void constraints () {
+ function_requires< VectorConcept<vector_type> >();
+ }
+ };
+
+ template<class V>
+ struct Mutable_SparseVectorConcept {
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+
+ void constraints () {
+ function_requires< SparseVectorConcept<vector_type> >();
+ function_requires< Mutable_VectorConcept<vector_type> >();
+ size_type i (0);
+ vector_type v;
+ // Element erasure
+ v.erase_element (i);
+ }
+ };
+
+ template<class M>
+ struct MatrixConcept {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ typedef const value_type *const_pointer;
+
+ void constraints () {
+ function_requires< MatrixExpressionConcept<matrix_type> >();
+ size_type n (0);
+ size_type i (0), j (0);
+ // Sizing constructor
+ matrix_type m (n, n);
+ // Element support
+#ifndef SKIP_BAD
+ const_pointer p = m.find_element (i, j);
+#else
+ const_pointer p;
+ ignore_unused_variable_warning (i);
+ ignore_unused_variable_warning (j);
+#endif
+ ignore_unused_variable_warning (p);
+ }
+ };
+
+ template<class M>
+ struct Mutable_MatrixConcept {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ typedef value_type *pointer;
+
+ void constraints () {
+ function_requires< MatrixConcept<matrix_type> >();
+ function_requires< DefaultConstructible<matrix_type> >();
+ function_requires< Mutable_MatrixExpressionConcept<matrix_type> >();
+ size_type n (0);
+ value_type t = value_type ();
+ size_type i (0), j (0);
+ matrix_type m;
+ // Element support
+#ifndef SKIP_BAD
+ pointer p = m.find_element (i, j);
+ ignore_unused_variable_warning (i);
+ ignore_unused_variable_warning (j);
+#else
+ pointer p;
+#endif
+ // Element assigment
+ value_type r = m.insert_element (i, j, t);
+ m.insert_element (i, j, t) = r;
+ // Zeroing
+ m.clear ();
+ // Resize
+ m.resize (n, n);
+ m.resize (n, n, false);
+
+ ignore_unused_variable_warning (p);
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class M>
+ struct SparseMatrixConcept {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+
+ void constraints () {
+ function_requires< MatrixConcept<matrix_type> >();
+ }
+ };
+
+ template<class M>
+ struct Mutable_SparseMatrixConcept {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+ void constraints () {
+ function_requires< SparseMatrixConcept<matrix_type> >();
+ function_requires< Mutable_MatrixConcept<matrix_type> >();
+ size_type i (0), j (0);
+ matrix_type m;
+ // Elemnent erasure
+ m.erase_element (i, j);
+ }
+ };
+
+ /** introduce anonymous namespace to make following functions
+ * local to the current compilation unit.
+ */
+ namespace {
+
+ template<class T>
+ T
+ ZeroElement (T);
+ template<>
+ float
+ ZeroElement (float) {
+ return 0.f;
+ }
+ template<>
+ double
+ ZeroElement (double) {
+ return 0.;
+ }
+ template<>
+ vector<float>
+ ZeroElement (vector<float>) {
+ return zero_vector<float> ();
+ }
+ template<>
+ vector<double>
+ ZeroElement (vector<double>) {
+ return zero_vector<double> ();
+ }
+ template<>
+ matrix<float>
+ ZeroElement (matrix<float>) {
+ return zero_matrix<float> ();
+ }
+ template<>
+ matrix<double>
+ ZeroElement (matrix<double>) {
+ return zero_matrix<double> ();
+ }
+ template<>
+ std::complex<float>
+ ZeroElement (std::complex<float>) {
+ return std::complex<float> (0.f);
+ }
+ template<>
+ std::complex<double>
+ ZeroElement (std::complex<double>) {
+ return std::complex<double> (0.);
+ }
+ template<>
+ vector<std::complex<float> >
+ ZeroElement (vector<std::complex<float> >) {
+ return zero_vector<std::complex<float> > ();
+ }
+ template<>
+ vector<std::complex<double> >
+ ZeroElement (vector<std::complex<double> >) {
+ return zero_vector<std::complex<double> > ();
+ }
+ template<>
+ matrix<std::complex<float> >
+ ZeroElement (matrix<std::complex<float> >) {
+ return zero_matrix<std::complex<float> > ();
+ }
+ template<>
+ matrix<std::complex<double> >
+ ZeroElement (matrix<std::complex<double> >) {
+ return zero_matrix<std::complex<double> > ();
+ }
+
+ template<class T>
+ T
+ OneElement (T);
+ template<>
+ float
+ OneElement (float) {
+ return 1.f;
+ }
+ template<>
+ double
+ OneElement (double) {
+ return 1.;
+ }
+ template<>
+ matrix<float>
+ OneElement (matrix<float>) {
+ return identity_matrix<float> ();
+ }
+ template<>
+ matrix<double>
+ OneElement (matrix<double>) {
+ return identity_matrix<double> ();
+ }
+ template<>
+ std::complex<float>
+ OneElement (std::complex<float>) {
+ return std::complex<float> (1.f);
+ }
+ template<>
+ std::complex<double>
+ OneElement (std::complex<double>) {
+ return std::complex<double> (1.);
+ }
+ template<>
+ matrix<std::complex<float> >
+ OneElement (matrix<std::complex<float> >) {
+ return identity_matrix<std::complex<float> > ();
+ }
+ template<>
+ matrix<std::complex<double> >
+ OneElement (matrix<std::complex<double> >) {
+ return identity_matrix<std::complex<double> > ();
+ }
+
+ template<class E1, class E2>
+ bool
+ operator == (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
+ typedef typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type value_type;
+ typedef typename type_traits<value_type>::real_type real_type;
+ return norm_inf (e1 - e2) == real_type/*zero*/();
+ }
+ template<class E1, class E2>
+ bool
+ operator == (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2) {
+ typedef typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type value_type;
+ typedef typename type_traits<value_type>::real_type real_type;
+ return norm_inf (e1 - e2) == real_type/*zero*/();
+ }
+
+ template<class T>
+ struct AdditiveAbelianGroupConcept {
+ typedef T value_type;
+
+ void constraints () {
+ bool r;
+ value_type a = value_type (), b = value_type (), c = value_type ();
+ r = (a + b) + c == a + (b + c);
+ r = ZeroElement (value_type ()) + a == a;
+ r = a + ZeroElement (value_type ()) == a;
+ r = a + (- a) == ZeroElement (value_type ());
+ r = (- a) + a == ZeroElement (value_type ());
+ r = a + b == b + a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T>
+ struct MultiplicativeAbelianGroupConcept {
+ typedef T value_type;
+
+ void constraints () {
+ bool r;
+ value_type a = value_type (), b = value_type (), c = value_type ();
+ r = (a * b) * c == a * (b * c);
+ r = OneElement (value_type ()) * a == a;
+ r = a * OneElement (value_type ()) == a;
+ r = a * (OneElement (value_type ()) / a) == a;
+ r = (OneElement (value_type ()) / a) * a == a;
+ r = a * b == b * a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T>
+ struct RingWithIdentityConcept {
+ typedef T value_type;
+
+ void constraints () {
+ function_requires< AdditiveAbelianGroupConcept<value_type> >();
+ bool r;
+ value_type a = value_type (), b = value_type (), c = value_type ();
+ r = (a * b) * c == a * (b * c);
+ r = (a + b) * c == a * c + b * c;
+ r = OneElement (value_type ()) * a == a;
+ r = a * OneElement (value_type ()) == a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T>
+ struct Prod_RingWithIdentityConcept {
+ typedef T value_type;
+
+ void constraints () {
+ function_requires< AdditiveAbelianGroupConcept<value_type> >();
+ bool r;
+ value_type a = value_type (), b = value_type (), c = value_type ();
+ r = prod (T (prod (a, b)), c) == prod (a, T (prod (b, c)));
+ r = prod (a + b, c) == prod (a, c) + prod (b, c);
+ r = prod (OneElement (value_type ()), a) == a;
+ r = prod (a, OneElement (value_type ())) == a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T>
+ struct CommutativeRingWithIdentityConcept {
+ typedef T value_type;
+
+ void constraints () {
+ function_requires< RingWithIdentityConcept<value_type> >();
+ bool r;
+ value_type a = value_type (), b = value_type ();
+ r = a * b == b * a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T>
+ struct FieldConcept {
+ typedef T value_type;
+
+ void constraints () {
+ function_requires< CommutativeRingWithIdentityConcept<value_type> >();
+ bool r;
+ value_type a = value_type ();
+ r = a == ZeroElement (value_type ()) || a * (OneElement (value_type ()) / a) == a;
+ r = a == ZeroElement (value_type ()) || (OneElement (value_type ()) / a) * a == a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T, class V>
+ struct VectorSpaceConcept {
+ typedef T value_type;
+ typedef V vector_type;
+
+ void constraints () {
+ function_requires< FieldConcept<value_type> >();
+ function_requires< AdditiveAbelianGroupConcept<vector_type> >();
+ bool r;
+ value_type alpha = value_type (), beta = value_type ();
+ vector_type a = vector_type (), b = vector_type ();
+ r = alpha * (a + b) == alpha * a + alpha * b;
+ r = (alpha + beta) * a == alpha * a + beta * a;
+ r = (alpha * beta) * a == alpha * (beta * a);
+ r = OneElement (value_type ()) * a == a;
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ template<class T, class V, class M>
+ struct LinearOperatorConcept {
+ typedef T value_type;
+ typedef V vector_type;
+ typedef M matrix_type;
+
+ void constraints () {
+ function_requires< VectorSpaceConcept<value_type, vector_type> >();
+ bool r;
+ value_type alpha = value_type (), beta = value_type ();
+ vector_type a = vector_type (), b = vector_type ();
+ matrix_type A = matrix_type ();
+ r = prod (A, alpha * a + beta * b) == alpha * prod (A, a) + beta * prod (A, b);
+ ignore_unused_variable_warning (r);
+ }
+ };
+
+ void concept_checks () {
+
+ // Allow tests to be group to keep down compiler storage requirement
+#ifdef INTERAL
+#define INTERNAL_STORAGE
+#define INTERNAL_VECTOR
+#define INTERNAL_MATRIX
+#define INTERNAL_SPECIAL
+#define INTERNAL_SPARSE
+#define INTERNAL_EXPRESSION
+#endif
+
+ // TODO enable this for development
+ // #define VIEW_CONCEPTS
+
+ // Element value type for tests
+ typedef float T;
+
+ // Storage Array
+#if defined (INTERNAL_STORAGE) || defined (INTERNAL_STORAGE_DENSE)
+ {
+ typedef std::vector<T> container_model;
+ function_requires< Mutable_StorageArrayConcept<container_model> >();
+ function_requires< RandomAccessIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_RandomAccessIteratorConcept<container_model::iterator> >();
+ }
+
+ {
+ typedef bounded_array<T, 1> container_model;
+ function_requires< Mutable_StorageArrayConcept<container_model> >();
+ function_requires< RandomAccessIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_RandomAccessIteratorConcept<container_model::iterator> >();
+ }
+
+ {
+ typedef unbounded_array<T> container_model;
+ function_requires< Mutable_StorageArrayConcept<container_model> >();
+ function_requires< RandomAccessIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_RandomAccessIteratorConcept<container_model::iterator> >();
+ }
+
+/* FIXME array_adaptors are in progress
+ {
+ typedef array_adaptor<T> container_model;
+ function_requires< Mutable_StorageArrayConcept<container_model> >();
+ function_requires< RandomAccessIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_RandomAccessIteratorConcept<container_model::iterator> >();
+ }
+*/
+
+ {
+ typedef range container_model;
+ function_requires< IndexSetConcept<range> >();
+ function_requires< RandomAccessIteratorConcept<range::const_iterator> >();
+ }
+
+ {
+ typedef slice container_model;
+ function_requires< IndexSetConcept<range> >();
+ function_requires< RandomAccessIteratorConcept<range::const_iterator> >();
+ }
+
+ {
+ typedef indirect_array<> container_model;
+ function_requires< IndexSetConcept<range> >();
+ function_requires< RandomAccessIteratorConcept<range::const_iterator> >();
+ }
+#endif
+
+ // Storage Sparse
+#if defined (INTERNAL_STORAGE) || defined (INTERNAL_STORAGE_SPARSE)
+ {
+ typedef map_array<std::size_t, T> container_model;
+ function_requires< Mutable_StorageSparseConcept<container_model> >();
+ function_requires< RandomAccessIteratorConcept<container_model::const_iterator> >();
+ function_requires< RandomAccessIteratorConcept<container_model::iterator> >();
+ }
+
+ {
+ typedef std::map<std::size_t, T> container_model;
+ function_requires< Mutable_StorageSparseConcept<container_model > >();
+ function_requires< BidirectionalIteratorConcept<container_model::const_iterator> >();
+ function_requires< BidirectionalIteratorConcept<container_model::iterator> >();
+ }
+#endif
+
+#ifdef VIEW_CONCEPTS
+ // read only vectors
+ {
+ typedef vector_view<T> container_model;
+ function_requires< RandomAccessContainerConcept<container_model> >();
+ function_requires< VectorConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ }
+#endif
+
+ // Vector
+#if defined (INTERNAL_VECTOR) || defined (INTERNAL_VECTOR_DENSE)
+ {
+ typedef vector<T> container_model;
+ function_requires< RandomAccessContainerConcept<container_model> >();
+ function_requires< Mutable_VectorConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef zero_vector<T> container_model;
+ function_requires< VectorConcept<container_model> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef unit_vector<T> container_model;
+ function_requires< VectorConcept<container_model> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef scalar_vector<T> container_model;
+ function_requires< VectorConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef c_vector<T, 1> container_model;
+ function_requires< Mutable_VectorConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+#endif
+
+ // Vector Proxies
+#if defined (INTERNAL_VECTOR) || defined (INTERNAL_VECTOR_PROXY)
+ {
+ typedef vector_range<vector<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef vector_slice<vector<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef vector_indirect<vector<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+#endif
+
+ // Sparse Vector
+#if defined (INTERNAL_SPARSE) || defined (INTERNAL_VECTOR_SPARSE)
+ {
+ typedef mapped_vector<T> container_model;
+ function_requires< Mutable_SparseVectorConcept<container_model> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef compressed_vector<T> container_model;
+ function_requires< Mutable_SparseVectorConcept<container_model> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef coordinate_vector<T> container_model;
+ function_requires< Mutable_SparseVectorConcept<container_model> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedBidirectional1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedBidirectional1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+#endif
+
+ // Matrix
+#if defined (INTERNAL_MATRIX) || defined (INTERNAL_MATRIX_DENSE)
+ {
+ typedef matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef vector_of_vector<T> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef zero_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef identity_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef scalar_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef c_matrix<T, 1, 1> container_model;
+ function_requires< Mutable_MatrixConcept<matrix<T> > >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Matrix Proxies
+#if defined (INTERNAL_MATRIX) || defined (INTERNAL_MATRIX_PROXY)
+ {
+ typedef matrix_row<matrix<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_column<matrix<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_vector_range<matrix<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_vector_slice<matrix<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_vector_indirect<matrix<T> > container_model;
+ function_requires< Mutable_VectorExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<container_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<container_model::reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_range<matrix<T> > container_model;
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_slice<matrix<T> > container_model;
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_indirect<matrix<T> > container_model;
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Banded Matrix
+#if defined (INTERNAL_SPECIAL) || defined (INTERNAL_BANDED)
+ {
+ typedef banded_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef banded_adaptor<matrix<T> > container_model;
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Triangular Matrix
+#if defined (INTERNAL_SPECIAL) || defined (INTERNAL_TRIANGULAR)
+ {
+ typedef triangular_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef triangular_adaptor<matrix<T> > container_model;
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Symmetric Matrix
+#if defined (INTERNA_SPECIAL) || defined (INTERNAL_SYMMETRIC)
+ {
+ typedef symmetric_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef banded_adaptor<matrix<T> > container_model;
+#ifndef SKIP_BAD
+ // const_iterator (iterator) constructor is bad
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+#endif
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Hermitian Matrix
+#if defined (INTERNAL_SPECIAL) || defined (INTERNAL_HERMITIAN)
+ {
+ typedef hermitian_matrix<T> container_model;
+ function_requires< Mutable_MatrixConcept<container_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef hermitian_adaptor<matrix<T> > container_model;
+#ifndef SKIP_BAD
+ // const_iterator (iterator) constructor is bad
+ function_requires< Mutable_MatrixExpressionConcept<container_model> >();
+#endif
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+#endif
+
+ // Sparse Matrix
+#if defined (INTERNAL_SPARSE) || defined (INTERNAL_MATRIX_SPARSE)
+ {
+ typedef mapped_matrix<T> container_model;
+ function_requires< Mutable_SparseMatrixConcept<container_model> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+ {
+ typedef mapped_vector_of_mapped_vector<T> container_model;
+ function_requires< Mutable_SparseMatrixConcept<container_model> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+ {
+ typedef compressed_matrix<T> container_model;
+ function_requires< Mutable_SparseMatrixConcept<container_model> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+ {
+ typedef coordinate_matrix<T> container_model;
+ function_requires< Mutable_SparseMatrixConcept<container_model> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+ {
+ typedef generalized_vector_of_vector<T, row_major, vector< coordinate_vector<T> > > container_model;
+ function_requires< Mutable_SparseMatrixConcept<container_model> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_iterator1, container_model::const_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::iterator1, container_model::iterator2> >();
+ function_requires< IndexedBidirectional2DIteratorConcept<container_model::const_reverse_iterator1, container_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedBidirectional2DIteratorConcept<container_model::reverse_iterator1, container_model::reverse_iterator2> >();
+ }
+
+#endif
+
+ // Scalar Expressions
+#if defined (INTERNAL_EXPRESSION) || defined (INTERNAL_VECTOR_EXPRESSION)
+ function_requires< ScalarExpressionConcept<scalar_value<T> > >();
+ function_requires< ScalarExpressionConcept<scalar_reference<T> > >();
+
+ // Vector Expressions
+ {
+ typedef vector_reference<vector<T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< Mutable_VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<expression_model::iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ function_requires< Mutable_IndexedRandomAccess1DIteratorConcept<expression_model::reverse_iterator> >();
+ }
+
+ {
+ typedef vector_unary<vector<T>, scalar_identity<T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef vector_binary<vector<T>, vector<T>, scalar_plus<T, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef vector_binary_scalar1<T, vector<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef vector_binary_scalar2<vector<T>, scalar_value<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef vector_binary_scalar1<scalar_value<T>, vector<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef vector_binary_scalar2<vector<T>, scalar_value<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ function_requires< ScalarExpressionConcept<vector_scalar_unary<vector<T>, vector_sum<vector<T> > > > >();
+ function_requires< ScalarExpressionConcept<vector_scalar_unary<vector<T>, vector_norm_1<vector<T> > > > >();
+ function_requires< ScalarExpressionConcept<vector_scalar_unary<vector<T>, vector_norm_2<vector<T> > > > >();
+ function_requires< ScalarExpressionConcept<vector_scalar_unary<vector<T>, vector_norm_inf<vector<T> > > > >();
+
+ function_requires< ScalarExpressionConcept<vector_scalar_binary<vector<T>, vector<T>, vector_inner_prod<vector<T>, vector<T>, T> > > >();
+#endif
+
+ // Matrix Expressions
+#if defined (INTERNAL_EXPRESSION) || defined (INTERNAL_MATRIX_EXPRESSION)
+ {
+ typedef matrix_reference<matrix<T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< Mutable_MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<expression_model::iterator1, expression_model::iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ function_requires< Mutable_IndexedRandomAccess2DIteratorConcept<expression_model::reverse_iterator1, expression_model::reverse_iterator2> >();
+ }
+
+ {
+ typedef vector_matrix_binary<vector<T>, vector<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_unary1<matrix<T>, scalar_identity<T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_unary2<matrix<T>, scalar_identity<T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_binary<matrix<T>, matrix<T>, scalar_plus<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_binary_scalar1<T, matrix<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_binary_scalar2<matrix<T>, T, scalar_multiplies<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_binary_scalar1<scalar_value<T>, matrix<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_binary_scalar2<matrix<T>, scalar_value<T>, scalar_multiplies<T, T> > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ {
+ typedef matrix_vector_binary1<matrix<T>, vector<T>, matrix_vector_prod1<matrix<T>, vector<T>, T> > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_vector_binary2<vector<T>, matrix<T>, matrix_vector_prod2<matrix<T>, vector<T>, T > > expression_model;
+ function_requires< VectorExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_iterator> >();
+ function_requires< IndexedRandomAccess1DIteratorConcept<expression_model::const_reverse_iterator> >();
+ }
+
+ {
+ typedef matrix_matrix_binary<matrix<T>, matrix<T>, matrix_matrix_prod<matrix<T>, matrix<T>, T > > expression_model;
+ function_requires< MatrixExpressionConcept<expression_model> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_iterator1, expression_model::const_iterator2> >();
+ function_requires< IndexedRandomAccess2DIteratorConcept<expression_model::const_reverse_iterator1, expression_model::const_reverse_iterator2> >();
+ }
+
+ function_requires< ScalarExpressionConcept<matrix_scalar_unary<matrix<T>, matrix_norm_1<vector<T> > > > >();
+ function_requires< ScalarExpressionConcept<matrix_scalar_unary<matrix<T>, matrix_norm_frobenius<vector<T> > > > >();
+ function_requires< ScalarExpressionConcept<matrix_scalar_unary<matrix<T>, matrix_norm_inf<vector<T> > > > >();
+#endif
+
+#ifdef EXTERNAL
+ function_requires< AdditiveAbelianGroupConcept<float> >();
+ function_requires< CommutativeRingWithIdentityConcept<float> >();
+ function_requires< FieldConcept<float> >();
+ function_requires< VectorSpaceConcept<float, vector<float> > >();
+ function_requires< Prod_RingWithIdentityConcept<matrix<float> > >();
+ function_requires< VectorSpaceConcept<float, matrix<float> > >();
+ function_requires< LinearOperatorConcept<float, vector<float>, matrix<float> > >();
+
+ function_requires< AdditiveAbelianGroupConcept<std::complex<float> > >();
+ function_requires< CommutativeRingWithIdentityConcept<std::complex<float> > >();
+ function_requires< FieldConcept<std::complex<float> > >();
+ function_requires< VectorSpaceConcept<std::complex<float>, vector<std::complex<float> > > >();
+ function_requires< Prod_RingWithIdentityConcept<matrix<std::complex<float> > > >();
+ function_requires< VectorSpaceConcept<std::complex<float>, matrix<std::complex<float> > > >();
+ function_requires< LinearOperatorConcept<std::complex<float>, vector<std::complex<float> >, matrix<std::complex<float> > > >();
+#endif
+ }
+
+ } // end of anonymous namespace
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_CONFIG_
+#define _BOOST_UBLAS_CONFIG_
+
+#include <cassert>
+#include <cstddef>
+#include <algorithm>
+#include <limits>
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+
+// Microsoft Visual C++
+#if defined (BOOST_MSVC) && ! defined (BOOST_STRICT_CONFIG)
+
+// Version 6.0 and 7.0
+#if BOOST_MSVC <= 1300
+#define BOOST_UBLAS_UNSUPPORTED_COMPILER 1
+#endif
+
+// Version 7.1
+#if BOOST_MSVC == 1310
+// One of these workarounds is needed for MSVC 7.1 AFAIK
+// (thanks to John Maddock and Martin Lauer).
+#if !(defined(BOOST_UBLAS_NO_NESTED_CLASS_RELATION) || defined(BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION))
+#define BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+#endif
+
+#endif
+
+#endif
+
+
+// GNU Compiler Collection
+#if defined (__GNUC__) && ! defined (BOOST_STRICT_CONFIG)
+
+#if __GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)
+// Specified by ABI definition see GCC bug id 9982
+#define BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
+#endif
+
+#if __GNUC__ < 3
+#define BOOST_UBLAS_UNSUPPORTED_COMPILER 1
+#endif
+
+#endif
+
+
+// Intel Compiler
+#if defined (BOOST_INTEL) && ! defined (BOOST_STRICT_CONFIG)
+
+#if defined (BOOST_INTEL_LINUX) && (BOOST_INTEL_LINUX >= 800)
+// By inspection of compiler results
+#define BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
+#endif
+
+#if (BOOST_INTEL < 700)
+#define BOOST_UBLAS_UNSUPPORTED_COMPILER 1
+#endif
+
+// Define swap for index_pair and triple.
+#if (BOOST_INTEL <= 800)
+namespace boost { namespace numeric { namespace ublas {
+ template<class C, class IC>
+ class indexed_iterator;
+
+ template<class V>
+ class index_pair;
+ template<class M>
+ class index_triple;
+}}}
+
+namespace std {
+ template<class V>
+ inline
+ void swap (boost::numeric::ublas::index_pair<V> i1, boost::numeric::ublas::index_pair<V> i2) {
+ i1.swap (i2);
+ }
+ template<class M>
+ inline
+ void swap (boost::numeric::ublas::index_triple<M> i1, boost::numeric::ublas::index_triple<M> i2) {
+ i1.swap (i2);
+ }
+ // iter_swap also needed for ICC on Itanium?
+ template<class C, class IC>
+ inline
+ void iter_swap (boost::numeric::ublas::indexed_iterator<C, IC> it1,
+ boost::numeric::ublas::indexed_iterator<C, IC> it2) {
+ swap (*it1, *it2);
+ }
+}
+#endif
+
+#endif
+
+
+// Comeau compiler - thanks to Kresimir Fresl
+#if defined (__COMO__) && ! defined (BOOST_STRICT_CONFIG)
+
+// Missing std::abs overloads for float types in <cmath> are in <cstdlib>
+#if defined(__LIBCOMO__) && (__LIBCOMO_VERSION__ <= 31)
+#include <cstdlib>
+#endif
+
+#endif
+
+
+// HP aCC C++ compiler
+#if defined (__HP_aCC) && ! defined (BOOST_STRICT_CONFIG)
+# if (__HP_aCC >= 60000 )
+# define BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
+#endif
+#endif
+
+
+// SGI MIPSpro C++ compiler
+#if defined (__sgi) && ! defined (BOOST_STRICT_CONFIG)
+
+// Missing std::abs overloads for float types in <cmath> are in <cstdlib>
+// This test should be library version specific.
+#include <cstdlib>
+
+#if __COMPILER_VERSION >=650
+// By inspection of compiler results - thanks to Peter Schmitteckert
+#define BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
+#endif
+
+#endif
+
+
+// Metrowerks Codewarrior
+#if defined (__MWERKS__) && ! defined (BOOST_STRICT_CONFIG)
+
+// 8.x
+#if __MWERKS__ <= 0x3003
+#define BOOST_UBLAS_UNSUPPORTED_COMPILER 1
+#endif
+
+#endif
+
+
+// Detect other compilers with serious defects - override by defineing BOOST_UBLAS_UNSUPPORTED_COMPILER=0
+#ifndef BOOST_UBLAS_UNSUPPORTED_COMPILER
+#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_SFINAE) || defined(BOOST_NO_STDC_NAMESPACE)
+#define BOOST_UBLAS_UNSUPPORTED_COMPILER 1
+#endif
+#endif
+
+// Cannot continue with an unsupported compiler
+#if defined(BOOST_UBLAS_UNSUPPORTED_COMPILER) && (BOOST_UBLAS_UNSUPPORTED_COMPILER != 0)
+#error Your compiler and/or configuration is unsupported by this verions of uBLAS. Define BOOST_UBLAS_UNSUPPORTED_COMPILER=0 to override this message. Boost 1.32.0 includes uBLAS with support for many older compilers.
+#endif
+
+
+
+// Enable performance options in RELEASE mode
+#if defined (NDEBUG) || defined (BOOST_UBLAS_NDEBUG)
+
+#ifndef BOOST_UBLAS_INLINE
+#define BOOST_UBLAS_INLINE inline
+#endif
+
+// Do not check sizes!
+#define BOOST_UBLAS_USE_FAST_SAME
+
+// NO runtime error checks with BOOST_UBLAS_CHECK macro
+#ifndef BOOST_UBLAS_CHECK_ENABLE
+#define BOOST_UBLAS_CHECK_ENABLE 0
+#endif
+
+// NO type compatibility numeric checks
+#ifndef BOOST_UBLAS_TYPE_CHECK
+#define BOOST_UBLAS_TYPE_CHECK 0
+#endif
+
+
+// Disable performance options in DEBUG mode
+#else
+
+#ifndef BOOST_UBLAS_INLINE
+#define BOOST_UBLAS_INLINE
+#endif
+
+// Enable runtime error checks with BOOST_UBLAS_CHECK macro. Check bounds etc
+#ifndef BOOST_UBLAS_CHECK_ENABLE
+#define BOOST_UBLAS_CHECK_ENABLE 1
+#endif
+
+// Type compatibiltity numeric checks
+#ifndef BOOST_UBLAS_TYPE_CHECK
+#define BOOST_UBLAS_TYPE_CHECK 1
+#endif
+
+#endif
+
+
+/*
+ * Type compatibility checks
+ * Control type compatibility numeric runtime checks for non dense matrices.
+ * Require additional storage and complexity
+ */
+#if BOOST_UBLAS_TYPE_CHECK
+template <class Dummy>
+struct disable_type_check
+{
+ static bool value;
+};
+template <class Dummy>
+bool disable_type_check<Dummy>::value = false;
+#endif
+#ifndef BOOST_UBLAS_TYPE_CHECK_EPSILON
+#define BOOST_UBLAS_TYPE_CHECK_EPSILON (type_traits<real_type>::type_sqrt (std::numeric_limits<real_type>::epsilon ()))
+#endif
+#ifndef BOOST_UBLAS_TYPE_CHECK_MIN
+#define BOOST_UBLAS_TYPE_CHECK_MIN (type_traits<real_type>::type_sqrt ( (std::numeric_limits<real_type>::min) ()))
+#endif
+
+
+/*
+ * General Configuration
+ */
+
+// Proxy shortcuts overload the alreadly heavily over used operator ()
+//#define BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+
+// In order to simplify debugging is is possible to simplify expression template
+// so they are restricted to a single operation
+// #define BOOST_UBLAS_SIMPLE_ET_DEBUG
+
+// Use invariant hoisting.
+// #define BOOST_UBLAS_USE_INVARIANT_HOISTING
+
+// Use Duff's device in element access loops
+// #define BOOST_UBLAS_USE_DUFF_DEVICE
+
+// Choose evaluation method for dense vectors and matrices
+#if !(defined(BOOST_UBLAS_USE_INDEXING) || defined(BOOST_UBLAS_USE_ITERATING))
+#define BOOST_UBLAS_USE_INDEXING
+#endif
+// #define BOOST_UBLAS_ITERATOR_THRESHOLD 0
+
+// Use indexed iterators - unsupported implementation experiment
+// #define BOOST_UBLAS_USE_INDEXED_ITERATOR
+
+// Alignment of bounded_array type
+#ifndef BOOST_UBLAS_BOUNDED_ARRAY_ALIGN
+#define BOOST_UBLAS_BOUNDED_ARRAY_ALIGN
+#endif
+
+// Enable different sparse element proxies
+#ifndef BOOST_UBLAS_NO_ELEMENT_PROXIES
+// Sparse proxies prevent reference invalidation problems in expressions such as:
+// a [1] = a [0] = 1 Thanks to Marc Duflot for spotting this.
+// #define BOOST_UBLAS_STRICT_MAP_ARRAY
+#define BOOST_UBLAS_STRICT_VECTOR_SPARSE
+#define BOOST_UBLAS_STRICT_MATRIX_SPARSE
+// Hermitian matrices use element proxies to allow assignment to conjugate triangle
+#define BOOST_UBLAS_STRICT_HERMITIAN
+#endif
+
+// Define to configure special settings for reference returning members
+// #define BOOST_UBLAS_REFERENCE_CONST_MEMBER
+// #define BOOST_UBLAS_PROXY_CONST_MEMBER
+
+
+// Include type declerations and functions
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/detail/definitions.hpp>
+
+
+#endif
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// Copyright (c) 2000-2004
+// 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.
+//
+
+// this file should not contain any code, but the documentation
+// global to all files
+
+/** \namespace boost::numeric::ublas
+ \brief contains all important classes and functions of uBLAS
+
+ all ublas definitions ...
+ \todo expand this section
+ */
+
+/** \defgroup blas1 Level 1 BLAS
+ \brief level 1 basic linear algebra subroutines
+*/
+
+/** \defgroup blas2 Level 2 BLAS
+ \brief level 2 basic linear algebra subroutines
+*/
+
+/** \defgroup blas3 Level 3 BLAS
+ \brief level 3 basic linear algebra subroutines
+*/
--- /dev/null
+//
+// 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_DUFF_
+#define _BOOST_UBLAS_DUFF_
+
+#define DD_SWITCH(n, d, r, expr) \
+ { \
+ unsigned r = ((n) + (d) - 1) / (d); \
+ switch ((n) % (d)) { \
+ case 0: do { expr;
+#define DD_CASE_I(i, expr) \
+ case (i): expr;
+#define DD_WHILE(r) \
+ } while (-- (r) > 0); \
+ } \
+ }
+
+#define DD_1T(n, d, r, expr) \
+ DD_WHILE(r)
+#define DD_2T(n, d, r, expr) \
+ DD_CASE_I(1, expr) \
+ DD_1T(n, d, r, expr)
+#define DD_3T(n, d, r, expr) \
+ DD_CASE_I(2, expr) \
+ DD_2T(n, d, r, expr)
+#define DD_4T(n, d, r, expr) \
+ DD_CASE_I(3, expr) \
+ DD_3T(n, d, r, expr)
+#define DD_5T(n, d, r, expr) \
+ DD_CASE_I(4, expr) \
+ DD_4T(n, d, r, expr)
+#define DD_6T(n, d, r, expr) \
+ DD_CASE_I(5, expr) \
+ DD_5T(n, d, r, expr)
+#define DD_7T(n, d, r, expr) \
+ DD_CASE_I(6, expr) \
+ DD_6T(n, d, r, expr)
+#define DD_8T(n, d, r, expr) \
+ DD_CASE_I(7, expr) \
+ DD_7T(n, d, r, expr)
+
+#define DD(n, d, r, expr) \
+ DD_SWITCH(n, d, r, expr) \
+ DD_##d##T(n, d, r, expr)
+
+#endif
--- /dev/null
+//
+// 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_ITERATOR_
+#define _BOOST_UBLAS_ITERATOR_
+
+#include <boost/numeric/ublas/exception.hpp>
+#include <iterator>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief Base class of all proxy classes that contain
+ * a (redirectable) reference to an immutable object.
+ *
+ * \param C the type of the container referred to
+ */
+ template<class C>
+ class container_const_reference:
+ private nonassignable {
+ public:
+ typedef C container_type;
+
+ BOOST_UBLAS_INLINE
+ container_const_reference ():
+ c_ (0) {}
+ BOOST_UBLAS_INLINE
+ container_const_reference (const container_type &c):
+ c_ (&c) {}
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return *c_;
+ }
+
+ BOOST_UBLAS_INLINE
+ container_const_reference &assign (const container_type *c) {
+ c_ = c;
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const container_const_reference &cr) const {
+ return c_ == cr.c_;
+ }
+
+ private:
+ const container_type *c_;
+ };
+
+ /** \brief Base class of all proxy classes that contain
+ * a (redirectable) reference to a mutable object.
+ *
+ * \param C the type of the container referred to
+ */
+ template<class C>
+ class container_reference:
+ private nonassignable {
+ public:
+ typedef C container_type;
+
+ BOOST_UBLAS_INLINE
+ container_reference ():
+ c_ (0) {}
+ BOOST_UBLAS_INLINE
+ container_reference (container_type &c):
+ c_ (&c) {}
+
+ BOOST_UBLAS_INLINE
+ container_type &operator () () const {
+ return *c_;
+ }
+
+ BOOST_UBLAS_INLINE
+ container_reference &assign (container_type *c) {
+ c_ = c;
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const container_reference &cr) const {
+ return c_ == cr.c_;
+ }
+
+ private:
+ container_type *c_;
+ };
+
+ /** \brief Base class of all forward iterators.
+ *
+ * \param IC the iterator category
+ * \param I the derived iterator type
+ * \param T the value type
+ *
+ * The forward iterator can only proceed in one direction
+ * via the post increment operator.
+ */
+ template<class IC, class I, class T>
+ struct forward_iterator_base:
+ public std::iterator<IC, T> {
+ typedef I derived_iterator_type;
+ typedef T derived_value_type;
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator ++ (int) {
+ derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator != (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return ! (*d == it);
+ }
+ };
+
+ /** \brief Base class of all bidirectional iterators.
+ *
+ * \param IC the iterator category
+ * \param I the derived iterator type
+ * \param T the value type
+ *
+ * The bidirectional iterator can proceed in both directions
+ * via the post increment and post decrement operator.
+ */
+ template<class IC, class I, class T>
+ struct bidirectional_iterator_base:
+ public std::iterator<IC, T> {
+ typedef I derived_iterator_type;
+ typedef T derived_value_type;
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator ++ (int) {
+ derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator -- (int) {
+ derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
+ derived_iterator_type tmp (d);
+ -- d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator -- (derived_iterator_type &d, int) {
+ derived_iterator_type tmp (d);
+ -- d;
+ return tmp;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator != (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return ! (*d == it);
+ }
+ };
+
+ /** \brief Base class of all random access iterators.
+ *
+ * \param IC the iterator category
+ * \param I the derived iterator type
+ * \param T the value type
+ * \param D the difference type, default: std::ptrdiff_t
+ *
+ * The random access iterator can proceed in both directions
+ * via the post increment/decrement operator or in larger steps
+ * via the +, - and +=, -= operators. The random access iterator
+ * is LessThan Comparable.
+ */
+ template<class IC, class I, class T, class D = std::ptrdiff_t>
+ // ISSUE the default for D seems rather dangerous as it can easily be (silently) incorrect
+ struct random_access_iterator_base:
+ public std::iterator<IC, T> {
+ typedef I derived_iterator_type;
+ typedef T derived_value_type;
+ typedef D derived_difference_type;
+
+ /* FIXME Need to explicitly pass derived_reference_type as otherwise I undefined type or forward declared
+ typedef typename derived_iterator_type::reference derived_reference_type;
+ // Indexed element
+ BOOST_UBLAS_INLINE
+ derived_reference_type operator [] (derived_difference_type n) {
+ return *(*this + n);
+ }
+ */
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator ++ (int) {
+ derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
+ derived_iterator_type tmp (d);
+ ++ d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator -- (int) {
+ derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));
+ derived_iterator_type tmp (d);
+ -- d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator -- (derived_iterator_type &d, int) {
+ derived_iterator_type tmp (d);
+ -- d;
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator + (derived_difference_type n) const {
+ derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator + (const derived_iterator_type &d, derived_difference_type n) {
+ derived_iterator_type tmp (d);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator + (derived_difference_type n, const derived_iterator_type &d) {
+ derived_iterator_type tmp (d);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ derived_iterator_type operator - (derived_difference_type n) const {
+ derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));
+ return tmp -= n;
+ }
+ BOOST_UBLAS_INLINE
+ friend derived_iterator_type operator - (const derived_iterator_type &d, derived_difference_type n) {
+ derived_iterator_type tmp (d);
+ return tmp -= n;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator != (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return ! (*d == it);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator <= (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return ! (it < *d);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator >= (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return ! (*d < it);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator > (const derived_iterator_type &it) const {
+ const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
+ return it < *d;
+ }
+ };
+
+ /** \brief Base class of all reverse iterators. (non-MSVC version)
+ *
+ * \param I the derived iterator type
+ * \param T the value type
+ * \param R the reference type
+ *
+ * The reverse iterator implements a bidirectional iterator
+ * reversing the elements of the underlying iterator. It
+ * implements most operators of a random access iterator.
+ *
+ * uBLAS extension: it.index()
+ */
+
+ // Renamed this class from reverse_iterator to get
+ // typedef reverse_iterator<...> reverse_iterator
+ // working. Thanks to Gabriel Dos Reis for explaining this.
+ template <class I>
+ class reverse_iterator_base:
+ public std::reverse_iterator<I> {
+ public:
+ typedef typename I::container_type container_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename I::difference_type difference_type;
+ typedef I iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base ():
+ std::reverse_iterator<iterator_type> () {}
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base (const iterator_type &it):
+ std::reverse_iterator<iterator_type> (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base &operator ++ () {
+ return *this = -- this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base operator ++ (int) {
+ reverse_iterator_base tmp (*this);
+ *this = -- this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base &operator -- () {
+ return *this = ++ this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base operator -- (int) {
+ reverse_iterator_base tmp (*this);
+ *this = ++ this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base &operator += (difference_type n) {
+ return *this = this->base () - n;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base &operator -= (difference_type n) {
+ return *this = this->base () + n;
+ }
+
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base operator + (const reverse_iterator_base &it, difference_type n) {
+ reverse_iterator_base tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base operator + (difference_type n, const reverse_iterator_base &it) {
+ reverse_iterator_base tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base operator - (const reverse_iterator_base &it, difference_type n) {
+ reverse_iterator_base tmp (it);
+ return tmp -= n;
+ }
+ BOOST_UBLAS_INLINE
+ friend difference_type operator - (const reverse_iterator_base &it1, const reverse_iterator_base &it2) {
+ return it2.base () - it1.base ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return this->base () ();
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).index ();
+ }
+ };
+
+ /** \brief 1st base class of all matrix reverse iterators. (non-MSVC version)
+ *
+ * \param I the derived iterator type
+ *
+ * The reverse iterator implements a bidirectional iterator
+ * reversing the elements of the underlying iterator. It
+ * implements most operators of a random access iterator.
+ *
+ * uBLAS extension: it.index1(), it.index2() and access to
+ * the dual iterator via begin(), end(), rbegin(), rend()
+ */
+
+ // Renamed this class from reverse_iterator1 to get
+ // typedef reverse_iterator1<...> reverse_iterator1
+ // working. Thanks to Gabriel Dos Reis for explaining this.
+ template <class I>
+ class reverse_iterator_base1:
+ public std::reverse_iterator<I> {
+ public:
+ typedef typename I::container_type container_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename I::difference_type difference_type;
+ typedef I iterator_type;
+ typedef typename I::dual_iterator_type dual_iterator_type;
+ typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 ():
+ std::reverse_iterator<iterator_type> () {}
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 (const iterator_type &it):
+ std::reverse_iterator<iterator_type> (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 &operator ++ () {
+ return *this = -- this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 operator ++ (int) {
+ reverse_iterator_base1 tmp (*this);
+ *this = -- this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 &operator -- () {
+ return *this = ++ this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 operator -- (int) {
+ reverse_iterator_base1 tmp (*this);
+ *this = ++ this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 &operator += (difference_type n) {
+ return *this = this->base () - n;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base1 &operator -= (difference_type n) {
+ return *this = this->base () + n;
+ }
+
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base1 operator + (const reverse_iterator_base1 &it, difference_type n) {
+ reverse_iterator_base1 tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base1 operator + (difference_type n, const reverse_iterator_base1 &it) {
+ reverse_iterator_base1 tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base1 operator - (const reverse_iterator_base1 &it, difference_type n) {
+ reverse_iterator_base1 tmp (it);
+ return tmp -= n;
+ }
+ BOOST_UBLAS_INLINE
+ friend difference_type operator - (const reverse_iterator_base1 &it1, const reverse_iterator_base1 &it2) {
+ return it2.base () - it1.base ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return this->base () ();
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).index2 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).begin ();
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).end ();
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+ };
+
+ /** \brief 2nd base class of all matrix reverse iterators. (non-MSVC version)
+ *
+ * \param I the derived iterator type
+ *
+ * The reverse iterator implements a bidirectional iterator
+ * reversing the elements of the underlying iterator. It
+ * implements most operators of a random access iterator.
+ *
+ * uBLAS extension: it.index1(), it.index2() and access to
+ * the dual iterator via begin(), end(), rbegin(), rend()
+ *
+ * Note: this type is _identical_ to reverse_iterator_base1
+ */
+
+ // Renamed this class from reverse_iterator2 to get
+ // typedef reverse_iterator2<...> reverse_iterator2
+ // working. Thanks to Gabriel Dos Reis for explaining this.
+ template <class I>
+ class reverse_iterator_base2:
+ public std::reverse_iterator<I> {
+ public:
+ typedef typename I::container_type container_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename I::difference_type difference_type;
+ typedef I iterator_type;
+ typedef typename I::dual_iterator_type dual_iterator_type;
+ typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 ():
+ std::reverse_iterator<iterator_type> () {}
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 (const iterator_type &it):
+ std::reverse_iterator<iterator_type> (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 &operator ++ () {
+ return *this = -- this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 operator ++ (int) {
+ reverse_iterator_base2 tmp (*this);
+ *this = -- this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 &operator -- () {
+ return *this = ++ this->base ();
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 operator -- (int) {
+ reverse_iterator_base2 tmp (*this);
+ *this = ++ this->base ();
+ return tmp;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 &operator += (difference_type n) {
+ return *this = this->base () - n;
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator_base2 &operator -= (difference_type n) {
+ return *this = this->base () + n;
+ }
+
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base2 operator + (const reverse_iterator_base2 &it, difference_type n) {
+ reverse_iterator_base2 tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base2 operator + (difference_type n, const reverse_iterator_base2 &it) {
+ reverse_iterator_base2 tmp (it);
+ return tmp += n;
+ }
+ BOOST_UBLAS_INLINE
+ friend reverse_iterator_base2 operator - (const reverse_iterator_base2 &it, difference_type n) {
+ reverse_iterator_base2 tmp (it);
+ return tmp -= n;
+ }
+ BOOST_UBLAS_INLINE
+ friend difference_type operator - (const reverse_iterator_base2 &it1, const reverse_iterator_base2 &it2) {
+ return it2.base () - it1.base ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return this->base () ();
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).index2 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).begin ();
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ iterator_type tmp (this->base ());
+ return (-- tmp).end ();
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+ };
+
+ /** \brief A class implementing an indexed random access iterator.
+ *
+ * \param C the (mutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as the unsigned integer it_ and the
+ * values are accessed via operator()(it_) of the container.
+ *
+ * uBLAS extension: index()
+ */
+
+ template<class C, class IC>
+ class indexed_iterator:
+ public container_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_iterator<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_iterator ():
+ container_reference<container_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_iterator (container_type &c, size_type it):
+ container_reference<container_type> (c), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) () (it_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_iterator &operator = (const indexed_iterator &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_reference<C>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type it_;
+ };
+
+ /** \brief A class implementing an indexed random access iterator.
+ *
+ * \param C the (immutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as the unsigned integer \c it_ and the
+ * values are accessed via \c operator()(it_) of the container.
+ *
+ * uBLAS extension: \c index()
+ *
+ * Note: there is an automatic conversion from
+ * \c indexed_iterator to \c indexed_const_iterator
+ */
+
+ template<class C, class IC>
+ class indexed_const_iterator:
+ public container_const_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_const_iterator<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::const_reference reference;
+ typedef indexed_iterator<container_type, iterator_category> iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator ():
+ container_const_reference<container_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator (const container_type &c, size_type it):
+ container_const_reference<container_type> (c), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator (const iterator_type &it):
+ container_const_reference<container_type> (it ()), it_ (it.index ()) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_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 (index () < (*this) ().size (), bad_index ());
+ return (*this) () (it_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator &operator = (const indexed_const_iterator &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_const_reference<C>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type it_;
+
+ friend class indexed_iterator<container_type, iterator_category>;
+ };
+
+ template<class C, class IC>
+ class indexed_iterator2;
+
+ /** \brief A class implementing an indexed random access iterator
+ * of a matrix.
+ *
+ * \param C the (mutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as two unsigned integers \c it1_ and \c it2_
+ * and the values are accessed via \c operator()(it1_, it2_) of the
+ * container. The iterator changes the first index.
+ *
+ * uBLAS extension: \c index1(), \c index2() and access to the
+ * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
+ *
+ * Note: The container has to support the \code find2(rank, i, j) \endcode
+ * method
+ */
+
+ template<class C, class IC>
+ class indexed_iterator1:
+ public container_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_iterator1<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+
+ typedef indexed_iterator2<container_type, iterator_category> dual_iterator_type;
+ typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 ():
+ container_reference<container_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 (container_type &c, size_type it1, size_type it2):
+ container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_iterator1 &operator = (const indexed_iterator1 &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_reference<C>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+
+ template<class C, class IC>
+ class indexed_const_iterator2;
+
+ /** \brief A class implementing an indexed random access iterator
+ * of a matrix.
+ *
+ * \param C the (immutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as two unsigned integers \c it1_ and \c it2_
+ * and the values are accessed via \c operator()(it1_, it2_) of the
+ * container. The iterator changes the first index.
+ *
+ * uBLAS extension: \c index1(), \c index2() and access to the
+ * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
+ *
+ * Note 1: The container has to support the find2(rank, i, j) method
+ *
+ * Note 2: there is an automatic conversion from
+ * \c indexed_iterator1 to \c indexed_const_iterator1
+ */
+
+ template<class C, class IC>
+ class indexed_const_iterator1:
+ public container_const_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_const_iterator1<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::const_reference reference;
+
+ typedef indexed_iterator1<container_type, iterator_category> iterator_type;
+ typedef indexed_const_iterator2<container_type, iterator_category> dual_iterator_type;
+ typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 ():
+ container_const_reference<container_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 (const container_type &c, size_type it1, size_type it2):
+ container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 (const iterator_type &it):
+ container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator1 &operator = (const indexed_const_iterator1 &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_const_reference<C>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class indexed_iterator1<container_type, iterator_category>;
+ };
+
+ /** \brief A class implementing an indexed random access iterator
+ * of a matrix.
+ *
+ * \param C the (mutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as two unsigned integers \c it1_ and \c it2_
+ * and the values are accessed via \c operator()(it1_, it2_) of the
+ * container. The iterator changes the second index.
+ *
+ * uBLAS extension: \c index1(), \c index2() and access to the
+ * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
+ *
+ * Note: The container has to support the find1(rank, i, j) method
+ */
+ template<class C, class IC>
+ class indexed_iterator2:
+ public container_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_iterator2<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::reference reference;
+
+ typedef indexed_iterator1<container_type, iterator_category> dual_iterator_type;
+ typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 ():
+ container_reference<container_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 (container_type &c, size_type it1, size_type it2):
+ container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_iterator2 &operator = (const indexed_iterator2 &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_reference<C>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+
+ /** \brief A class implementing an indexed random access iterator
+ * of a matrix.
+ *
+ * \param C the (immutable) container type
+ * \param IC the iterator category
+ *
+ * This class implements a random access iterator. The current
+ * position is stored as two unsigned integers \c it1_ and \c it2_
+ * and the values are accessed via \c operator()(it1_, it2_) of the
+ * container. The iterator changes the second index.
+ *
+ * uBLAS extension: \c index1(), \c index2() and access to the
+ * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
+ *
+ * Note 1: The container has to support the \c find2(rank, i, j) method
+ *
+ * Note 2: there is an automatic conversion from
+ * \c indexed_iterator2 to \c indexed_const_iterator2
+ */
+
+ template<class C, class IC>
+ class indexed_const_iterator2:
+ public container_const_reference<C>,
+ public random_access_iterator_base<IC,
+ indexed_const_iterator2<C, IC>,
+ typename C::value_type,
+ typename C::difference_type> {
+ public:
+ typedef C container_type;
+ typedef IC iterator_category;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::const_reference reference;
+
+ typedef indexed_iterator2<container_type, iterator_category> iterator_type;
+ typedef indexed_const_iterator1<container_type, iterator_category> dual_iterator_type;
+ typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 ():
+ container_const_reference<container_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 (const container_type &c, size_type it1, size_type it2):
+ container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 (const iterator_type &it):
+ container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const indexed_const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *((*this) + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ BOOST_UBLAS_INLINE
+ dual_iterator_type begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_iterator_type end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rbegin () const {
+ return dual_reverse_iterator_type (end ());
+ }
+ BOOST_UBLAS_INLINE
+ dual_reverse_iterator_type rend () const {
+ return dual_reverse_iterator_type (begin ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ indexed_const_iterator2 &operator = (const indexed_const_iterator2 &it) {
+ // FIX: ICC needs full qualification?!
+ // assign (&it ());
+ container_const_reference<C>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const indexed_const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const indexed_const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class indexed_iterator2<container_type, iterator_category>;
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_MATRIX_ASSIGN_
+#define _BOOST_UBLAS_MATRIX_ASSIGN_
+
+#include <boost/numeric/ublas/traits.hpp>
+// Required for make_conformant storage
+#include <vector>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+namespace detail {
+
+ // Weak equality check - useful to compare equality two arbitary matrix expression results.
+ // Since the actual expressions are unknown, we check for and arbitary error bound
+ // on the relative error.
+ // For a linear expression the infinity norm makes sense as we do not know how the elements will be
+ // combined in the expression. False positive results are inevitable for arbirary expressions!
+ template<class E1, class E2, class S>
+ BOOST_UBLAS_INLINE
+ bool equals (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2, S epsilon, S min_norm) {
+ return norm_inf (e1 - e2) < epsilon *
+ std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ bool expression_type_check (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2) {
+ typedef typename type_traits<typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type>::real_type real_type;
+ return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
+ }
+
+
+ template<class M, class E, class R>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void make_conformant (M &m, const matrix_expression<E> &e, row_major_tag, R) {
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ // FIXME unbounded_array with push_back maybe better
+ std::vector<std::pair<size_type, size_type> > index;
+ typename M::iterator1 it1 (m.begin1 ());
+ typename M::iterator1 it1_end (m.end1 ());
+ typename E::const_iterator1 it1e (e ().begin1 ());
+ typename E::const_iterator1 it1e_end (e ().end1 ());
+ while (it1 != it1_end && it1e != it1e_end) {
+ difference_type compare = it1.index1 () - it1e.index1 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ if (it2 != it2_end && it2e != it2e_end) {
+ size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
+ while (true) {
+ difference_type compare = it2_index - it2e_index;
+ if (compare == 0) {
+ ++ it2, ++ it2e;
+ if (it2 != it2_end && it2e != it2e_end) {
+ it2_index = it2.index2 ();
+ it2e_index = it2e.index2 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it2, it2_end, - compare);
+ if (it2 != it2_end)
+ it2_index = it2.index2 ();
+ else
+ break;
+ } else if (compare > 0) {
+ if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
+ if (static_cast<value_type>(*it2e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
+ ++ it2e;
+ if (it2e != it2e_end)
+ it2e_index = it2e.index2 ();
+ else
+ break;
+ }
+ }
+ }
+ while (it2e != it2e_end) {
+ if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
+ if (static_cast<value_type>(*it2e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
+ ++ it2e;
+ }
+ ++ it1, ++ it1e;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ } else if (compare > 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ while (it2e != it2e_end) {
+ if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
+ if (static_cast<value_type>(*it2e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
+ ++ it2e;
+ }
+ ++ it1e;
+ }
+ }
+ while (it1e != it1e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ while (it2e != it2e_end) {
+ if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
+ if (static_cast<value_type>(*it2e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
+ ++ it2e;
+ }
+ ++ it1e;
+ }
+ // ISSUE proxies require insert_element
+ for (size_type k = 0; k < index.size (); ++ k)
+ m (index [k].first, index [k].second) = value_type/*zero*/();
+ }
+ template<class M, class E, class R>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void make_conformant (M &m, const matrix_expression<E> &e, column_major_tag, R) {
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ std::vector<std::pair<size_type, size_type> > index;
+ typename M::iterator2 it2 (m.begin2 ());
+ typename M::iterator2 it2_end (m.end2 ());
+ typename E::const_iterator2 it2e (e ().begin2 ());
+ typename E::const_iterator2 it2e_end (e ().end2 ());
+ while (it2 != it2_end && it2e != it2e_end) {
+ difference_type compare = it2.index2 () - it2e.index2 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ if (it1 != it1_end && it1e != it1e_end) {
+ size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
+ while (true) {
+ difference_type compare = it1_index - it1e_index;
+ if (compare == 0) {
+ ++ it1, ++ it1e;
+ if (it1 != it1_end && it1e != it1e_end) {
+ it1_index = it1.index1 ();
+ it1e_index = it1e.index1 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index1 ();
+ else
+ break;
+ } else if (compare > 0) {
+ if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
+ if (static_cast<value_type>(*it1e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
+ ++ it1e;
+ if (it1e != it1e_end)
+ it1e_index = it1e.index1 ();
+ else
+ break;
+ }
+ }
+ }
+ while (it1e != it1e_end) {
+ if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
+ if (static_cast<value_type>(*it1e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
+ ++ it1e;
+ }
+ ++ it2, ++ it2e;
+ } else if (compare < 0) {
+ increment (it2, it2_end, - compare);
+ } else if (compare > 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ while (it1e != it1e_end) {
+ if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
+ if (static_cast<value_type>(*it1e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
+ ++ it1e;
+ }
+ ++ it2e;
+ }
+ }
+ while (it2e != it2e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ while (it1e != it1e_end) {
+ if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
+ if (static_cast<value_type>(*it1e) != value_type/*zero*/())
+ index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
+ ++ it1e;
+ }
+ ++ it2e;
+ }
+ // ISSUE proxies require insert_element
+ for (size_type k = 0; k < index.size (); ++ k)
+ m (index [k].first, index [k].second) = value_type/*zero*/();
+ }
+
+}//namespace detail
+
+
+ // Explicitly iterating row major
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
+ typedef F<typename M::iterator2::reference, T> functor_type;
+ typedef typename M::difference_type difference_type;
+ difference_type size1 (m.size1 ());
+ difference_type size2 (m.size2 ());
+ typename M::iterator1 it1 (m.begin1 ());
+ BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+#endif
+ BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
+ difference_type temp_size2 (size2);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- temp_size2 >= 0)
+ functor_type::apply (*it2, t), ++ it2;
+#else
+ DD (temp_size2, 4, r, (functor_type::apply (*it2, t), ++ it2));
+#endif
+ ++ it1;
+ }
+ }
+ // Explicitly iterating column major
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
+ typedef F<typename M::iterator1::reference, T> functor_type;
+ typedef typename M::difference_type difference_type;
+ difference_type size2 (m.size2 ());
+ difference_type size1 (m.size1 ());
+ typename M::iterator2 it2 (m.begin2 ());
+ BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+#endif
+ BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
+ difference_type temp_size1 (size1);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- temp_size1 >= 0)
+ functor_type::apply (*it1, t), ++ it1;
+#else
+ DD (temp_size1, 4, r, (functor_type::apply (*it1, t), ++ it1));
+#endif
+ ++ it2;
+ }
+ }
+ // Explicitly indexing row major
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
+ typedef F<typename M::reference, T> functor_type;
+ typedef typename M::size_type size_type;
+ size_type size1 (m.size1 ());
+ size_type size2 (m.size2 ());
+ for (size_type i = 0; i < size1; ++ i) {
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type j = 0; j < size2; ++ j)
+ functor_type::apply (m (i, j), t);
+#else
+ size_type j (0);
+ DD (size2, 4, r, (functor_type::apply (m (i, j), t), ++ j));
+#endif
+ }
+ }
+ // Explicitly indexing column major
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
+ typedef F<typename M::reference, T> functor_type;
+ typedef typename M::size_type size_type;
+ size_type size2 (m.size2 ());
+ size_type size1 (m.size1 ());
+ for (size_type j = 0; j < size2; ++ j) {
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type i = 0; i < size1; ++ i)
+ functor_type::apply (m (i, j), t);
+#else
+ size_type i (0);
+ DD (size1, 4, r, (functor_type::apply (m (i, j), t), ++ i));
+#endif
+ }
+ }
+
+ // Dense (proxy) case
+ template<template <class T1, class T2> class F, class M, class T, class C>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign_scalar (M &m, const T &t, dense_proxy_tag, C) {
+ typedef C orientation_category;
+#ifdef BOOST_UBLAS_USE_INDEXING
+ indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
+#elif BOOST_UBLAS_USE_ITERATING
+ iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
+#else
+ typedef typename M::size_type size_type;
+ size_type size1 (m.size1 ());
+ size_type size2 (m.size2 ());
+ if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
+ size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
+ else
+ indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
+#endif
+ }
+ // Packed (proxy) row major case
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, T> functor_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator1 it1 (m.begin1 ());
+ difference_type size1 (m.end1 () - it1);
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ difference_type size2 (it1.end () - it2);
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ difference_type size2 (end (it1, iterator1_tag ()) - it2);
+#endif
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, t), ++ it2;
+ ++ it1;
+ }
+ }
+ // Packed (proxy) column major case
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, T> functor_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator2 it2 (m.begin2 ());
+ difference_type size2 (m.end2 () - it2);
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ difference_type size1 (it2.end () - it1);
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ difference_type size1 (end (it2, iterator2_tag ()) - it1);
+#endif
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, t), ++ it1;
+ ++ it2;
+ }
+ }
+ // Sparse (proxy) row major case
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, T> functor_type;
+ typename M::iterator1 it1 (m.begin1 ());
+ typename M::iterator1 it1_end (m.end1 ());
+ while (it1 != it1_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end)
+ functor_type::apply (*it2, t), ++ it2;
+ ++ it1;
+ }
+ }
+ // Sparse (proxy) column major case
+ template<template <class T1, class T2> class F, class M, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, T> functor_type;
+ typename M::iterator2 it2 (m.begin2 ());
+ typename M::iterator2 it2_end (m.end2 ());
+ while (it2 != it2_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end)
+ functor_type::apply (*it1, t), ++ it1;
+ ++ it2;
+ }
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class M, class T>
+ BOOST_UBLAS_INLINE
+ void matrix_assign_scalar (M &m, const T &t) {
+ typedef typename M::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+ matrix_assign_scalar<F> (m, t, storage_category (), orientation_category ());
+ }
+
+ template<class SC, bool COMPUTED, class RI1, class RI2>
+ struct matrix_assign_traits {
+ typedef SC storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct matrix_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
+ typedef packed_tag storage_category;
+ };
+ template<>
+ struct matrix_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_tag storage_category;
+ };
+ template<>
+ struct matrix_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct matrix_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<bool COMPUTED>
+ struct matrix_assign_traits<dense_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct matrix_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_tag storage_category;
+ };
+ template<>
+ struct matrix_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct matrix_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct matrix_assign_traits<sparse_tag, true, dense_random_access_iterator_tag, dense_random_access_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct matrix_assign_traits<sparse_tag, true, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct matrix_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ // Explicitly iterating row major
+ template<template <class T1, class T2> class F, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
+ typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
+ typedef typename M::difference_type difference_type;
+ difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
+ difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
+ typename M::iterator1 it1 (m.begin1 ());
+ BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
+ typename E::const_iterator1 it1e (e ().begin1 ());
+ BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ());
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename E::const_iterator2 it2e (it1e.begin ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+#endif
+ BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
+ BOOST_UBLAS_CHECK (it1e.end () - it2e == size2, bad_size ());
+ difference_type temp_size2 (size2);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- temp_size2 >= 0)
+ functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
+#else
+ DD (temp_size2, 2, r, (functor_type::apply (*it2, *it2e), ++ it2, ++ it2e));
+#endif
+ ++ it1, ++ it1e;
+ }
+ }
+ // Explicitly iterating column major
+ template<template <class T1, class T2> class F, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
+ typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
+ typedef typename M::difference_type difference_type;
+ difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
+ difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
+ typename M::iterator2 it2 (m.begin2 ());
+ BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
+ typename E::const_iterator2 it2e (e ().begin2 ());
+ BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ());
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename E::const_iterator1 it1e (it2e.begin ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+#endif
+ BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
+ BOOST_UBLAS_CHECK (it2e.end () - it1e == size1, bad_size ());
+ difference_type temp_size1 (size1);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- temp_size1 >= 0)
+ functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
+#else
+ DD (temp_size1, 2, r, (functor_type::apply (*it1, *it1e), ++ it1, ++ it1e));
+#endif
+ ++ it2, ++ it2e;
+ }
+ }
+ // Explicitly indexing row major
+ template<template <class T1, class T2> class F, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
+ typedef F<typename M::reference, typename E::value_type> functor_type;
+ typedef typename M::size_type size_type;
+ size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
+ size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
+ for (size_type i = 0; i < size1; ++ i) {
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type j = 0; j < size2; ++ j)
+ functor_type::apply (m (i, j), e () (i, j));
+#else
+ size_type j (0);
+ DD (size2, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ j));
+#endif
+ }
+ }
+ // Explicitly indexing column major
+ template<template <class T1, class T2> class F, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
+ typedef F<typename M::reference, typename E::value_type> functor_type;
+ typedef typename M::size_type size_type;
+ size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
+ size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
+ for (size_type j = 0; j < size2; ++ j) {
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type i = 0; i < size1; ++ i)
+ functor_type::apply (m (i, j), e () (i, j));
+#else
+ size_type i (0);
+ DD (size1, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ i));
+#endif
+ }
+ }
+
+ // Dense (proxy) case
+ template<template <class T1, class T2> class F, class R, class M, class E, class C>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, dense_proxy_tag, C) {
+ // R unnecessary, make_conformant not required
+ typedef C orientation_category;
+#ifdef BOOST_UBLAS_USE_INDEXING
+ indexing_matrix_assign<F> (m, e, orientation_category ());
+#elif BOOST_UBLAS_USE_ITERATING
+ iterating_matrix_assign<F> (m, e, orientation_category ());
+#else
+ typedef typename M::difference_type difference_type;
+ size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
+ size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
+ if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
+ size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ iterating_matrix_assign<F> (m, e, orientation_category ());
+ else
+ indexing_matrix_assign<F> (m, e, orientation_category ());
+#endif
+ }
+ // Packed (proxy) row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
+ typedef typename matrix_traits<E>::value_type expr_value_type;
+ typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
+ indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
+ indexing_matrix_assign<F> (cm, e, row_major_tag ());
+#endif
+ typename M::iterator1 it1 (m.begin1 ());
+ typename M::iterator1 it1_end (m.end1 ());
+ typename E::const_iterator1 it1e (e ().begin1 ());
+ typename E::const_iterator1 it1e_end (e ().end1 ());
+ difference_type it1_size (it1_end - it1);
+ difference_type it1e_size (it1e_end - it1e);
+ difference_type diff1 (0);
+ if (it1_size > 0 && it1e_size > 0)
+ diff1 = it1.index1 () - it1e.index1 ();
+ if (diff1 != 0) {
+ difference_type size1 = (std::min) (diff1, it1e_size);
+ if (size1 > 0) {
+ it1e += size1;
+ it1e_size -= size1;
+ diff1 -= size1;
+ }
+ size1 = (std::min) (- diff1, it1_size);
+ if (size1 > 0) {
+ it1_size -= size1;
+ if (!functor_type::computed) {
+ while (-- size1 >= 0) { // zeroing
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ difference_type size2 (it2_end - it2);
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
+ ++ it1;
+ }
+ } else {
+ it1 += size1;
+ }
+ diff1 += size1;
+ }
+ }
+ difference_type size1 ((std::min) (it1_size, it1e_size));
+ it1_size -= size1;
+ it1e_size -= size1;
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ difference_type it2_size (it2_end - it2);
+ difference_type it2e_size (it2e_end - it2e);
+ difference_type diff2 (0);
+ if (it2_size > 0 && it2e_size > 0) {
+ diff2 = it2.index2 () - it2e.index2 ();
+ difference_type size2 = (std::min) (diff2, it2e_size);
+ if (size2 > 0) {
+ it2e += size2;
+ it2e_size -= size2;
+ diff2 -= size2;
+ }
+ size2 = (std::min) (- diff2, it2_size);
+ if (size2 > 0) {
+ it2_size -= size2;
+ if (!functor_type::computed) {
+ while (-- size2 >= 0) // zeroing
+ functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
+ } else {
+ it2 += size2;
+ }
+ diff2 += size2;
+ }
+ }
+ difference_type size2 ((std::min) (it2_size, it2e_size));
+ it2_size -= size2;
+ it2e_size -= size2;
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
+ size2 = it2_size;
+ if (!functor_type::computed) {
+ while (-- size2 >= 0) // zeroing
+ functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
+ } else {
+ it2 += size2;
+ }
+ ++ it1, ++ it1e;
+ }
+ size1 = it1_size;
+ if (!functor_type::computed) {
+ while (-- size1 >= 0) { // zeroing
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ difference_type size2 (it2_end - it2);
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
+ ++ it1;
+ }
+ } else {
+ it1 += size1;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
+#endif
+ }
+ // Packed (proxy) column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
+ typedef typename matrix_traits<E>::value_type expr_value_type;
+ typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
+ indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
+ indexing_matrix_assign<F> (cm, e, column_major_tag ());
+#endif
+ typename M::iterator2 it2 (m.begin2 ());
+ typename M::iterator2 it2_end (m.end2 ());
+ typename E::const_iterator2 it2e (e ().begin2 ());
+ typename E::const_iterator2 it2e_end (e ().end2 ());
+ difference_type it2_size (it2_end - it2);
+ difference_type it2e_size (it2e_end - it2e);
+ difference_type diff2 (0);
+ if (it2_size > 0 && it2e_size > 0)
+ diff2 = it2.index2 () - it2e.index2 ();
+ if (diff2 != 0) {
+ difference_type size2 = (std::min) (diff2, it2e_size);
+ if (size2 > 0) {
+ it2e += size2;
+ it2e_size -= size2;
+ diff2 -= size2;
+ }
+ size2 = (std::min) (- diff2, it2_size);
+ if (size2 > 0) {
+ it2_size -= size2;
+ if (!functor_type::computed) {
+ while (-- size2 >= 0) { // zeroing
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ difference_type size1 (it1_end - it1);
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
+ ++ it2;
+ }
+ } else {
+ it2 += size2;
+ }
+ diff2 += size2;
+ }
+ }
+ difference_type size2 ((std::min) (it2_size, it2e_size));
+ it2_size -= size2;
+ it2e_size -= size2;
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ difference_type it1_size (it1_end - it1);
+ difference_type it1e_size (it1e_end - it1e);
+ difference_type diff1 (0);
+ if (it1_size > 0 && it1e_size > 0) {
+ diff1 = it1.index1 () - it1e.index1 ();
+ difference_type size1 = (std::min) (diff1, it1e_size);
+ if (size1 > 0) {
+ it1e += size1;
+ it1e_size -= size1;
+ diff1 -= size1;
+ }
+ size1 = (std::min) (- diff1, it1_size);
+ if (size1 > 0) {
+ it1_size -= size1;
+ if (!functor_type::computed) {
+ while (-- size1 >= 0) // zeroing
+ functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
+ } else {
+ it1 += size1;
+ }
+ diff1 += size1;
+ }
+ }
+ difference_type size1 ((std::min) (it1_size, it1e_size));
+ it1_size -= size1;
+ it1e_size -= size1;
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
+ size1 = it1_size;
+ if (!functor_type::computed) {
+ while (-- size1 >= 0) // zeroing
+ functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
+ } else {
+ it1 += size1;
+ }
+ ++ it2, ++ it2e;
+ }
+ size2 = it2_size;
+ if (!functor_type::computed) {
+ while (-- size2 >= 0) { // zeroing
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ difference_type size1 (it1_end - it1);
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
+ ++ it2;
+ }
+ } else {
+ it2 += size2;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
+#endif
+ }
+ // Sparse row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
+ // R unnecessary, make_conformant not required
+ BOOST_STATIC_ASSERT ((!functor_type::computed));
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+ typedef typename M::value_type value_type;
+ // Sparse type has no numeric constraints to check
+
+ m.clear ();
+ typename E::const_iterator1 it1e (e ().begin1 ());
+ typename E::const_iterator1 it1e_end (e ().end1 ());
+ while (it1e != it1e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ while (it2e != it2e_end) {
+ value_type t (*it2e);
+ if (t != value_type/*zero*/())
+ m.insert_element (it2e.index1 (), it2e.index2 (), t);
+ ++ it2e;
+ }
+ ++ it1e;
+ }
+ }
+ // Sparse column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
+ // R unnecessary, make_conformant not required
+ BOOST_STATIC_ASSERT ((!functor_type::computed));
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+ typedef typename M::value_type value_type;
+ // Sparse type has no numeric constraints to check
+
+ m.clear ();
+ typename E::const_iterator2 it2e (e ().begin2 ());
+ typename E::const_iterator2 it2e_end (e ().end2 ());
+ while (it2e != it2e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ while (it1e != it1e_end) {
+ value_type t (*it1e);
+ if (t != value_type/*zero*/())
+ m.insert_element (it1e.index1 (), it1e.index2 (), t);
+ ++ it1e;
+ }
+ ++ it2e;
+ }
+ }
+ // Sparse proxy or functional row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
+ typedef typename matrix_traits<E>::value_type expr_value_type;
+ typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
+ indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
+ indexing_matrix_assign<F> (cm, e, row_major_tag ());
+#endif
+ detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
+
+ typename M::iterator1 it1 (m.begin1 ());
+ typename M::iterator1 it1_end (m.end1 ());
+ typename E::const_iterator1 it1e (e ().begin1 ());
+ typename E::const_iterator1 it1e_end (e ().end1 ());
+ while (it1 != it1_end && it1e != it1e_end) {
+ difference_type compare = it1.index1 () - it1e.index1 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+ typename E::const_iterator2 it2e (it1e.begin ());
+ typename E::const_iterator2 it2e_end (it1e.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+ typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ if (it2 != it2_end && it2e != it2e_end) {
+ size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
+ while (true) {
+ difference_type compare = it2_index - it2e_index;
+ if (compare == 0) {
+ functor_type::apply (*it2, *it2e);
+ ++ it2, ++ it2e;
+ if (it2 != it2_end && it2e != it2e_end) {
+ it2_index = it2.index2 ();
+ it2e_index = it2e.index2 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ if (!functor_type::computed) {
+ functor_type::apply (*it2, expr_value_type/*zero*/());
+ ++ it2;
+ } else
+ increment (it2, it2_end, - compare);
+ if (it2 != it2_end)
+ it2_index = it2.index2 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it2e, it2e_end, compare);
+ if (it2e != it2e_end)
+ it2e_index = it2e.index2 ();
+ else
+ break;
+ }
+ }
+ }
+ if (!functor_type::computed) {
+ while (it2 != it2_end) { // zeroing
+ functor_type::apply (*it2, expr_value_type/*zero*/());
+ ++ it2;
+ }
+ } else {
+ it2 = it2_end;
+ }
+ ++ it1, ++ it1e;
+ } else if (compare < 0) {
+ if (!functor_type::computed) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) { // zeroing
+ functor_type::apply (*it2, expr_value_type/*zero*/());
+ ++ it2;
+ }
+ ++ it1;
+ } else {
+ increment (it1, it1_end, - compare);
+ }
+ } else if (compare > 0) {
+ increment (it1e, it1e_end, compare);
+ }
+ }
+ if (!functor_type::computed) {
+ while (it1 != it1_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) { // zeroing
+ functor_type::apply (*it2, expr_value_type/*zero*/());
+ ++ it2;
+ }
+ ++ it1;
+ }
+ } else {
+ it1 = it1_end;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
+#endif
+ }
+ // Sparse proxy or functional column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
+ typedef typename matrix_traits<E>::value_type expr_value_type;
+ typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
+ indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
+ indexing_matrix_assign<F> (cm, e, column_major_tag ());
+#endif
+ detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
+
+ typename M::iterator2 it2 (m.begin2 ());
+ typename M::iterator2 it2_end (m.end2 ());
+ typename E::const_iterator2 it2e (e ().begin2 ());
+ typename E::const_iterator2 it2e_end (e ().end2 ());
+ while (it2 != it2_end && it2e != it2e_end) {
+ difference_type compare = it2.index2 () - it2e.index2 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+ typename E::const_iterator1 it1e (it2e.begin ());
+ typename E::const_iterator1 it1e_end (it2e.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+ typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ if (it1 != it1_end && it1e != it1e_end) {
+ size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
+ while (true) {
+ difference_type compare = it1_index - it1e_index;
+ if (compare == 0) {
+ functor_type::apply (*it1, *it1e);
+ ++ it1, ++ it1e;
+ if (it1 != it1_end && it1e != it1e_end) {
+ it1_index = it1.index1 ();
+ it1e_index = it1e.index1 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ if (!functor_type::computed) {
+ functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing
+ ++ it1;
+ } else
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index1 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it1e, it1e_end, compare);
+ if (it1e != it1e_end)
+ it1e_index = it1e.index1 ();
+ else
+ break;
+ }
+ }
+ }
+ if (!functor_type::computed) {
+ while (it1 != it1_end) { // zeroing
+ functor_type::apply (*it1, expr_value_type/*zero*/());
+ ++ it1;
+ }
+ } else {
+ it1 = it1_end;
+ }
+ ++ it2, ++ it2e;
+ } else if (compare < 0) {
+ if (!functor_type::computed) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) { // zeroing
+ functor_type::apply (*it1, expr_value_type/*zero*/());
+ ++ it1;
+ }
+ ++ it2;
+ } else {
+ increment (it2, it2_end, - compare);
+ }
+ } else if (compare > 0) {
+ increment (it2e, it2e_end, compare);
+ }
+ }
+ if (!functor_type::computed) {
+ while (it2 != it2_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) { // zeroing
+ functor_type::apply (*it1, expr_value_type/*zero*/());
+ ++ it1;
+ }
+ ++ it2;
+ }
+ } else {
+ it2 = it2_end;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
+#endif
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class M, class E>
+ BOOST_UBLAS_INLINE
+ void matrix_assign (M &m, const matrix_expression<E> &e) {
+ typedef typename matrix_assign_traits<typename M::storage_category,
+ F<typename M::reference, typename E::value_type>::computed,
+ typename E::const_iterator1::iterator_category,
+ typename E::const_iterator2::iterator_category>::storage_category storage_category;
+ // give preference to matrix M's orientation if known
+ typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
+ typename E::orientation_category ,
+ typename M::orientation_category >::type orientation_category;
+ typedef basic_full<typename M::size_type> unrestricted;
+ matrix_assign<F, unrestricted> (m, e, storage_category (), orientation_category ());
+ }
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ BOOST_UBLAS_INLINE
+ void matrix_assign (M &m, const matrix_expression<E> &e) {
+ typedef R conformant_restrict_type;
+ typedef typename matrix_assign_traits<typename M::storage_category,
+ F<typename M::reference, typename E::value_type>::computed,
+ typename E::const_iterator1::iterator_category,
+ typename E::const_iterator2::iterator_category>::storage_category storage_category;
+ // give preference to matrix M's orientation if known
+ typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
+ typename E::orientation_category ,
+ typename M::orientation_category >::type orientation_category;
+ matrix_assign<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
+ }
+
+ template<class SC, class RI1, class RI2>
+ struct matrix_swap_traits {
+ typedef SC storage_category;
+ };
+
+ template<>
+ struct matrix_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct matrix_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ // Dense (proxy) row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator1 it1 (m.begin1 ());
+ typename E::iterator1 it1e (e ().begin1 ());
+ difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (e ().end1 () - it1e)));
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename E::iterator2 it2e (it1e.begin ());
+ difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (it1e.end () - it2e)));
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
+ difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (end (it1e, iterator1_tag ()) - it2e)));
+#endif
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
+ ++ it1, ++ it1e;
+ }
+ }
+ // Dense (proxy) column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator2 it2 (m.begin2 ());
+ typename E::iterator2 it2e (e ().begin2 ());
+ difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (e ().end2 () - it2e)));
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename E::iterator1 it1e (it2e.begin ());
+ difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (it2e.end () - it1e)));
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
+ difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (end (it2e, iterator2_tag ()) - it1e)));
+#endif
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
+ ++ it2, ++ it2e;
+ }
+ }
+ // Packed (proxy) row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator1 it1 (m.begin1 ());
+ typename E::iterator1 it1e (e ().begin1 ());
+ difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e));
+ while (-- size1 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename E::iterator2 it2e (it1e.begin ());
+ difference_type size2 (BOOST_UBLAS_SAME (it1.end () - it2, it1e.end () - it2e));
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
+ difference_type size2 (BOOST_UBLAS_SAME (end (it1, iterator1_tag ()) - it2, end (it1e, iterator1_tag ()) - it2e));
+#endif
+ while (-- size2 >= 0)
+ functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
+ ++ it1, ++ it1e;
+ }
+ }
+ // Packed (proxy) column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
+ // R unnecessary, make_conformant not required
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typename M::iterator2 it2 (m.begin2 ());
+ typename E::iterator2 it2e (e ().begin2 ());
+ difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e));
+ while (-- size2 >= 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename E::iterator1 it1e (it2e.begin ());
+ difference_type size1 (BOOST_UBLAS_SAME (it2.end () - it1, it2e.end () - it1e));
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
+ difference_type size1 (BOOST_UBLAS_SAME (end (it2, iterator2_tag ()) - it1, end (it2e, iterator2_tag ()) - it1e));
+#endif
+ while (-- size1 >= 0)
+ functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
+ ++ it2, ++ it2e;
+ }
+ }
+ // Sparse (proxy) row major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
+ typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+
+ detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
+ // FIXME should be a seperate restriction for E
+ detail::make_conformant (e (), m, row_major_tag (), conformant_restrict_type ());
+
+ typename M::iterator1 it1 (m.begin1 ());
+ typename M::iterator1 it1_end (m.end1 ());
+ typename E::iterator1 it1e (e ().begin1 ());
+ typename E::iterator1 it1e_end (e ().end1 ());
+ while (it1 != it1_end && it1e != it1e_end) {
+ difference_type compare = it1.index1 () - it1e.index1 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+ typename E::iterator2 it2e (it1e.begin ());
+ typename E::iterator2 it2e_end (it1e.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+ typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ if (it2 != it2_end && it2e != it2e_end) {
+ size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
+ while (true) {
+ difference_type compare = it2_index - it2e_index;
+ if (compare == 0) {
+ functor_type::apply (*it2, *it2e);
+ ++ it2, ++ it2e;
+ if (it2 != it2_end && it2e != it2e_end) {
+ it2_index = it2.index2 ();
+ it2e_index = it2e.index2 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it2, it2_end, - compare);
+ if (it2 != it2_end)
+ it2_index = it2.index2 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it2e, it2e_end, compare);
+ if (it2e != it2e_end)
+ it2e_index = it2e.index2 ();
+ else
+ break;
+ }
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ increment (it2e, it2e_end);
+ increment (it2, it2_end);
+#endif
+ ++ it1, ++ it1e;
+ } else if (compare < 0) {
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it1.index1 () < it1e.index1 ()) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ increment (it2, it2_end);
+ ++ it1;
+ }
+#else
+ increment (it1, it1_end, - compare);
+#endif
+ } else if (compare > 0) {
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it1e.index1 () < it1.index1 ()) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::iterator2 it2e (it1e.begin ());
+ typename E::iterator2 it2e_end (it1e.end ());
+#else
+ typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ increment (it2e, it2e_end);
+ ++ it1e;
+ }
+#else
+ increment (it1e, it1e_end, compare);
+#endif
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it1e != it1e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::iterator2 it2e (it1e.begin ());
+ typename E::iterator2 it2e_end (it1e.end ());
+#else
+ typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
+ typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
+#endif
+ increment (it2e, it2e_end);
+ ++ it1e;
+ }
+ while (it1 != it1_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator2 it2 (it1.begin ());
+ typename M::iterator2 it2_end (it1.end ());
+#else
+ typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
+ typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
+#endif
+ increment (it2, it2_end);
+ ++ it1;
+ }
+#endif
+ }
+ // Sparse (proxy) column major case
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
+ typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
+ typedef R conformant_restrict_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
+
+ detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
+ // FIXME should be a seperate restriction for E
+ detail::make_conformant (e (), m, column_major_tag (), conformant_restrict_type ());
+
+ typename M::iterator2 it2 (m.begin2 ());
+ typename M::iterator2 it2_end (m.end2 ());
+ typename E::iterator2 it2e (e ().begin2 ());
+ typename E::iterator2 it2e_end (e ().end2 ());
+ while (it2 != it2_end && it2e != it2e_end) {
+ difference_type compare = it2.index2 () - it2e.index2 ();
+ if (compare == 0) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+ typename E::iterator1 it1e (it2e.begin ());
+ typename E::iterator1 it1e_end (it2e.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+ typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ if (it1 != it1_end && it1e != it1e_end) {
+ size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
+ while (true) {
+ difference_type compare = it1_index - it1e_index;
+ if (compare == 0) {
+ functor_type::apply (*it1, *it1e);
+ ++ it1, ++ it1e;
+ if (it1 != it1_end && it1e != it1e_end) {
+ it1_index = it1.index1 ();
+ it1e_index = it1e.index1 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index1 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it1e, it1e_end, compare);
+ if (it1e != it1e_end)
+ it1e_index = it1e.index1 ();
+ else
+ break;
+ }
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ increment (it1e, it1e_end);
+ increment (it1, it1_end);
+#endif
+ ++ it2, ++ it2e;
+ } else if (compare < 0) {
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it2.index2 () < it2e.index2 ()) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ increment (it1, it1_end);
+ ++ it2;
+ }
+#else
+ increment (it2, it2_end, - compare);
+#endif
+ } else if (compare > 0) {
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it2e.index2 () < it2.index2 ()) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::iterator1 it1e (it2e.begin ());
+ typename E::iterator1 it1e_end (it2e.end ());
+#else
+ typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ increment (it1e, it1e_end);
+ ++ it2e;
+ }
+#else
+ increment (it2e, it2e_end, compare);
+#endif
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ while (it2e != it2e_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename E::iterator1 it1e (it2e.begin ());
+ typename E::iterator1 it1e_end (it2e.end ());
+#else
+ typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
+ typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
+#endif
+ increment (it1e, it1e_end);
+ ++ it2e;
+ }
+ while (it2 != it2_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename M::iterator1 it1 (it2.begin ());
+ typename M::iterator1 it1_end (it2.end ());
+#else
+ typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
+ typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
+#endif
+ increment (it1, it1_end);
+ ++ it2;
+ }
+#endif
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class M, class E>
+ BOOST_UBLAS_INLINE
+ void matrix_swap (M &m, matrix_expression<E> &e) {
+ typedef typename matrix_swap_traits<typename M::storage_category,
+ typename E::const_iterator1::iterator_category,
+ typename E::const_iterator2::iterator_category>::storage_category storage_category;
+ // give preference to matrix M's orientation if known
+ typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
+ typename E::orientation_category ,
+ typename M::orientation_category >::type orientation_category;
+ typedef basic_full<typename M::size_type> unrestricted;
+ matrix_swap<F, unrestricted> (m, e, storage_category (), orientation_category ());
+ }
+ template<template <class T1, class T2> class F, class R, class M, class E>
+ BOOST_UBLAS_INLINE
+ void matrix_swap (M &m, matrix_expression<E> &e) {
+ typedef R conformant_restrict_type;
+ typedef typename matrix_swap_traits<typename M::storage_category,
+ typename E::const_iterator1::iterator_category,
+ typename E::const_iterator2::iterator_category>::storage_category storage_category;
+ // give preference to matrix M's orientation if known
+ typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
+ typename E::orientation_category ,
+ typename M::orientation_category >::type orientation_category;
+ matrix_swap<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2002-2003
+// Toon Knapen, Kresimir Fresl, Joerg Walter
+//
+// 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)
+//
+//
+
+#ifndef _BOOST_UBLAS_RAW_
+#define _BOOST_UBLAS_RAW_
+
+namespace boost { namespace numeric { namespace ublas { namespace raw {
+
+ // We need data_const() mostly due to MSVC 6.0.
+ // But how shall we write portable code otherwise?
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int size( const V &v ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int size( const vector_reference<V> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size1( const M &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size2( const M &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size1( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size2( const matrix_reference<M> &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m, row_major_tag ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m, column_major_tag ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const matrix_reference<M> &m ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const V &v ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const vector_slice<V> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride( const matrix_column<M> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const M &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const M &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_reference<M> &m ) ;
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ int stride1( const c_matrix<T, M, N> &m ) ;
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ int stride2( const c_matrix<T, M, N> &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_slice<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_slice<M> &m ) ;
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::const_pointer data( const MV &mv ) ;
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::const_pointer data_const( const MV &mv ) ;
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::pointer data( MV &mv ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_reference<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data_const( const vector_reference<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_reference<V> &v ) ;
+
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer data( const c_vector<T, N> &v ) ;
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer data_const( const c_vector<T, N> &v ) ;
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::pointer data( c_vector<T, N> &v ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_slice<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data_const( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data_const( const vector_slice<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_slice<V> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data_const( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_reference<M> &m ) ;
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::array_type::const_pointer data( const c_matrix<T, M, N> &m ) ;
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::array_type::const_pointer data_const( const c_matrix<T, M, N> &m ) ;
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::pointer data( c_matrix<T, M, N> &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data( const matrix_column<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data_const( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data_const( const matrix_column<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_column<M> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data( const matrix_slice<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data_const( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer data_const( const matrix_slice<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_slice<M> &m ) ;
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::const_pointer base( const MV &mv ) ;
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::const_pointer base_const( const MV &mv ) ;
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::pointer base( MV &mv ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base( const vector_reference<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base_const( const vector_reference<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_reference<V> &v ) ;
+
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer base( const c_vector<T, N> &v ) ;
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer base_const( const c_vector<T, N> &v ) ;
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::pointer base( c_vector<T, N> &v ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base( const vector_slice<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base_const( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer base_const( const vector_slice<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_slice<V> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base_const( const matrix_reference<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_reference<M> &m ) ;
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::array_type::const_pointer base( const c_matrix<T, M, N> &m ) ;
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::array_type::const_pointer base_const( const c_matrix<T, M, N> &m ) ;
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::pointer base( c_matrix<T, M, N> &m ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base( const matrix_column<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base_const( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base_const( const matrix_column<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_column<M> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base( const matrix_slice<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base_const( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::array_type::const_pointer base_const( const matrix_slice<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_slice<M> &m ) ;
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::size_type start( const MV &mv ) ;
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::size_type start( const vector_range<V> &v ) ;
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::size_type start( const vector_slice<V> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_row<M> &v ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_column<M> &v ) ;
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_range<M> &m ) ;
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_slice<M> &m ) ;
+
+
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int size( const V &v ) {
+ return v.size() ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int size( const vector_reference<V> &v ) {
+ return size( v ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size1( const M &m ) {
+ return m.size1() ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size2( const M &m ) {
+ return m.size2() ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size1( const matrix_reference<M> &m ) {
+ return size1( m.expression() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int size2( const matrix_reference<M> &m ) {
+ return size2( m.expression() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m, row_major_tag ) {
+ return m.size2() ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m, column_major_tag ) {
+ return m.size1() ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const M &m ) {
+ return leading_dimension( m, typename M::orientation_category() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int leading_dimension( const matrix_reference<M> &m ) {
+ return leading_dimension( m.expression() ) ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const V &v ) {
+ return 1 ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const vector_range<V> &v ) {
+ return stride( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ int stride( const vector_slice<V> &v ) {
+ return v.stride() * stride( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride( const matrix_row<M> &v ) {
+ return stride2( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride( const matrix_column<M> &v ) {
+ return stride1( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const M &m ) {
+ typedef typename M::functor_type functor_type;
+ return functor_type::one1( m.size1(), m.size2() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const M &m ) {
+ typedef typename M::functor_type functor_type;
+ return functor_type::one2( m.size1(), m.size2() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_reference<M> &m ) {
+ return stride1( m.expression() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_reference<M> &m ) {
+ return stride2( m.expression() ) ;
+ }
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ int stride1( const c_matrix<T, M, N> &m ) {
+ return N ;
+ }
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ int stride2( const c_matrix<T, M, N> &m ) {
+ return 1 ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_range<M> &m ) {
+ return stride1( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride1( const matrix_slice<M> &m ) {
+ return m.stride1() * stride1( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_range<M> &m ) {
+ return stride2( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ int stride2( const matrix_slice<M> &m ) {
+ return m.stride2() * stride2( m.data() ) ;
+ }
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::array_type::const_pointer data( const MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::array_type::const_pointer data_const( const MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::pointer data( MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_reference<V> &v ) {
+ return data( v.expression () ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data_const( const vector_reference<V> &v ) {
+ return data_const( v.expression () ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_reference<V> &v ) {
+ return data( v.expression () ) ;
+ }
+
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer data( const c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::array_type::const_pointer data_const( const c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::pointer data( c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_range<V> &v ) {
+ return data( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data( const vector_slice<V> &v ) {
+ return data( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::array_type::const_pointer data_const( const vector_range<V> &v ) {
+ return data_const( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer data_const( const vector_slice<V> &v ) {
+ return data_const( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_range<V> &v ) {
+ return data( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer data( vector_slice<V> &v ) {
+ return data( v.data() ) + v.start() * stride (v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data( const matrix_reference<M> &m ) {
+ return data( m.expression () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data_const( const matrix_reference<M> &m ) {
+ return data_const( m.expression () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_reference<M> &m ) {
+ return data( m.expression () ) ;
+ }
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::const_pointer data( const c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::const_pointer data_const( const c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::pointer data( c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data( const matrix_row<M> &v ) {
+ return data( v.data() ) + v.index() * stride1( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data( const matrix_column<M> &v ) {
+ return data( v.data() ) + v.index() * stride2( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data_const( const matrix_row<M> &v ) {
+ return data_const( v.data() ) + v.index() * stride1( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data_const( const matrix_column<M> &v ) {
+ return data_const( v.data() ) + v.index() * stride2( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_row<M> &v ) {
+ return data( v.data() ) + v.index() * stride1( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_column<M> &v ) {
+ return data( v.data() ) + v.index() * stride2( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data( const matrix_range<M> &m ) {
+ return data( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data( const matrix_slice<M> &m ) {
+ return data( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data_const( const matrix_range<M> &m ) {
+ return data_const( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer data_const( const matrix_slice<M> &m ) {
+ return data_const( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_range<M> &m ) {
+ return data( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer data( matrix_slice<M> &m ) {
+ return data( m.data() ) + m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::const_pointer base( const MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::const_pointer base_const( const MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::array_type::pointer base( MV &mv ) {
+ return &mv.data().begin()[0] ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base( const vector_reference<V> &v ) {
+ return base( v.expression () ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base_const( const vector_reference<V> &v ) {
+ return base_const( v.expression () ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_reference<V> &v ) {
+ return base( v.expression () ) ;
+ }
+
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::const_pointer base( const c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::array_type::const_pointer base_const( const c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+ template < typename T, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_vector<T, N>::pointer base( c_vector<T, N> &v ) {
+ return v.data() ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base( const vector_range<V> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base( const vector_slice<V> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base_const( const vector_range<V> &v ) {
+ return base_const( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::const_pointer base_const( const vector_slice<V> &v ) {
+ return base_const( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_range<V> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::array_type::pointer base( vector_slice<V> &v ) {
+ return base( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base( const matrix_reference<M> &m ) {
+ return base( m.expression () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base_const( const matrix_reference<M> &m ) {
+ return base_const( m.expression () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_reference<M> &m ) {
+ return base( m.expression () ) ;
+ }
+
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::const_pointer base( const c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::array_type::const_pointer base_const( const c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+ template < typename T, std::size_t M, std::size_t N >
+ BOOST_UBLAS_INLINE
+ typename c_matrix<T, M, N>::pointer base( c_matrix<T, M, N> &m ) {
+ return m.data() ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base( const matrix_row<M> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base( const matrix_column<M> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base_const( const matrix_row<M> &v ) {
+ return base_const( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base_const( const matrix_column<M> &v ) {
+ return base_const( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_row<M> &v ) {
+ return base( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_column<M> &v ) {
+ return base( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base( const matrix_range<M> &m ) {
+ return base( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base( const matrix_slice<M> &m ) {
+ return base( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base_const( const matrix_range<M> &m ) {
+ return base_const( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::const_pointer base_const( const matrix_slice<M> &m ) {
+ return base_const( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_range<M> &m ) {
+ return base( m.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::array_type::pointer base( matrix_slice<M> &m ) {
+ return base( m.data() ) ;
+ }
+
+ template < typename MV >
+ BOOST_UBLAS_INLINE
+ typename MV::size_type start( const MV &mv ) {
+ return 0 ;
+ }
+
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::size_type start( const vector_range<V> &v ) {
+ return v.start() * stride (v.data() ) ;
+ }
+ template < typename V >
+ BOOST_UBLAS_INLINE
+ typename V::size_type start( const vector_slice<V> &v ) {
+ return v.start() * stride (v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_row<M> &v ) {
+ return v.index() * stride1( v.data() ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_column<M> &v ) {
+ return v.index() * stride2( v.data() ) ;
+ }
+
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_range<M> &m ) {
+ return m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+ template < typename M >
+ BOOST_UBLAS_INLINE
+ typename M::size_type start( const matrix_slice<M> &m ) {
+ return m.start1() * stride1( m.data () ) + m.start2() * stride2( m.data () ) ;
+ }
+
+}}}}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2001-2003 Joel de Guzman
+ *
+ * Use, modification and distribution is subject to 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)
+ */
+#ifndef _BOOST_UBLAS_NUMERICTYPE_DEDUCTION_
+#define _BOOST_UBLAS_NUMERICTYPE_DEDUCTION_
+
+// See original in boost-sandbox/boost/utility/type_deduction.hpp for comments
+
+#include <boost/mpl/vector/vector20.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+struct error_cant_deduce_type {};
+
+ namespace type_deduction_detail
+ {
+ typedef char(&bool_value_type)[1];
+ typedef char(&float_value_type)[2];
+ typedef char(&double_value_type)[3];
+ typedef char(&long_double_value_type)[4];
+ typedef char(&char_value_type)[5];
+ typedef char(&schar_value_type)[6];
+ typedef char(&uchar_value_type)[7];
+ typedef char(&short_value_type)[8];
+ typedef char(&ushort_value_type)[9];
+ typedef char(&int_value_type)[10];
+ typedef char(&uint_value_type)[11];
+ typedef char(&long_value_type)[12];
+ typedef char(&ulong_value_type)[13];
+
+ typedef char(&x_value_type)[14];
+ typedef char(&y_value_type)[15];
+
+ typedef char(&cant_deduce_type)[16];
+
+ template <typename T, typename PlainT = typename remove_cv<T>::type>
+ struct is_basic
+ : mpl::or_<
+ typename mpl::or_<
+ is_same<PlainT, bool>
+ , is_same<PlainT, float>
+ , is_same<PlainT, double>
+ , is_same<PlainT, long double>
+ > ::type,
+ typename mpl::or_<
+ is_same<PlainT, char>
+ , is_same<PlainT, signed char>
+ , is_same<PlainT, unsigned char>
+ , is_same<PlainT, short>
+ , is_same<PlainT, unsigned short>
+ > ::type,
+ typename mpl::or_<
+ is_same<PlainT, int>
+ , is_same<PlainT, unsigned int>
+ , is_same<PlainT, long>
+ , is_same<PlainT, unsigned long>
+ > ::type
+ > {};
+
+ struct asymmetric;
+
+ template <typename X, typename Y>
+ cant_deduce_type
+ test(...); // The black hole !!!
+
+ template <typename X, typename Y>
+ bool_value_type
+ test(bool const&);
+
+ template <typename X, typename Y>
+ float_value_type
+ test(float const&);
+
+ template <typename X, typename Y>
+ double_value_type
+ test(double const&);
+
+ template <typename X, typename Y>
+ long_double_value_type
+ test(long double const&);
+
+ template <typename X, typename Y>
+ char_value_type
+ test(char const&);
+
+ template <typename X, typename Y>
+ schar_value_type
+ test(signed char const&);
+
+ template <typename X, typename Y>
+ uchar_value_type
+ test(unsigned char const&);
+
+ template <typename X, typename Y>
+ short_value_type
+ test(short const&);
+
+ template <typename X, typename Y>
+ ushort_value_type
+ test(unsigned short const&);
+
+ template <typename X, typename Y>
+ int_value_type
+ test(int const&);
+
+ template <typename X, typename Y>
+ uint_value_type
+ test(unsigned int const&);
+
+ template <typename X, typename Y>
+ long_value_type
+ test(long const&);
+
+ template <typename X, typename Y>
+ ulong_value_type
+ test(unsigned long const&);
+
+ template <typename X, typename Y>
+ typename disable_if<
+ is_basic<X>, x_value_type
+ >::type
+ test(X const&);
+
+ template <typename X, typename Y>
+ typename disable_if<
+ mpl::or_<
+ is_basic<Y>
+ , is_same<Y, asymmetric>
+ , is_same<const X, const Y>
+ >
+ , y_value_type
+ >::type
+ test(Y const&);
+
+ template <typename X, typename Y>
+ struct base_result_of
+ {
+ typedef typename remove_cv<X>::type x_type;
+ typedef typename remove_cv<Y>::type y_type;
+
+ typedef mpl::vector16<
+ mpl::identity<bool>
+ , mpl::identity<float>
+ , mpl::identity<double>
+ , mpl::identity<long double>
+ , mpl::identity<char>
+ , mpl::identity<signed char>
+ , mpl::identity<unsigned char>
+ , mpl::identity<short>
+ , mpl::identity<unsigned short>
+ , mpl::identity<int>
+ , mpl::identity<unsigned int>
+ , mpl::identity<long>
+ , mpl::identity<unsigned long>
+ , mpl::identity<x_type>
+ , mpl::identity<y_type>
+ , mpl::identity<error_cant_deduce_type>
+ >
+ types;
+ };
+
+}}} } // namespace boost::numeric::ublas ::type_deduction_detail
+
+#endif
--- /dev/null
+//
+// 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_TEMPORARY_
+#define _BOOST_UBLAS_TEMPORARY_
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+/// For the creation of temporary vectors in the assignment of proxies
+template <class M>
+struct vector_temporary_traits {
+ typedef typename M::vector_temporary_type type ;
+};
+
+/// For the creation of temporary vectors in the assignment of proxies
+template <class M>
+struct matrix_temporary_traits {
+ typedef typename M::matrix_temporary_type type ;
+};
+
+} } }
+
+#endif
--- /dev/null
+//
+// 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_VECTOR_ASSIGN_
+#define _BOOST_UBLAS_VECTOR_ASSIGN_
+
+#include <boost/numeric/ublas/functional.hpp> // scalar_assign
+// Required for make_conformant storage
+#include <vector>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+namespace detail {
+
+ // Weak equality check - useful to compare equality two arbitary vector expression results.
+ // Since the actual expressions are unknown, we check for and arbitary error bound
+ // on the relative error.
+ // For a linear expression the infinity norm makes sense as we do not know how the elements will be
+ // combined in the expression. False positive results are inevitable for arbirary expressions!
+ template<class E1, class E2, class S>
+ BOOST_UBLAS_INLINE
+ bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
+ return norm_inf (e1 - e2) < epsilon *
+ std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
+ typedef typename type_traits<typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type>::real_type real_type;
+ return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
+ }
+
+
+ // Make sparse proxies conformant
+ template<class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void make_conformant (V &v, const vector_expression<E> &e) {
+ BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+ // FIXME unbounded_array with push_back maybe better
+ std::vector<size_type> index;
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ typename E::const_iterator ite (e ().begin ());
+ typename E::const_iterator ite_end (e ().end ());
+ if (it != it_end && ite != ite_end) {
+ size_type it_index = it.index (), ite_index = ite.index ();
+ while (true) {
+ difference_type compare = it_index - ite_index;
+ if (compare == 0) {
+ ++ it, ++ ite;
+ if (it != it_end && ite != ite_end) {
+ it_index = it.index ();
+ ite_index = ite.index ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it, it_end, - compare);
+ if (it != it_end)
+ it_index = it.index ();
+ else
+ break;
+ } else if (compare > 0) {
+ if (*ite != value_type/*zero*/())
+ index.push_back (ite.index ());
+ ++ ite;
+ if (ite != ite_end)
+ ite_index = ite.index ();
+ else
+ break;
+ }
+ }
+ }
+
+ while (ite != ite_end) {
+ if (*ite != value_type/*zero*/())
+ index.push_back (ite.index ());
+ ++ ite;
+ }
+ for (size_type k = 0; k < index.size (); ++ k)
+ v (index [k]) = value_type/*zero*/();
+ }
+
+}//namespace detail
+
+
+ // Explicitly iterating
+ template<template <class T1, class T2> class F, class V, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_vector_assign_scalar (V &v, const T &t) {
+ typedef F<typename V::iterator::reference, T> functor_type;
+ typedef typename V::difference_type difference_type;
+ difference_type size (v.size ());
+ typename V::iterator it (v.begin ());
+ BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ functor_type::apply (*it, t), ++ it;
+#else
+ DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
+#endif
+ }
+ // Explicitly case
+ template<template <class T1, class T2> class F, class V, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_vector_assign_scalar (V &v, const T &t) {
+ typedef F<typename V::reference, T> functor_type;
+ typedef typename V::size_type size_type;
+ size_type size (v.size ());
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type i = 0; i < size; ++ i)
+ functor_type::apply (v (i), t);
+#else
+ size_type i (0);
+ DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
+#endif
+ }
+
+ // Dense (proxy) case
+ template<template <class T1, class T2> class F, class V, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
+#ifdef BOOST_UBLAS_USE_INDEXING
+ indexing_vector_assign_scalar<F> (v, t);
+#elif BOOST_UBLAS_USE_ITERATING
+ iterating_vector_assign_scalar<F> (v, t);
+#else
+ typedef typename V::size_type size_type;
+ size_type size (v.size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ iterating_vector_assign_scalar<F> (v, t);
+ else
+ indexing_vector_assign_scalar<F> (v, t);
+#endif
+ }
+ // Packed (proxy) case
+ template<template <class T1, class T2> class F, class V, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
+ typedef F<typename V::iterator::reference, T> functor_type;
+ typedef typename V::difference_type difference_type;
+ typename V::iterator it (v.begin ());
+ difference_type size (v.end () - it);
+ while (-- size >= 0)
+ functor_type::apply (*it, t), ++ it;
+ }
+ // Sparse (proxy) case
+ template<template <class T1, class T2> class F, class V, class T>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
+ typedef F<typename V::iterator::reference, T> functor_type;
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ while (it != it_end)
+ functor_type::apply (*it, t), ++ it;
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class V, class T>
+ BOOST_UBLAS_INLINE
+ void vector_assign_scalar (V &v, const T &t) {
+ typedef typename V::storage_category storage_category;
+ vector_assign_scalar<F> (v, t, storage_category ());
+ }
+
+ template<class SC, bool COMPUTED, class RI>
+ struct vector_assign_traits {
+ typedef SC storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
+ typedef packed_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
+ typedef sparse_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
+ typedef sparse_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<bool COMPUTED>
+ struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ // Explicitly iterating
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void iterating_vector_assign (V &v, const vector_expression<E> &e) {
+ typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
+ typedef typename V::difference_type difference_type;
+ difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
+ typename V::iterator it (v.begin ());
+ BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
+ typename E::const_iterator ite (e ().begin ());
+ BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ functor_type::apply (*it, *ite), ++ it, ++ ite;
+#else
+ DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
+#endif
+ }
+ // Explicitly indexing
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void indexing_vector_assign (V &v, const vector_expression<E> &e) {
+ typedef F<typename V::reference, typename E::value_type> functor_type;
+ typedef typename V::size_type size_type;
+ size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type i = 0; i < size; ++ i)
+ functor_type::apply (v (i), e () (i));
+#else
+ size_type i (0);
+ DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
+#endif
+ }
+
+ // Dense (proxy) case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
+#ifdef BOOST_UBLAS_USE_INDEXING
+ indexing_vector_assign<F> (v, e);
+#elif BOOST_UBLAS_USE_ITERATING
+ iterating_vector_assign<F> (v, e);
+#else
+ typedef typename V::size_type size_type;
+ size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ iterating_vector_assign<F> (v, e);
+ else
+ indexing_vector_assign<F> (v, e);
+#endif
+ }
+ // Packed (proxy) case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
+ BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
+ typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v.size ());
+ indexing_vector_assign<scalar_assign> (cv, v);
+ indexing_vector_assign<F> (cv, e);
+#endif
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ typename E::const_iterator ite (e ().begin ());
+ typename E::const_iterator ite_end (e ().end ());
+ difference_type it_size (it_end - it);
+ difference_type ite_size (ite_end - ite);
+ if (it_size > 0 && ite_size > 0) {
+ difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
+ if (size > 0) {
+ ite += size;
+ ite_size -= size;
+ }
+ }
+ if (it_size > 0 && ite_size > 0) {
+ difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
+ if (size > 0) {
+ it_size -= size;
+ if (!functor_type::computed) {
+ while (-- size >= 0) // zeroing
+ functor_type::apply (*it, value_type/*zero*/()), ++ it;
+ } else {
+ it += size;
+ }
+ }
+ }
+ difference_type size ((std::min) (it_size, ite_size));
+ it_size -= size;
+ ite_size -= size;
+ while (-- size >= 0)
+ functor_type::apply (*it, *ite), ++ it, ++ ite;
+ size = it_size;
+ if (!functor_type::computed) {
+ while (-- size >= 0) // zeroing
+ functor_type::apply (*it, value_type/*zero*/()), ++ it;
+ } else {
+ it += size;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
+ external_logic ("external logic or bad condition of inputs"));
+#endif
+ }
+ // Sparse case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
+ BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
+ typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
+ BOOST_STATIC_ASSERT ((!functor_type::computed));
+ typedef typename V::value_type value_type;
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v.size ());
+ indexing_vector_assign<scalar_assign> (cv, v);
+ indexing_vector_assign<F> (cv, e);
+#endif
+ v.clear ();
+ typename E::const_iterator ite (e ().begin ());
+ typename E::const_iterator ite_end (e ().end ());
+ while (ite != ite_end) {
+ value_type t (*ite);
+ if (t != value_type/*zero*/())
+ v.insert_element (ite.index (), t);
+ ++ ite;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
+ external_logic ("external logic or bad condition of inputs"));
+#endif
+ }
+ // Sparse proxy or functional case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
+ BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
+ typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+ typedef typename V::reference reference;
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v.size ());
+ indexing_vector_assign<scalar_assign> (cv, v);
+ indexing_vector_assign<F> (cv, e);
+#endif
+ detail::make_conformant (v, e);
+
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ typename E::const_iterator ite (e ().begin ());
+ typename E::const_iterator ite_end (e ().end ());
+ if (it != it_end && ite != ite_end) {
+ size_type it_index = it.index (), ite_index = ite.index ();
+ while (true) {
+ difference_type compare = it_index - ite_index;
+ if (compare == 0) {
+ functor_type::apply (*it, *ite);
+ ++ it, ++ ite;
+ if (it != it_end && ite != ite_end) {
+ it_index = it.index ();
+ ite_index = ite.index ();
+ } else
+ break;
+ } else if (compare < 0) {
+ if (!functor_type::computed) {
+ functor_type::apply (*it, value_type/*zero*/());
+ ++ it;
+ } else
+ increment (it, it_end, - compare);
+ if (it != it_end)
+ it_index = it.index ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (ite, ite_end, compare);
+ if (ite != ite_end)
+ ite_index = ite.index ();
+ else
+ break;
+ }
+ }
+ }
+
+ if (!functor_type::computed) {
+ while (it != it_end) { // zeroing
+ functor_type::apply (*it, value_type/*zero*/());
+ ++ it;
+ }
+ } else {
+ it = it_end;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ if (! disable_type_check<bool>::value)
+ BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
+ external_logic ("external logic or bad condition of inputs"));
+#endif
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class V, class E>
+ BOOST_UBLAS_INLINE
+ void vector_assign (V &v, const vector_expression<E> &e) {
+ typedef typename vector_assign_traits<typename V::storage_category,
+ F<typename V::reference, typename E::value_type>::computed,
+ typename E::const_iterator::iterator_category>::storage_category storage_category;
+ vector_assign<F> (v, e, storage_category ());
+ }
+
+ template<class SC, class RI>
+ struct vector_swap_traits {
+ typedef SC storage_category;
+ };
+
+ template<>
+ struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ // Dense (proxy) case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
+ typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
+ typedef typename V::difference_type difference_type;
+ difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
+ typename V::iterator it (v.begin ());
+ typename E::iterator ite (e ().begin ());
+ while (-- size >= 0)
+ functor_type::apply (*it, *ite), ++ it, ++ ite;
+ }
+ // Packed (proxy) case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
+ typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
+ typedef typename V::difference_type difference_type;
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ typename E::iterator ite (e ().begin ());
+ typename E::iterator ite_end (e ().end ());
+ difference_type it_size (it_end - it);
+ difference_type ite_size (ite_end - ite);
+ if (it_size > 0 && ite_size > 0) {
+ difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
+ if (size > 0) {
+ ite += size;
+ ite_size -= size;
+ }
+ }
+ if (it_size > 0 && ite_size > 0) {
+ difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
+ if (size > 0)
+ it_size -= size;
+ }
+ difference_type size ((std::min) (it_size, ite_size));
+ it_size -= size;
+ ite_size -= size;
+ while (-- size >= 0)
+ functor_type::apply (*it, *ite), ++ it, ++ ite;
+ }
+ // Sparse proxy case
+ template<template <class T1, class T2> class F, class V, class E>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
+ BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
+ typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+
+ detail::make_conformant (v, e);
+ // FIXME should be a seperate restriction for E
+ detail::make_conformant (e (), v);
+
+ typename V::iterator it (v.begin ());
+ typename V::iterator it_end (v.end ());
+ typename E::iterator ite (e ().begin ());
+ typename E::iterator ite_end (e ().end ());
+ if (it != it_end && ite != ite_end) {
+ size_type it_index = it.index (), ite_index = ite.index ();
+ while (true) {
+ difference_type compare = it_index - ite_index;
+ if (compare == 0) {
+ functor_type::apply (*it, *ite);
+ ++ it, ++ ite;
+ if (it != it_end && ite != ite_end) {
+ it_index = it.index ();
+ ite_index = ite.index ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it, it_end, - compare);
+ if (it != it_end)
+ it_index = it.index ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (ite, ite_end, compare);
+ if (ite != ite_end)
+ ite_index = ite.index ();
+ else
+ break;
+ }
+ }
+ }
+
+#if BOOST_UBLAS_TYPE_CHECK
+ increment (ite, ite_end);
+ increment (it, it_end);
+#endif
+ }
+
+ // Dispatcher
+ template<template <class T1, class T2> class F, class V, class E>
+ BOOST_UBLAS_INLINE
+ void vector_swap (V &v, vector_expression<E> &e) {
+ typedef typename vector_swap_traits<typename V::storage_category,
+ typename E::const_iterator::iterator_category>::storage_category storage_category;
+ vector_swap<F> (v, e, storage_category ());
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2010
+// David Bellot
+//
+// 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)
+//
+// And we acknowledge the support from all contributors.
+
+/** \mainpage BOOST uBLAS: a Linear Algebra Library
+ *
+ * This is the API Reference Documentation.
+ *
+ * For introduction, documentations and tutorial, please refer
+ * to http://www.boost.org/doc/libs/1_44_0/libs/numeric/ublas/doc/index.htm
+ *
+ * \section main_classes Main classes
+ *
+ * \subsection listvector Vectors
+ * - \link #boost::numeric::ublas::vector vector \endlink
+ * - \link #boost::numeric::ublas::bounded_vector bounded_vector \endlink
+ * - \link #boost::numeric::ublas::zero_vector zero_vector \endlink
+ * - \link #boost::numeric::ublas::unit_vector unit_vector \endlink
+ * - \link #boost::numeric::ublas::scalar_vector scalar_vector \endlink
+ * - \link #boost::numeric::ublas::c_vector c_vector \endlink
+ * - \link #boost::numeric::ublas::vector_slice vector_slice \endlink
+ * - \link #boost::numeric::ublas::vector_range vector_range \endlink
+ * - \link #boost::numeric::ublas::vector_indirect vector_indirect \endlink
+ * - \link #boost::numeric::ublas::mapped_vector mapped_vector \endlink
+ * - \link #boost::numeric::ublas::compressed_vector compressed_vector \endlink
+ * - \link #boost::numeric::ublas::coordinate_vector coordinate_vector \endlink
+ * - \link #boost::numeric::ublas::matrix_row matrix_row \endlink
+ * - \link #boost::numeric::ublas::matrix_column matrix_column \endlink
+ *
+ * \subsection listmatrix Matrices
+ * - \link #boost::numeric::ublas::matrix matrix \endlink
+ * - \link #boost::numeric::ublas::banded_matrix banded_matrix \endlink
+ * - \link #boost::numeric::ublas::diagonal_matrix diagonal_matrix \endlink
+ * - \link #boost::numeric::ublas::banded_adaptor banded_adaptor \endlink
+ * - \link #boost::numeric::ublas::diagonal_adaptor diagonal_adaptor \endlink
+ * - \link #boost::numeric::ublas::hermitian_matrix hermitian_matrix \endlink
+ * - \link #boost::numeric::ublas::hermitian_adaptor hermitian_adaptor \endlink
+ * - \link #boost::numeric::ublas::symmetric_matrix symmetric_matrix \endlink
+ * - \link #boost::numeric::ublas::symmetric_adaptor symmetric_adaptor \endlink
+ * - \link #boost::numeric::ublas::triangular_matrix triangular_matrix \endlink
+ * - \link #boost::numeric::ublas::triangular_adaptor triangular_adaptor \endlink
+ * - \link #boost::numeric::ublas::vector_of_vector vector_of_vector \endlink
+ * - \link #boost::numeric::ublas::bounded_matrix bounded_matrix \endlink
+ * - \link #boost::numeric::ublas::zero_matrix zero_matrix \endlink
+ * - \link #boost::numeric::ublas::identity_matrix identity_matrix \endlink
+ * - \link #boost::numeric::ublas::scalar_matrix scalar_matrix \endlink
+ * - \link #boost::numeric::ublas::c_matrix c_matrix \endlink
+ * - \link #boost::numeric::ublas::matrix_vector_range matrix_vector_range \endlink
+ * - \link #boost::numeric::ublas::matrix_vector_slice matrix_vector_slice \endlink
+ * - \link #boost::numeric::ublas::matrix_vector_indirect matrix_vector_indirect \endlink
+ * - \link #boost::numeric::ublas::matrix_range matrix_range \endlink
+ * - \link #boost::numeric::ublas::matrix_slice matrix_slice \endlink
+ * - \link #boost::numeric::ublas::matrix_indirect matrix_indirect \endlink
+ * - \link #boost::numeric::ublas::mapped_matrix mapped_matrix \endlink
+ * - \link #boost::numeric::ublas::mapped_vector_of_mapped_vector mapped_vector_of_mapped_vector \endlink
+ * - \link #boost::numeric::ublas::compressed_matrix compressed_matrix \endlink
+ * - \link #boost::numeric::ublas::coordinate_matrix coordinate_matrix \endlink
+ * - \link #boost::numeric::ublas::generalized_vector_of_vector generalized_vector_of_vector \endlink
+ */
--- /dev/null
+//
+// 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_EXCEPTION_
+#define _BOOST_UBLAS_EXCEPTION_
+
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+#include <stdexcept>
+#else
+#include <cstdlib>
+#endif
+#ifndef BOOST_UBLAS_NO_STD_CERR
+#include <iostream>
+#endif
+
+#include <boost/numeric/ublas/detail/config.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief Exception raised when a division by zero occurs
+ */
+ struct divide_by_zero
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::runtime_error
+ {
+ explicit divide_by_zero (const char *s = "divide by zero") :
+ std::runtime_error (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ divide_by_zero ()
+ {}
+ explicit divide_by_zero (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ /** \brief Expception raised when some interal errors occurs like computations errors, zeros values where you should not have zeros, etc...
+ */
+ struct internal_logic
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::logic_error {
+ explicit internal_logic (const char *s = "internal logic") :
+ std::logic_error (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ internal_logic ()
+ {}
+ explicit internal_logic (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ struct external_logic
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::logic_error {
+ explicit external_logic (const char *s = "external logic") :
+ std::logic_error (s) {}
+ // virtual const char *what () const throw () {
+ // return "exception: external logic";
+ // }
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ external_logic ()
+ {}
+ explicit external_logic (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ struct bad_argument
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::invalid_argument {
+ explicit bad_argument (const char *s = "bad argument") :
+ std::invalid_argument (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ bad_argument ()
+ {}
+ explicit bad_argument (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ /**
+ */
+ struct bad_size
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::domain_error {
+ explicit bad_size (const char *s = "bad size") :
+ std::domain_error (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ bad_size ()
+ {}
+ explicit bad_size (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ struct bad_index
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::out_of_range {
+ explicit bad_index (const char *s = "bad index") :
+ std::out_of_range (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ bad_index ()
+ {}
+ explicit bad_index (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ struct singular
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::runtime_error {
+ explicit singular (const char *s = "singular") :
+ std::runtime_error (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ singular ()
+ {}
+ explicit singular (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+ struct non_real
+#if ! defined (BOOST_NO_EXCEPTIONS) && ! defined (BOOST_UBLAS_NO_EXCEPTIONS)
+ // Inherit from standard exceptions as requested during review.
+ : public std::domain_error {
+ explicit non_real (const char *s = "exception: non real") :
+ std::domain_error (s) {}
+ void raise () {
+ throw *this;
+ }
+#else
+ {
+ non_real ()
+ {}
+ explicit non_real (const char *)
+ {}
+ void raise () {
+ std::abort ();
+ }
+#endif
+ };
+
+#if BOOST_UBLAS_CHECK_ENABLE
+// Macros are equivilent to
+// template<class E>
+// BOOST_UBLAS_INLINE
+// void check (bool expression, const E &e) {
+// if (! expression)
+// e.raise ();
+// }
+// template<class E>
+// BOOST_UBLAS_INLINE
+// void check_ex (bool expression, const char *file, int line, const E &e) {
+// if (! expression)
+// e.raise ();
+// }
+#ifndef BOOST_UBLAS_NO_STD_CERR
+#define BOOST_UBLAS_CHECK_FALSE(e) \
+ std::cerr << "Check failed in file " << __FILE__ << " at line " << __LINE__ << ":" << std::endl; \
+ e.raise ();
+#define BOOST_UBLAS_CHECK(expression, e) \
+ if (! (expression)) { \
+ std::cerr << "Check failed in file " << __FILE__ << " at line " << __LINE__ << ":" << std::endl; \
+ std::cerr << #expression << std::endl; \
+ e.raise (); \
+ }
+#define BOOST_UBLAS_CHECK_EX(expression, file, line, e) \
+ if (! (expression)) { \
+ std::cerr << "Check failed in file " << (file) << " at line " << (line) << ":" << std::endl; \
+ std::cerr << #expression << std::endl; \
+ e.raise (); \
+ }
+#else
+#define BOOST_UBLAS_CHECK_FALSE(e) \
+ e.raise ();
+#define BOOST_UBLAS_CHECK(expression, e) \
+ if (! (expression)) { \
+ e.raise (); \
+ }
+#define BOOST_UBLAS_CHECK_EX(expression, file, line, e) \
+ if (! (expression)) { \
+ e.raise (); \
+ }
+#endif
+#else
+// Macros are equivilent to
+// template<class E>
+// BOOST_UBLAS_INLINE
+// void check (bool expression, const E &e) {}
+// template<class E>
+// BOOST_UBLAS_INLINE
+// void check_ex (bool expression, const char *file, int line, const E &e) {}
+#define BOOST_UBLAS_CHECK_FALSE(e)
+#define BOOST_UBLAS_CHECK(expression, e)
+#define BOOST_UBLAS_CHECK_EX(expression, file, line, e)
+#endif
+
+
+#ifndef BOOST_UBLAS_USE_FAST_SAME
+// Macro is equivilent to
+// template<class T>
+// BOOST_UBLAS_INLINE
+// const T &same_impl (const T &size1, const T &size2) {
+// BOOST_UBLAS_CHECK (size1 == size2, bad_argument ());
+// return (std::min) (size1, size2);
+// }
+// #define BOOST_UBLAS_SAME(size1, size2) same_impl ((size1), (size2))
+ // need two types here because different containers can have
+ // different size_types (especially sparse types)
+ template<class T1, class T2>
+ BOOST_UBLAS_INLINE
+ // Kresimir Fresl and Dan Muller reported problems with COMO.
+ // We better change the signature instead of libcomo ;-)
+ // const T &same_impl_ex (const T &size1, const T &size2, const char *file, int line) {
+ T1 same_impl_ex (const T1 &size1, const T2 &size2, const char *file, int line) {
+ BOOST_UBLAS_CHECK_EX (size1 == size2, file, line, bad_argument ());
+ return (size1 < size2)?(size1):(size2);
+ }
+ template<class T>
+ BOOST_UBLAS_INLINE
+ T same_impl_ex (const T &size1, const T &size2, const char *file, int line) {
+ BOOST_UBLAS_CHECK_EX (size1 == size2, file, line, bad_argument ());
+ return (std::min) (size1, size2);
+ }
+#define BOOST_UBLAS_SAME(size1, size2) same_impl_ex ((size1), (size2), __FILE__, __LINE__)
+#else
+// Macros are equivilent to
+// template<class T>
+// BOOST_UBLAS_INLINE
+// const T &same_impl (const T &size1, const T &size2) {
+// return size1;
+// }
+// #define BOOST_UBLAS_SAME(size1, size2) same_impl ((size1), (size2))
+#define BOOST_UBLAS_SAME(size1, size2) (size1)
+#endif
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2009
+// Gunter Winkler
+//
+// 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)
+//
+//
+
+#ifndef _BOOST_UBLAS_SPARSE_VIEW_
+#define _BOOST_UBLAS_SPARSE_VIEW_
+
+#include <boost/numeric/ublas/matrix_expression.hpp>
+#include <boost/numeric/ublas/detail/matrix_assign.hpp>
+#if BOOST_UBLAS_TYPE_CHECK
+#include <boost/numeric/ublas/matrix.hpp>
+#endif
+
+#include <boost/next_prior.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+ // view a chunk of memory as ublas array
+
+ template < class T >
+ class c_array_view
+ : public storage_array< c_array_view<T> > {
+ private:
+ typedef c_array_view<T> self_type;
+ typedef T * pointer;
+
+ public:
+ // TODO: think about a const pointer
+ typedef const pointer array_type;
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef const T *const_pointer;
+
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ //
+ // typedefs required by vector concept
+ //
+
+ typedef dense_tag storage_category;
+ typedef const vector_reference<const self_type> const_closure_type;
+
+ c_array_view(size_type size, array_type data) :
+ size_(size), data_(data)
+ {}
+
+ ~c_array_view()
+ {}
+
+ //
+ // immutable methods of container concept
+ //
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_ + size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ };
+
+
+ /** \brief Present existing arrays as compressed array based
+ * sparse matrix.
+ * This class provides CRS / CCS storage layout.
+ *
+ * see also http://www.netlib.org/utk/papers/templates/node90.html
+ *
+ * \param L layout type, either row_major or column_major
+ * \param IB index base, use 0 for C indexing and 1 for
+ * FORTRAN indexing of the internal index arrays. This
+ * does not affect the operator()(int,int) where the first
+ * row/column has always index 0.
+ * \param IA index array type, e.g., int[]
+ * \param TA value array type, e.g., double[]
+ */
+ template<class L, std::size_t IB, class IA, class JA, class TA>
+ class compressed_matrix_view:
+ public matrix_expression<compressed_matrix_view<L, IB, IA, JA, TA> > {
+
+ public:
+ typedef typename vector_view_traits<TA>::value_type value_type;
+
+ private:
+ typedef value_type &true_reference;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef L layout_type;
+ typedef compressed_matrix_view<L, IB, IA, JA, TA> self_type;
+
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ // ISSUE require type consistency check
+ // is_convertable (IA::size_type, TA::size_type)
+ typedef typename boost::remove_cv<typename vector_view_traits<JA>::value_type>::type index_type;
+ // for compatibility, should be removed some day ...
+ typedef index_type size_type;
+ // size_type for the data arrays.
+ typedef typename vector_view_traits<JA>::size_type array_size_type;
+ typedef typename vector_view_traits<JA>::difference_type difference_type;
+ typedef const value_type & const_reference;
+
+ // do NOT define reference type, because class is read only
+ // typedef value_type & reference;
+
+ typedef IA rowptr_array_type;
+ typedef JA index_array_type;
+ typedef TA value_array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+
+ // FIXME: define a corresponding temporary type
+ // typedef compressed_vector<T, IB, IA, TA> vector_temporary_type;
+
+ // FIXME: define a corresponding temporary type
+ // typedef self_type matrix_temporary_type;
+
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ //
+ // private types for internal use
+ //
+
+ private:
+ typedef typename vector_view_traits<index_array_type>::const_iterator const_subiterator_type;
+
+ //
+ // Construction and destruction
+ //
+ private:
+ /// private default constructor because data must be filled by caller
+ BOOST_UBLAS_INLINE
+ compressed_matrix_view () { }
+
+ public:
+ BOOST_UBLAS_INLINE
+ compressed_matrix_view (index_type n_rows, index_type n_cols, array_size_type nnz
+ , const rowptr_array_type & iptr
+ , const index_array_type & jptr
+ , const value_array_type & values):
+ matrix_expression<self_type> (),
+ size1_ (n_rows), size2_ (n_cols),
+ nnz_ (nnz),
+ index1_data_ (iptr),
+ index2_data_ (jptr),
+ value_data_ (values) {
+ storage_invariants ();
+ }
+
+ 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_)
+ {}
+
+ //
+ // implement immutable iterator types
+ //
+
+ class const_iterator1 {};
+ class const_iterator2 {};
+
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ //
+ // implement all read only methods for the matrix expression concept
+ //
+
+ //! return the number of rows
+ index_type size1() const {
+ return size1_;
+ }
+
+ //! return the number of columns
+ index_type size2() const {
+ return size2_;
+ }
+
+ //! return value at position (i,j)
+ value_type operator()(index_type i, index_type j) const {
+ const_pointer p = find_element(i,j);
+ if (!p) {
+ return zero_;
+ } else {
+ return *p;
+ }
+ }
+
+
+ private:
+ //
+ // private helper functions
+ //
+
+ const_pointer find_element (index_type i, index_type j) const {
+ index_type element1 (layout_type::index_M (i, j));
+ index_type element2 (layout_type::index_m (i, j));
+
+ const array_size_type itv = zero_based( index1_data_[element1] );
+ const array_size_type itv_next = zero_based( index1_data_[element1+1] );
+
+ const_subiterator_type it_start = boost::next(vector_view_traits<index_array_type>::begin(index2_data_),itv);
+ const_subiterator_type it_end = boost::next(vector_view_traits<index_array_type>::begin(index2_data_),itv_next);
+ const_subiterator_type it = find_index_in_row(it_start, it_end, element2) ;
+
+ if (it == it_end || *it != k_based (element2))
+ return 0;
+ return &value_data_ [it - vector_view_traits<index_array_type>::begin(index2_data_)];
+ }
+
+ const_subiterator_type find_index_in_row(const_subiterator_type it_start
+ , const_subiterator_type it_end
+ , index_type index) const {
+ return std::lower_bound( it_start
+ , it_end
+ , k_based (index) );
+ }
+
+
+ private:
+ void storage_invariants () const {
+ BOOST_UBLAS_CHECK (index1_data_ [layout_type::size_M (size1_, size2_)] == k_based (nnz_), external_logic ());
+ }
+
+ index_type size1_;
+ index_type size2_;
+
+ array_size_type nnz_;
+
+ const rowptr_array_type & index1_data_;
+ const index_array_type & index2_data_;
+ const value_array_type & value_data_;
+
+ static const value_type zero_;
+
+ BOOST_UBLAS_INLINE
+ static index_type zero_based (index_type k_based_index) {
+ return k_based_index - IB;
+ }
+ BOOST_UBLAS_INLINE
+ static index_type k_based (index_type zero_based_index) {
+ return zero_based_index + IB;
+ }
+
+ friend class iterator1;
+ friend class iterator2;
+ friend class const_iterator1;
+ friend class const_iterator2;
+ };
+
+ template<class L, std::size_t IB, class IA, class JA, class TA >
+ const typename compressed_matrix_view<L,IB,IA,JA,TA>::value_type
+ compressed_matrix_view<L,IB,IA,JA,TA>::zero_ = value_type/*zero*/();
+
+
+ template<class L, std::size_t IB, class IA, class JA, class TA >
+ compressed_matrix_view<L,IB,IA,JA,TA>
+ make_compressed_matrix_view(typename vector_view_traits<JA>::value_type n_rows
+ , typename vector_view_traits<JA>::value_type n_cols
+ , typename vector_view_traits<JA>::size_type nnz
+ , const IA & ia
+ , const JA & ja
+ , const TA & ta) {
+
+ return compressed_matrix_view<L,IB,IA,JA,TA>(n_rows, n_cols, nnz, ia, ja, ta);
+
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch. David Bellot
+//
+// 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_EXPRESSION_TYPE_
+#define _BOOST_UBLAS_EXPRESSION_TYPE_
+
+#include <boost/numeric/ublas/exception.hpp>
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/numeric/ublas/functional.hpp>
+
+
+// Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick
+ *
+ * This is a NonAssignable class
+ * Directly implement nonassignable - simplifes debugging call trace!
+ *
+ * \tparam E an expression type
+ */
+ template<class E>
+ class ublas_expression {
+ public:
+ typedef E expression_type;
+ /* E can be an incomplete type - to define the following we would need more template arguments
+ typedef typename E::type_category type_category;
+ typedef typename E::value_type value_type;
+ */
+
+ protected:
+ ublas_expression () {}
+ ~ublas_expression () {}
+ private:
+ const ublas_expression& operator= (const ublas_expression &);
+ };
+
+
+ /** \brief Base class for Scalar Expression models
+ *
+ * It does not model the Scalar Expression concept but all derived types should.
+ * The class defines a common base type and some common interface for all statically
+ * derived Scalar Expression classes.
+ *
+ * We implement the casts to the statically derived type.
+ *
+ * \tparam E an expression type
+ */
+ template<class E>
+ class scalar_expression:
+ public ublas_expression<E> {
+ public:
+ typedef E expression_type;
+ typedef scalar_tag type_category;
+
+ BOOST_UBLAS_INLINE
+ const expression_type &operator () () const {
+ return *static_cast<const expression_type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ expression_type &operator () () {
+ return *static_cast<expression_type *> (this);
+ }
+ };
+
+ template<class T>
+ class scalar_reference:
+ public scalar_expression<scalar_reference<T> > {
+
+ typedef scalar_reference<T> self_type;
+ public:
+ typedef T value_type;
+ typedef const value_type &const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<T>,
+ const_reference,
+ value_type &>::type reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit scalar_reference (reference t):
+ t_ (t) {}
+
+ // Conversion
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return t_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ scalar_reference &operator = (const scalar_reference &s) {
+ t_ = s.t_;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ scalar_reference &operator = (const scalar_expression<AE> &ae) {
+ t_ = ae;
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const scalar_reference &sr) const {
+ return &t_ == &sr.t_;
+ }
+
+ private:
+ reference t_;
+ };
+
+ template<class T>
+ class scalar_value:
+ public scalar_expression<scalar_value<T> > {
+
+ typedef scalar_value<T> self_type;
+ public:
+ typedef T value_type;
+ typedef const value_type &const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<T>,
+ const_reference,
+ value_type &>::type reference;
+ typedef const scalar_reference<const self_type> const_closure_type;
+ typedef scalar_reference<self_type> closure_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ scalar_value ():
+ t_ () {}
+ BOOST_UBLAS_INLINE
+ scalar_value (const value_type &t):
+ t_ (t) {}
+
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return t_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ scalar_value &operator = (const scalar_value &s) {
+ t_ = s.t_;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ scalar_value &operator = (const scalar_expression<AE> &ae) {
+ t_ = ae;
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const scalar_value &sv) const {
+ return this == &sv; // self closing on instances value
+ }
+
+ private:
+ value_type t_;
+ };
+
+
+ /** \brief Base class for Vector Expression models
+ *
+ * it does not model the Vector Expression concept but all derived types should.
+ * The class defines a common base type and some common interface for all
+ * statically derived Vector Expression classes.
+ * We implement the casts to the statically derived type.
+ */
+ template<class E>
+ class vector_expression:
+ public ublas_expression<E> {
+ public:
+ static const unsigned complexity = 0;
+ typedef E expression_type;
+ typedef vector_tag type_category;
+ /* E can be an incomplete type - to define the following we would need more template arguments
+ typedef typename E::size_type size_type;
+ */
+
+ BOOST_UBLAS_INLINE
+ const expression_type &operator () () const {
+ return *static_cast<const expression_type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ expression_type &operator () () {
+ return *static_cast<expression_type *> (this);
+ }
+
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ private:
+ // projection types
+ typedef vector_range<E> vector_range_type;
+ typedef vector_range<const E> const_vector_range_type;
+ typedef vector_slice<E> vector_slice_type;
+ typedef vector_slice<const E> const_vector_slice_type;
+ // vector_indirect_type will depend on the A template parameter
+ typedef basic_range<> default_range; // required to avoid range/slice name confusion
+ typedef basic_slice<> default_slice;
+ public:
+ BOOST_UBLAS_INLINE
+ const_vector_range_type operator () (const default_range &r) const {
+ return const_vector_range_type (operator () (), r);
+ }
+ BOOST_UBLAS_INLINE
+ vector_range_type operator () (const default_range &r) {
+ return vector_range_type (operator () (), r);
+ }
+ BOOST_UBLAS_INLINE
+ const_vector_slice_type operator () (const default_slice &s) const {
+ return const_vector_slice_type (operator () (), s);
+ }
+ BOOST_UBLAS_INLINE
+ vector_slice_type operator () (const default_slice &s) {
+ return vector_slice_type (operator () (), s);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const {
+ return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
+ return vector_indirect<E, indirect_array<A> > (operator () (), ia);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_vector_range_type project (const default_range &r) const {
+ return const_vector_range_type (operator () (), r);
+ }
+ BOOST_UBLAS_INLINE
+ vector_range_type project (const default_range &r) {
+ return vector_range_type (operator () (), r);
+ }
+ BOOST_UBLAS_INLINE
+ const_vector_slice_type project (const default_slice &s) const {
+ return const_vector_slice_type (operator () (), s);
+ }
+ BOOST_UBLAS_INLINE
+ vector_slice_type project (const default_slice &s) {
+ return vector_slice_type (operator () (), s);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const {
+ return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
+ return vector_indirect<E, indirect_array<A> > (operator () (), ia);
+ }
+#endif
+ };
+
+ /** \brief Base class for Vector container models
+ *
+ * it does not model the Vector concept but all derived types should.
+ * The class defines a common base type and some common interface for all
+ * statically derived Vector classes
+ * We implement the casts to the statically derived type.
+ */
+ template<class C>
+ class vector_container:
+ public vector_expression<C> {
+ public:
+ static const unsigned complexity = 0;
+ typedef C container_type;
+ typedef vector_tag type_category;
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return *static_cast<const container_type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ container_type &operator () () {
+ return *static_cast<container_type *> (this);
+ }
+
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<C>::operator ();
+#endif
+ };
+
+
+ /** \brief Base class for Matrix Expression models
+ *
+ * it does not model the Matrix Expression concept but all derived types should.
+ * The class defines a common base type and some common interface for all
+ * statically derived Matrix Expression classes
+ * We implement the casts to the statically derived type.
+ */
+ template<class E>
+ class matrix_expression:
+ public ublas_expression<E> {
+ private:
+ typedef matrix_expression<E> self_type;
+ public:
+ static const unsigned complexity = 0;
+ typedef E expression_type;
+ typedef matrix_tag type_category;
+ /* E can be an incomplete type - to define the following we would need more template arguments
+ typedef typename E::size_type size_type;
+ */
+
+ BOOST_UBLAS_INLINE
+ const expression_type &operator () () const {
+ return *static_cast<const expression_type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ expression_type &operator () () {
+ return *static_cast<expression_type *> (this);
+ }
+
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ private:
+ // projection types
+ typedef vector_range<E> vector_range_type;
+ typedef const vector_range<const E> const_vector_range_type;
+ typedef vector_slice<E> vector_slice_type;
+ typedef const vector_slice<const E> const_vector_slice_type;
+ typedef matrix_row<E> matrix_row_type;
+ typedef const matrix_row<const E> const_matrix_row_type;
+ typedef matrix_column<E> matrix_column_type;
+ typedef const matrix_column<const E> const_matrix_column_type;
+ typedef matrix_range<E> matrix_range_type;
+ typedef const matrix_range<const E> const_matrix_range_type;
+ typedef matrix_slice<E> matrix_slice_type;
+ typedef const matrix_slice<const E> const_matrix_slice_type;
+ // matrix_indirect_type will depend on the A template parameter
+ typedef basic_range<> default_range; // required to avoid range/slice name confusion
+ typedef basic_slice<> default_slice;
+
+ public:
+ BOOST_UBLAS_INLINE
+ const_matrix_row_type operator [] (std::size_t i) const {
+ return const_matrix_row_type (operator () (), i);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_row_type operator [] (std::size_t i) {
+ return matrix_row_type (operator () (), i);
+ }
+ BOOST_UBLAS_INLINE
+ const_matrix_row_type row (std::size_t i) const {
+ return const_matrix_row_type (operator () (), i);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_row_type row (std::size_t i) {
+ return matrix_row_type (operator () (), i);
+ }
+ BOOST_UBLAS_INLINE
+ const_matrix_column_type column (std::size_t j) const {
+ return const_matrix_column_type (operator () (), j);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_column_type column (std::size_t j) {
+ return matrix_column_type (operator () (), j);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
+ return const_matrix_range_type (operator () (), r1, r2);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_range_type operator () (const default_range &r1, const default_range &r2) {
+ return matrix_range_type (operator () (), r1, r2);
+ }
+ BOOST_UBLAS_INLINE
+ const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
+ return const_matrix_slice_type (operator () (), s1, s2);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
+ return matrix_slice_type (operator () (), s1, s2);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
+ return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
+ return const_matrix_range_type (operator () (), r1, r2);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_range_type project (const default_range &r1, const default_range &r2) {
+ return matrix_range_type (operator () (), r1, r2);
+ }
+ BOOST_UBLAS_INLINE
+ const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
+ return const_matrix_slice_type (operator () (), s1, s2);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
+ return matrix_slice_type (operator () (), s1, s2);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
+ return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
+ }
+ template<class A>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
+ }
+#endif
+ };
+
+#ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ struct iterator1_tag {};
+ struct iterator2_tag {};
+
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
+ return it ().find2 (1, it.index1 (), 0);
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_iterator_type end (const I &it, iterator1_tag) {
+ return it ().find2 (1, it.index1 (), it ().size2 ());
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) {
+ return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ()));
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) {
+ return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ()));
+ }
+
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
+ return it ().find1 (1, 0, it.index2 ());
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_iterator_type end (const I &it, iterator2_tag) {
+ return it ().find1 (1, it ().size1 (), it.index2 ());
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) {
+ return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ()));
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) {
+ return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ()));
+ }
+#endif
+
+ /** \brief Base class for Matrix container models
+ *
+ * it does not model the Matrix concept but all derived types should.
+ * The class defines a common base type and some common interface for all
+ * statically derived Matrix classes
+ * We implement the casts to the statically derived type.
+ */
+ template<class C>
+ class matrix_container:
+ public matrix_expression<C> {
+ public:
+ static const unsigned complexity = 0;
+ typedef C container_type;
+ typedef matrix_tag type_category;
+
+ BOOST_UBLAS_INLINE
+ const container_type &operator () () const {
+ return *static_cast<const container_type *> (this);
+ }
+ BOOST_UBLAS_INLINE
+ container_type &operator () () {
+ return *static_cast<container_type *> (this);
+ }
+
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<C>::operator ();
+#endif
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2009
+// Joerg Walter, Mathias Koch, Gunter Winkler
+//
+// 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_FUNCTIONAL_
+#define _BOOST_UBLAS_FUNCTIONAL_
+
+#include <functional>
+
+#include <boost/numeric/ublas/traits.hpp>
+#ifdef BOOST_UBLAS_USE_DUFF_DEVICE
+#include <boost/numeric/ublas/detail/duff.hpp>
+#endif
+#ifdef BOOST_UBLAS_USE_SIMD
+#include <boost/numeric/ublas/detail/raw.hpp>
+#else
+namespace boost { namespace numeric { namespace ublas { namespace raw {
+}}}}
+#endif
+#ifdef BOOST_UBLAS_HAVE_BINDINGS
+#include <boost/numeric/bindings/traits/std_vector.hpp>
+#include <boost/numeric/bindings/traits/ublas_vector.hpp>
+#include <boost/numeric/bindings/traits/ublas_matrix.hpp>
+#include <boost/numeric/bindings/atlas/cblas.hpp>
+#endif
+
+#include <boost/numeric/ublas/detail/definitions.hpp>
+
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ // Scalar functors
+
+ // Unary
+ template<class T>
+ struct scalar_unary_functor {
+ typedef T value_type;
+ typedef typename type_traits<T>::const_reference argument_type;
+ typedef typename type_traits<T>::value_type result_type;
+ };
+
+ template<class T>
+ struct scalar_identity:
+ public scalar_unary_functor<T> {
+ typedef typename scalar_unary_functor<T>::argument_type argument_type;
+ typedef typename scalar_unary_functor<T>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument_type t) {
+ return t;
+ }
+ };
+ template<class T>
+ struct scalar_negate:
+ public scalar_unary_functor<T> {
+ typedef typename scalar_unary_functor<T>::argument_type argument_type;
+ typedef typename scalar_unary_functor<T>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument_type t) {
+ return - t;
+ }
+ };
+ template<class T>
+ struct scalar_conj:
+ public scalar_unary_functor<T> {
+ typedef typename scalar_unary_functor<T>::value_type value_type;
+ typedef typename scalar_unary_functor<T>::argument_type argument_type;
+ typedef typename scalar_unary_functor<T>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument_type t) {
+ return type_traits<value_type>::conj (t);
+ }
+ };
+
+ // Unary returning real
+ template<class T>
+ struct scalar_real_unary_functor {
+ typedef T value_type;
+ typedef typename type_traits<T>::const_reference argument_type;
+ typedef typename type_traits<T>::real_type result_type;
+ };
+
+ template<class T>
+ struct scalar_real:
+ public scalar_real_unary_functor<T> {
+ typedef typename scalar_real_unary_functor<T>::value_type value_type;
+ typedef typename scalar_real_unary_functor<T>::argument_type argument_type;
+ typedef typename scalar_real_unary_functor<T>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument_type t) {
+ return type_traits<value_type>::real (t);
+ }
+ };
+ template<class T>
+ struct scalar_imag:
+ public scalar_real_unary_functor<T> {
+ typedef typename scalar_real_unary_functor<T>::value_type value_type;
+ typedef typename scalar_real_unary_functor<T>::argument_type argument_type;
+ typedef typename scalar_real_unary_functor<T>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument_type t) {
+ return type_traits<value_type>::imag (t);
+ }
+ };
+
+ // Binary
+ template<class T1, class T2>
+ struct scalar_binary_functor {
+ typedef typename type_traits<T1>::const_reference argument1_type;
+ typedef typename type_traits<T2>::const_reference argument2_type;
+ typedef typename promote_traits<T1, T2>::promote_type result_type;
+ };
+
+ template<class T1, class T2>
+ struct scalar_plus:
+ public scalar_binary_functor<T1, T2> {
+ typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
+ typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument1_type t1, argument2_type t2) {
+ return t1 + t2;
+ }
+ };
+ template<class T1, class T2>
+ struct scalar_minus:
+ public scalar_binary_functor<T1, T2> {
+ typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
+ typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument1_type t1, argument2_type t2) {
+ return t1 - t2;
+ }
+ };
+ template<class T1, class T2>
+ struct scalar_multiplies:
+ public scalar_binary_functor<T1, T2> {
+ typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
+ typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument1_type t1, argument2_type t2) {
+ return t1 * t2;
+ }
+ };
+ template<class T1, class T2>
+ struct scalar_divides:
+ public scalar_binary_functor<T1, T2> {
+ typedef typename scalar_binary_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_functor<T1, T2>::argument2_type argument2_type;
+ typedef typename scalar_binary_functor<T1, T2>::result_type result_type;
+
+ static BOOST_UBLAS_INLINE
+ result_type apply (argument1_type t1, argument2_type t2) {
+ return t1 / t2;
+ }
+ };
+
+ template<class T1, class T2>
+ struct scalar_binary_assign_functor {
+ // ISSUE Remove reference to avoid reference to reference problems
+ typedef typename type_traits<typename boost::remove_reference<T1>::type>::reference argument1_type;
+ typedef typename type_traits<T2>::const_reference argument2_type;
+ };
+
+ struct assign_tag {};
+ struct computed_assign_tag {};
+
+ template<class T1, class T2>
+ struct scalar_assign:
+ public scalar_binary_assign_functor<T1, T2> {
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ static const bool computed ;
+#else
+ static const bool computed = false ;
+#endif
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ t1 = t2;
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_assign<U1, U2> other;
+ };
+ };
+
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ template<class T1, class T2>
+ const bool scalar_assign<T1,T2>::computed = false;
+#endif
+
+ template<class T1, class T2>
+ struct scalar_plus_assign:
+ public scalar_binary_assign_functor<T1, T2> {
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ static const bool computed ;
+#else
+ static const bool computed = true ;
+#endif
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ t1 += t2;
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_plus_assign<U1, U2> other;
+ };
+ };
+
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ template<class T1, class T2>
+ const bool scalar_plus_assign<T1,T2>::computed = true;
+#endif
+
+ template<class T1, class T2>
+ struct scalar_minus_assign:
+ public scalar_binary_assign_functor<T1, T2> {
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ static const bool computed ;
+#else
+ static const bool computed = true ;
+#endif
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ t1 -= t2;
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_minus_assign<U1, U2> other;
+ };
+ };
+
+#if BOOST_WORKAROUND( __IBMCPP__, <=600 )
+ template<class T1, class T2>
+ const bool scalar_minus_assign<T1,T2>::computed = true;
+#endif
+
+ template<class T1, class T2>
+ struct scalar_multiplies_assign:
+ public scalar_binary_assign_functor<T1, T2> {
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
+ static const bool computed = true;
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ t1 *= t2;
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_multiplies_assign<U1, U2> other;
+ };
+ };
+ template<class T1, class T2>
+ struct scalar_divides_assign:
+ public scalar_binary_assign_functor<T1, T2> {
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_assign_functor<T1, T2>::argument2_type argument2_type;
+ static const bool computed ;
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ t1 /= t2;
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_divides_assign<U1, U2> other;
+ };
+ };
+ template<class T1, class T2>
+ const bool scalar_divides_assign<T1,T2>::computed = true;
+
+ template<class T1, class T2>
+ struct scalar_binary_swap_functor {
+ typedef typename type_traits<typename boost::remove_reference<T1>::type>::reference argument1_type;
+ typedef typename type_traits<typename boost::remove_reference<T2>::type>::reference argument2_type;
+ };
+
+ template<class T1, class T2>
+ struct scalar_swap:
+ public scalar_binary_swap_functor<T1, T2> {
+ typedef typename scalar_binary_swap_functor<T1, T2>::argument1_type argument1_type;
+ typedef typename scalar_binary_swap_functor<T1, T2>::argument2_type argument2_type;
+
+ static BOOST_UBLAS_INLINE
+ void apply (argument1_type t1, argument2_type t2) {
+ std::swap (t1, t2);
+ }
+
+ template<class U1, class U2>
+ struct rebind {
+ typedef scalar_swap<U1, U2> other;
+ };
+ };
+
+ // Vector functors
+
+ // Unary returning scalar
+ template<class V>
+ struct vector_scalar_unary_functor {
+ typedef typename V::value_type value_type;
+ typedef typename V::value_type result_type;
+ };
+
+ template<class V>
+ struct vector_sum:
+ public vector_scalar_unary_functor<V> {
+ typedef typename vector_scalar_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+ result_type t = result_type (0);
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i)
+ t += e () (i);
+ return t;
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+ result_type t = result_type (0);
+ while (-- size >= 0)
+ t += *it, ++ it;
+ return t;
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+ result_type t = result_type (0);
+ while (it != it_end)
+ t += *it, ++ it;
+ return t;
+ }
+ };
+
+ // Unary returning real scalar
+ template<class V>
+ struct vector_scalar_real_unary_functor {
+ typedef typename V::value_type value_type;
+ typedef typename type_traits<value_type>::real_type real_type;
+ typedef real_type result_type;
+ };
+
+ template<class V>
+ struct vector_norm_1:
+ public vector_scalar_real_unary_functor<V> {
+ typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
+ typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::type_abs (e () (i)));
+ t += u;
+ }
+ return t;
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+ real_type t = real_type ();
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_1 (*it));
+ t += u;
+ ++ it;
+ }
+ return t;
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+ real_type t = real_type ();
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_1 (*it));
+ t += u;
+ ++ it;
+ }
+ return t;
+ }
+ };
+ template<class V>
+ struct vector_norm_2:
+ public vector_scalar_real_unary_functor<V> {
+ typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
+ typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+#ifndef BOOST_UBLAS_SCALED_NORM
+ real_type t = real_type ();
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::norm_2 (e () (i)));
+ t += u * u;
+ }
+ return type_traits<real_type>::type_sqrt (t);
+#else
+ real_type scale = real_type ();
+ real_type sum_squares (1);
+ size_type size (e ().size ());
+ for (size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::norm_2 (e () (i)));
+ if ( real_type () /* zero */ == u ) continue;
+ if (scale < u) {
+ real_type v (scale / u);
+ sum_squares = sum_squares * v * v + real_type (1);
+ scale = u;
+ } else {
+ real_type v (u / scale);
+ sum_squares += v * v;
+ }
+ }
+ return scale * type_traits<real_type>::type_sqrt (sum_squares);
+#endif
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+#ifndef BOOST_UBLAS_SCALED_NORM
+ real_type t = real_type ();
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ t += u * u;
+ ++ it;
+ }
+ return type_traits<real_type>::type_sqrt (t);
+#else
+ real_type scale = real_type ();
+ real_type sum_squares (1);
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ if (scale < u) {
+ real_type v (scale / u);
+ sum_squares = sum_squares * v * v + real_type (1);
+ scale = u;
+ } else {
+ real_type v (u / scale);
+ sum_squares += v * v;
+ }
+ ++ it;
+ }
+ return scale * type_traits<real_type>::type_sqrt (sum_squares);
+#endif
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+#ifndef BOOST_UBLAS_SCALED_NORM
+ real_type t = real_type ();
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ t += u * u;
+ ++ it;
+ }
+ return type_traits<real_type>::type_sqrt (t);
+#else
+ real_type scale = real_type ();
+ real_type sum_squares (1);
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_2 (*it));
+ if (scale < u) {
+ real_type v (scale / u);
+ sum_squares = sum_squares * v * v + real_type (1);
+ scale = u;
+ } else {
+ real_type v (u / scale);
+ sum_squares += v * v;
+ }
+ ++ it;
+ }
+ return scale * type_traits<real_type>::type_sqrt (sum_squares);
+#endif
+ }
+ };
+ template<class V>
+ struct vector_norm_inf:
+ public vector_scalar_real_unary_functor<V> {
+ typedef typename vector_scalar_real_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_real_unary_functor<V>::real_type real_type;
+ typedef typename vector_scalar_real_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::norm_inf (e () (i)));
+ if (u > t)
+ t = u;
+ }
+ return t;
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+ real_type t = real_type ();
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_inf (*it));
+ if (u > t)
+ t = u;
+ ++ it;
+ }
+ return t;
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+ real_type t = real_type ();
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_inf (*it));
+ if (u > t)
+ t = u;
+ ++ it;
+ }
+ return t;
+ }
+ };
+
+ // Unary returning index
+ template<class V>
+ struct vector_scalar_index_unary_functor {
+ typedef typename V::value_type value_type;
+ typedef typename type_traits<value_type>::real_type real_type;
+ typedef typename V::size_type result_type;
+ };
+
+ template<class V>
+ struct vector_index_norm_inf:
+ public vector_scalar_index_unary_functor<V> {
+ typedef typename vector_scalar_index_unary_functor<V>::value_type value_type;
+ typedef typename vector_scalar_index_unary_functor<V>::real_type real_type;
+ typedef typename vector_scalar_index_unary_functor<V>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E> &e) {
+ // ISSUE For CBLAS compatibility return 0 index in empty case
+ result_type i_norm_inf (0);
+ real_type t = real_type ();
+ typedef typename E::size_type vector_size_type;
+ vector_size_type size (e ().size ());
+ for (vector_size_type i = 0; i < size; ++ i) {
+ real_type u (type_traits<value_type>::norm_inf (e () (i)));
+ if (u > t) {
+ i_norm_inf = i;
+ t = u;
+ }
+ }
+ return i_norm_inf;
+ }
+ // Dense case
+ template<class D, class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I it) {
+ // ISSUE For CBLAS compatibility return 0 index in empty case
+ result_type i_norm_inf (0);
+ real_type t = real_type ();
+ while (-- size >= 0) {
+ real_type u (type_traits<value_type>::norm_inf (*it));
+ if (u > t) {
+ i_norm_inf = it.index ();
+ t = u;
+ }
+ ++ it;
+ }
+ return i_norm_inf;
+ }
+ // Sparse case
+ template<class I>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I it, const I &it_end) {
+ // ISSUE For CBLAS compatibility return 0 index in empty case
+ result_type i_norm_inf (0);
+ real_type t = real_type ();
+ while (it != it_end) {
+ real_type u (type_traits<value_type>::norm_inf (*it));
+ if (u > t) {
+ i_norm_inf = it.index ();
+ t = u;
+ }
+ ++ it;
+ }
+ return i_norm_inf;
+ }
+ };
+
+ // Binary returning scalar
+ template<class V1, class V2, class TV>
+ struct vector_scalar_binary_functor {
+ typedef TV value_type;
+ typedef TV result_type;
+ };
+
+ template<class V1, class V2, class TV>
+ struct vector_inner_prod:
+ public vector_scalar_binary_functor<V1, V2, TV> {
+ typedef typename vector_scalar_binary_functor<V1, V2, TV>::value_type value_type;
+ typedef typename vector_scalar_binary_functor<V1, V2, TV>::result_type result_type;
+
+ template<class C1, class C2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_container<C1> &c1,
+ const vector_container<C2> &c2) {
+#ifdef BOOST_UBLAS_USE_SIMD
+ using namespace raw;
+ typedef typename C1::size_type vector_size_type;
+ vector_size_type size (BOOST_UBLAS_SAME (c1 ().size (), c2 ().size ()));
+ const typename V1::value_type *data1 = data_const (c1 ());
+ const typename V1::value_type *data2 = data_const (c2 ());
+ vector_size_type s1 = stride (c1 ());
+ vector_size_type s2 = stride (c2 ());
+ result_type t = result_type (0);
+ if (s1 == 1 && s2 == 1) {
+ for (vector_size_type i = 0; i < size; ++ i)
+ t += data1 [i] * data2 [i];
+ } else if (s2 == 1) {
+ for (vector_size_type i = 0, i1 = 0; i < size; ++ i, i1 += s1)
+ t += data1 [i1] * data2 [i];
+ } else if (s1 == 1) {
+ for (vector_size_type i = 0, i2 = 0; i < size; ++ i, i2 += s2)
+ t += data1 [i] * data2 [i2];
+ } else {
+ for (vector_size_type i = 0, i1 = 0, i2 = 0; i < size; ++ i, i1 += s1, i2 += s2)
+ t += data1 [i1] * data2 [i2];
+ }
+ return t;
+#elif defined(BOOST_UBLAS_HAVE_BINDINGS)
+ return boost::numeric::bindings::atlas::dot (c1 (), c2 ());
+#else
+ return apply (static_cast<const vector_expression<C1> > (c1), static_cast<const vector_expression<C2> > (c2));
+#endif
+ }
+ template<class E1, class E2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename E1::size_type vector_size_type;
+ vector_size_type size (BOOST_UBLAS_SAME (e1 ().size (), e2 ().size ()));
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (vector_size_type i = 0; i < size; ++ i)
+ t += e1 () (i) * e2 () (i);
+#else
+ vector_size_type i (0);
+ DD (size, 4, r, (t += e1 () (i) * e2 () (i), ++ i));
+#endif
+ return t;
+ }
+ // Dense case
+ template<class D, class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (D size, I1 it1, I2 it2) {
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+#else
+ DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
+#endif
+ return t;
+ }
+ // Packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
+ result_type t = result_type (0);
+ typedef typename I1::difference_type vector_difference_type;
+ vector_difference_type it1_size (it1_end - it1);
+ vector_difference_type it2_size (it2_end - it2);
+ vector_difference_type diff (0);
+ if (it1_size > 0 && it2_size > 0)
+ diff = it2.index () - it1.index ();
+ if (diff != 0) {
+ vector_difference_type size = (std::min) (diff, it1_size);
+ if (size > 0) {
+ it1 += size;
+ it1_size -= size;
+ diff -= size;
+ }
+ size = (std::min) (- diff, it2_size);
+ if (size > 0) {
+ it2 += size;
+ it2_size -= size;
+ diff += size;
+ }
+ }
+ vector_difference_type size ((std::min) (it1_size, it2_size));
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+ return t;
+ }
+ // Sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ if (it1 != it1_end && it2 != it2_end) {
+ while (true) {
+ if (it1.index () == it2.index ()) {
+ t += *it1 * *it2, ++ it1, ++ it2;
+ if (it1 == it1_end || it2 == it2_end)
+ break;
+ } else if (it1.index () < it2.index ()) {
+ increment (it1, it1_end, it2.index () - it1.index ());
+ if (it1 == it1_end)
+ break;
+ } else if (it1.index () > it2.index ()) {
+ increment (it2, it2_end, it1.index () - it2.index ());
+ if (it2 == it2_end)
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ };
+
+ // Matrix functors
+
+ // Binary returning vector
+ template<class M1, class M2, class TV>
+ struct matrix_vector_binary_functor {
+ typedef typename M1::size_type size_type;
+ typedef typename M1::difference_type difference_type;
+ typedef TV value_type;
+ typedef TV result_type;
+ };
+
+ template<class M1, class M2, class TV>
+ struct matrix_vector_prod1:
+ public matrix_vector_binary_functor<M1, M2, TV> {
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::size_type size_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::difference_type difference_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::value_type value_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::result_type result_type;
+
+ template<class C1, class C2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_container<C1> &c1,
+ const vector_container<C2> &c2,
+ size_type i) {
+#ifdef BOOST_UBLAS_USE_SIMD
+ using namespace raw;
+ size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().size ());
+ const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ());
+ const typename M2::value_type *data2 = data_const (c2 ());
+ size_type s1 = stride2 (c1 ());
+ size_type s2 = stride (c2 ());
+ result_type t = result_type (0);
+ if (s1 == 1 && s2 == 1) {
+ for (size_type j = 0; j < size; ++ j)
+ t += data1 [j] * data2 [j];
+ } else if (s2 == 1) {
+ for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1)
+ t += data1 [j1] * data2 [j];
+ } else if (s1 == 1) {
+ for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2)
+ t += data1 [j] * data2 [j2];
+ } else {
+ for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2)
+ t += data1 [j1] * data2 [j2];
+ }
+ return t;
+#elif defined(BOOST_UBLAS_HAVE_BINDINGS)
+ return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ());
+#else
+ return apply (static_cast<const matrix_expression<C1> > (c1), static_cast<const vector_expression<C2> > (c2, i));
+#endif
+ }
+ template<class E1, class E2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ size_type i) {
+ size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size ());
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type j = 0; j < size; ++ j)
+ t += e1 () (i, j) * e2 () (j);
+#else
+ size_type j (0);
+ DD (size, 4, r, (t += e1 () (i, j) * e2 () (j), ++ j));
+#endif
+ return t;
+ }
+ // Dense case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (difference_type size, I1 it1, I2 it2) {
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+#else
+ DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
+#endif
+ return t;
+ }
+ // Packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
+ result_type t = result_type (0);
+ difference_type it1_size (it1_end - it1);
+ difference_type it2_size (it2_end - it2);
+ difference_type diff (0);
+ if (it1_size > 0 && it2_size > 0)
+ diff = it2.index () - it1.index2 ();
+ if (diff != 0) {
+ difference_type size = (std::min) (diff, it1_size);
+ if (size > 0) {
+ it1 += size;
+ it1_size -= size;
+ diff -= size;
+ }
+ size = (std::min) (- diff, it2_size);
+ if (size > 0) {
+ it2 += size;
+ it2_size -= size;
+ diff += size;
+ }
+ }
+ difference_type size ((std::min) (it1_size, it2_size));
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+ return t;
+ }
+ // Sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
+ sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ if (it1 != it1_end && it2 != it2_end) {
+ size_type it1_index = it1.index2 (), it2_index = it2.index ();
+ while (true) {
+ difference_type compare = it1_index - it2_index;
+ if (compare == 0) {
+ t += *it1 * *it2, ++ it1, ++ it2;
+ if (it1 != it1_end && it2 != it2_end) {
+ it1_index = it1.index2 ();
+ it2_index = it2.index ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index2 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it2, it2_end, compare);
+ if (it2 != it2_end)
+ it2_index = it2.index ();
+ else
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ // Sparse packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */,
+ sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) {
+ result_type t = result_type (0);
+ while (it1 != it1_end) {
+ t += *it1 * it2 () (it1.index2 ());
+ ++ it1;
+ }
+ return t;
+ }
+ // Packed sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end,
+ packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ while (it2 != it2_end) {
+ t += it1 () (it1.index1 (), it2.index ()) * *it2;
+ ++ it2;
+ }
+ return t;
+ }
+ // Another dispatcher
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
+ sparse_bidirectional_iterator_tag) {
+ typedef typename I1::iterator_category iterator1_category;
+ typedef typename I2::iterator_category iterator2_category;
+ return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ());
+ }
+ };
+
+ template<class M1, class M2, class TV>
+ struct matrix_vector_prod2:
+ public matrix_vector_binary_functor<M1, M2, TV> {
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::size_type size_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::difference_type difference_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::value_type value_type;
+ typedef typename matrix_vector_binary_functor<M1, M2, TV>::result_type result_type;
+
+ template<class C1, class C2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_container<C1> &c1,
+ const matrix_container<C2> &c2,
+ size_type i) {
+#ifdef BOOST_UBLAS_USE_SIMD
+ using namespace raw;
+ size_type size = BOOST_UBLAS_SAME (c1 ().size (), c2 ().size1 ());
+ const typename M1::value_type *data1 = data_const (c1 ());
+ const typename M2::value_type *data2 = data_const (c2 ()) + i * stride2 (c2 ());
+ size_type s1 = stride (c1 ());
+ size_type s2 = stride1 (c2 ());
+ result_type t = result_type (0);
+ if (s1 == 1 && s2 == 1) {
+ for (size_type j = 0; j < size; ++ j)
+ t += data1 [j] * data2 [j];
+ } else if (s2 == 1) {
+ for (size_type j = 0, j1 = 0; j < size; ++ j, j1 += s1)
+ t += data1 [j1] * data2 [j];
+ } else if (s1 == 1) {
+ for (size_type j = 0, j2 = 0; j < size; ++ j, j2 += s2)
+ t += data1 [j] * data2 [j2];
+ } else {
+ for (size_type j = 0, j1 = 0, j2 = 0; j < size; ++ j, j1 += s1, j2 += s2)
+ t += data1 [j1] * data2 [j2];
+ }
+ return t;
+#elif defined(BOOST_UBLAS_HAVE_BINDINGS)
+ return boost::numeric::bindings::atlas::dot (c1 (), c2 ().column (i));
+#else
+ return apply (static_cast<const vector_expression<C1> > (c1), static_cast<const matrix_expression<C2> > (c2, i));
+#endif
+ }
+ template<class E1, class E2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ size_type i) {
+ size_type size = BOOST_UBLAS_SAME (e1 ().size (), e2 ().size1 ());
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type j = 0; j < size; ++ j)
+ t += e1 () (j) * e2 () (j, i);
+#else
+ size_type j (0);
+ DD (size, 4, r, (t += e1 () (j) * e2 () (j, i), ++ j));
+#endif
+ return t;
+ }
+ // Dense case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (difference_type size, I1 it1, I2 it2) {
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+#else
+ DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
+#endif
+ return t;
+ }
+ // Packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end) {
+ result_type t = result_type (0);
+ difference_type it1_size (it1_end - it1);
+ difference_type it2_size (it2_end - it2);
+ difference_type diff (0);
+ if (it1_size > 0 && it2_size > 0)
+ diff = it2.index1 () - it1.index ();
+ if (diff != 0) {
+ difference_type size = (std::min) (diff, it1_size);
+ if (size > 0) {
+ it1 += size;
+ it1_size -= size;
+ diff -= size;
+ }
+ size = (std::min) (- diff, it2_size);
+ if (size > 0) {
+ it2 += size;
+ it2_size -= size;
+ diff += size;
+ }
+ }
+ difference_type size ((std::min) (it1_size, it2_size));
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+ return t;
+ }
+ // Sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
+ sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ if (it1 != it1_end && it2 != it2_end) {
+ size_type it1_index = it1.index (), it2_index = it2.index1 ();
+ while (true) {
+ difference_type compare = it1_index - it2_index;
+ if (compare == 0) {
+ t += *it1 * *it2, ++ it1, ++ it2;
+ if (it1 != it1_end && it2 != it2_end) {
+ it1_index = it1.index ();
+ it2_index = it2.index1 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it2, it2_end, compare);
+ if (it2 != it2_end)
+ it2_index = it2.index1 ();
+ else
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ // Packed sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &/* it1_end */, I2 it2, const I2 &it2_end,
+ packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ while (it2 != it2_end) {
+ t += it1 () (it2.index1 ()) * *it2;
+ ++ it2;
+ }
+ return t;
+ }
+ // Sparse packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &/* it2_end */,
+ sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag) {
+ result_type t = result_type (0);
+ while (it1 != it1_end) {
+ t += *it1 * it2 () (it1.index (), it2.index2 ());
+ ++ it1;
+ }
+ return t;
+ }
+ // Another dispatcher
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end,
+ sparse_bidirectional_iterator_tag) {
+ typedef typename I1::iterator_category iterator1_category;
+ typedef typename I2::iterator_category iterator2_category;
+ return apply (it1, it1_end, it2, it2_end, iterator1_category (), iterator2_category ());
+ }
+ };
+
+ // Binary returning matrix
+ template<class M1, class M2, class TV>
+ struct matrix_matrix_binary_functor {
+ typedef typename M1::size_type size_type;
+ typedef typename M1::difference_type difference_type;
+ typedef TV value_type;
+ typedef TV result_type;
+ };
+
+ template<class M1, class M2, class TV>
+ struct matrix_matrix_prod:
+ public matrix_matrix_binary_functor<M1, M2, TV> {
+ typedef typename matrix_matrix_binary_functor<M1, M2, TV>::size_type size_type;
+ typedef typename matrix_matrix_binary_functor<M1, M2, TV>::difference_type difference_type;
+ typedef typename matrix_matrix_binary_functor<M1, M2, TV>::value_type value_type;
+ typedef typename matrix_matrix_binary_functor<M1, M2, TV>::result_type result_type;
+
+ template<class C1, class C2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_container<C1> &c1,
+ const matrix_container<C2> &c2,
+ size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_SIMD
+ using namespace raw;
+ size_type size = BOOST_UBLAS_SAME (c1 ().size2 (), c2 ().sizc1 ());
+ const typename M1::value_type *data1 = data_const (c1 ()) + i * stride1 (c1 ());
+ const typename M2::value_type *data2 = data_const (c2 ()) + j * stride2 (c2 ());
+ size_type s1 = stride2 (c1 ());
+ size_type s2 = stride1 (c2 ());
+ result_type t = result_type (0);
+ if (s1 == 1 && s2 == 1) {
+ for (size_type k = 0; k < size; ++ k)
+ t += data1 [k] * data2 [k];
+ } else if (s2 == 1) {
+ for (size_type k = 0, k1 = 0; k < size; ++ k, k1 += s1)
+ t += data1 [k1] * data2 [k];
+ } else if (s1 == 1) {
+ for (size_type k = 0, k2 = 0; k < size; ++ k, k2 += s2)
+ t += data1 [k] * data2 [k2];
+ } else {
+ for (size_type k = 0, k1 = 0, k2 = 0; k < size; ++ k, k1 += s1, k2 += s2)
+ t += data1 [k1] * data2 [k2];
+ }
+ return t;
+#elif defined(BOOST_UBLAS_HAVE_BINDINGS)
+ return boost::numeric::bindings::atlas::dot (c1 ().row (i), c2 ().column (j));
+#else
+ return apply (static_cast<const matrix_expression<C1> > (c1), static_cast<const matrix_expression<C2> > (c2, i));
+#endif
+ }
+ template<class E1, class E2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ size_type i, size_type j) {
+ size_type size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ());
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ for (size_type k = 0; k < size; ++ k)
+ t += e1 () (i, k) * e2 () (k, j);
+#else
+ size_type k (0);
+ DD (size, 4, r, (t += e1 () (i, k) * e2 () (k, j), ++ k));
+#endif
+ return t;
+ }
+ // Dense case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (difference_type size, I1 it1, I2 it2) {
+ result_type t = result_type (0);
+#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+#else
+ DD (size, 4, r, (t += *it1 * *it2, ++ it1, ++ it2));
+#endif
+ return t;
+ }
+ // Packed case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, packed_random_access_iterator_tag) {
+ result_type t = result_type (0);
+ difference_type it1_size (it1_end - it1);
+ difference_type it2_size (it2_end - it2);
+ difference_type diff (0);
+ if (it1_size > 0 && it2_size > 0)
+ diff = it2.index1 () - it1.index2 ();
+ if (diff != 0) {
+ difference_type size = (std::min) (diff, it1_size);
+ if (size > 0) {
+ it1 += size;
+ it1_size -= size;
+ diff -= size;
+ }
+ size = (std::min) (- diff, it2_size);
+ if (size > 0) {
+ it2 += size;
+ it2_size -= size;
+ diff += size;
+ }
+ }
+ difference_type size ((std::min) (it1_size, it2_size));
+ while (-- size >= 0)
+ t += *it1 * *it2, ++ it1, ++ it2;
+ return t;
+ }
+ // Sparse case
+ template<class I1, class I2>
+ static BOOST_UBLAS_INLINE
+ result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) {
+ result_type t = result_type (0);
+ if (it1 != it1_end && it2 != it2_end) {
+ size_type it1_index = it1.index2 (), it2_index = it2.index1 ();
+ while (true) {
+ difference_type compare = difference_type (it1_index - it2_index);
+ if (compare == 0) {
+ t += *it1 * *it2, ++ it1, ++ it2;
+ if (it1 != it1_end && it2 != it2_end) {
+ it1_index = it1.index2 ();
+ it2_index = it2.index1 ();
+ } else
+ break;
+ } else if (compare < 0) {
+ increment (it1, it1_end, - compare);
+ if (it1 != it1_end)
+ it1_index = it1.index2 ();
+ else
+ break;
+ } else if (compare > 0) {
+ increment (it2, it2_end, compare);
+ if (it2 != it2_end)
+ it2_index = it2.index1 ();
+ else
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ };
+
+ // Unary returning scalar norm
+ template<class M>
+ struct matrix_scalar_real_unary_functor {
+ typedef typename M::value_type value_type;
+ typedef typename type_traits<value_type>::real_type real_type;
+ typedef real_type result_type;
+ };
+
+ template<class M>
+ struct matrix_norm_1:
+ public matrix_scalar_real_unary_functor<M> {
+ typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type matrix_size_type;
+ matrix_size_type size2 (e ().size2 ());
+ for (matrix_size_type j = 0; j < size2; ++ j) {
+ real_type u = real_type ();
+ matrix_size_type size1 (e ().size1 ());
+ for (matrix_size_type i = 0; i < size1; ++ i) {
+ real_type v (type_traits<value_type>::norm_1 (e () (i, j)));
+ u += v;
+ }
+ if (u > t)
+ t = u;
+ }
+ return t;
+ }
+ };
+
+ template<class M>
+ struct matrix_norm_frobenius:
+ public matrix_scalar_real_unary_functor<M> {
+ typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type matrix_size_type;
+ matrix_size_type size1 (e ().size1 ());
+ for (matrix_size_type i = 0; i < size1; ++ i) {
+ matrix_size_type size2 (e ().size2 ());
+ for (matrix_size_type j = 0; j < size2; ++ j) {
+ real_type u (type_traits<value_type>::norm_2 (e () (i, j)));
+ t += u * u;
+ }
+ }
+ return type_traits<real_type>::type_sqrt (t);
+ }
+ };
+
+ template<class M>
+ struct matrix_norm_inf:
+ public matrix_scalar_real_unary_functor<M> {
+ typedef typename matrix_scalar_real_unary_functor<M>::value_type value_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::real_type real_type;
+ typedef typename matrix_scalar_real_unary_functor<M>::result_type result_type;
+
+ template<class E>
+ static BOOST_UBLAS_INLINE
+ result_type apply (const matrix_expression<E> &e) {
+ real_type t = real_type ();
+ typedef typename E::size_type matrix_size_type;
+ matrix_size_type size1 (e ().size1 ());
+ for (matrix_size_type i = 0; i < size1; ++ i) {
+ real_type u = real_type ();
+ matrix_size_type size2 (e ().size2 ());
+ for (matrix_size_type j = 0; j < size2; ++ j) {
+ real_type v (type_traits<value_type>::norm_inf (e () (i, j)));
+ u += v;
+ }
+ if (u > t)
+ t = u;
+ }
+ return t;
+ }
+ };
+
+ // forward declaration
+ template <class Z, class D> struct basic_column_major;
+
+ // This functor defines storage layout and it's properties
+ // matrix (i,j) -> storage [i * size_i + j]
+ template <class Z, class D>
+ struct basic_row_major {
+ typedef Z size_type;
+ typedef D difference_type;
+ typedef row_major_tag orientation_category;
+ typedef basic_column_major<Z,D> transposed_layout;
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type storage_size (size_type size_i, size_type size_j) {
+ // Guard against size_type overflow
+ BOOST_UBLAS_CHECK (size_j == 0 || size_i <= (std::numeric_limits<size_type>::max) () / size_j, bad_size ());
+ return size_i * size_j;
+ }
+
+ // Indexing conversion to storage element
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ detail::ignore_unused_variable_warning(size_i);
+ // Guard against size_type overflow
+ BOOST_UBLAS_CHECK (i <= ((std::numeric_limits<size_type>::max) () - j) / size_j, bad_index ());
+ return i * size_j + j;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type address (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i <= size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j <= size_j, bad_index ());
+ // Guard against size_type overflow - address may be size_j past end of storage
+ BOOST_UBLAS_CHECK (size_j == 0 || i <= ((std::numeric_limits<size_type>::max) () - j) / size_j, bad_index ());
+ detail::ignore_unused_variable_warning(size_i);
+ return i * size_j + j;
+ }
+
+ // Storage element to index conversion
+ static
+ BOOST_UBLAS_INLINE
+ difference_type distance_i (difference_type k, size_type /* size_i */, size_type size_j) {
+ return size_j != 0 ? k / size_j : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ difference_type distance_j (difference_type k, size_type /* size_i */, size_type /* size_j */) {
+ return k;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_i (difference_type k, size_type /* size_i */, size_type size_j) {
+ return size_j != 0 ? k / size_j : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_j (difference_type k, size_type /* size_i */, size_type size_j) {
+ return size_j != 0 ? k % size_j : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool fast_i () {
+ return false;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool fast_j () {
+ return true;
+ }
+
+ // Iterating storage elements
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_i (I &it, size_type /* size_i */, size_type size_j) {
+ it += size_j;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) {
+ it += n * size_j;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_i (I &it, size_type /* size_i */, size_type size_j) {
+ it -= size_j;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type size_j) {
+ it -= n * size_j;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_j (I &it, size_type /* size_i */, size_type /* size_j */) {
+ ++ it;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
+ it += n;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_j (I &it, size_type /* size_i */, size_type /* size_j */) {
+ -- it;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_j (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
+ it -= n;
+ }
+
+ // Triangular access
+ static
+ BOOST_UBLAS_INLINE
+ size_type triangular_size (size_type size_i, size_type size_j) {
+ size_type size = (std::max) (size_i, size_j);
+ // Guard against size_type overflow - simplified
+ BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size /* +1/2 */, bad_size ());
+ return ((size + 1) * size) / 2;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ BOOST_UBLAS_CHECK (i >= j, bad_index ());
+ detail::ignore_unused_variable_warning(size_i);
+ detail::ignore_unused_variable_warning(size_j);
+ // FIXME size_type overflow
+ // sigma_i (i + 1) = (i + 1) * i / 2
+ // i = 0 1 2 3, sigma = 0 1 3 6
+ return ((i + 1) * i) / 2 + j;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ BOOST_UBLAS_CHECK (i <= j, bad_index ());
+ // FIXME size_type overflow
+ // sigma_i (size - i) = size * i - i * (i - 1) / 2
+ // i = 0 1 2 3, sigma = 0 4 7 9
+ return (i * (2 * (std::max) (size_i, size_j) - i + 1)) / 2 + j - i;
+ }
+
+ // Major and minor indices
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_M (size_type index1, size_type /* index2 */) {
+ return index1;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_m (size_type /* index1 */, size_type index2) {
+ return index2;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type size_M (size_type size_i, size_type /* size_j */) {
+ return size_i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type size_m (size_type /* size_i */, size_type size_j) {
+ return size_j;
+ }
+ };
+
+ // This functor defines storage layout and it's properties
+ // matrix (i,j) -> storage [i + j * size_i]
+ template <class Z, class D>
+ struct basic_column_major {
+ typedef Z size_type;
+ typedef D difference_type;
+ typedef column_major_tag orientation_category;
+ typedef basic_row_major<Z,D> transposed_layout;
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type storage_size (size_type size_i, size_type size_j) {
+ // Guard against size_type overflow
+ BOOST_UBLAS_CHECK (size_i == 0 || size_j <= (std::numeric_limits<size_type>::max) () / size_i, bad_size ());
+ return size_i * size_j;
+ }
+
+ // Indexing conversion to storage element
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ detail::ignore_unused_variable_warning(size_j);
+ // Guard against size_type overflow
+ BOOST_UBLAS_CHECK (j <= ((std::numeric_limits<size_type>::max) () - i) / size_i, bad_index ());
+ return i + j * size_i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type address (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i <= size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j <= size_j, bad_index ());
+ detail::ignore_unused_variable_warning(size_j);
+ // Guard against size_type overflow - address may be size_i past end of storage
+ BOOST_UBLAS_CHECK (size_i == 0 || j <= ((std::numeric_limits<size_type>::max) () - i) / size_i, bad_index ());
+ return i + j * size_i;
+ }
+
+ // Storage element to index conversion
+ static
+ BOOST_UBLAS_INLINE
+ difference_type distance_i (difference_type k, size_type /* size_i */, size_type /* size_j */) {
+ return k;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ difference_type distance_j (difference_type k, size_type size_i, size_type /* size_j */) {
+ return size_i != 0 ? k / size_i : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_i (difference_type k, size_type size_i, size_type /* size_j */) {
+ return size_i != 0 ? k % size_i : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_j (difference_type k, size_type size_i, size_type /* size_j */) {
+ return size_i != 0 ? k / size_i : 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool fast_i () {
+ return true;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool fast_j () {
+ return false;
+ }
+
+ // Iterating
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_i (I &it, size_type /* size_i */, size_type /* size_j */) {
+ ++ it;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
+ it += n;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_i (I &it, size_type /* size_i */, size_type /* size_j */) {
+ -- it;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_i (I &it, difference_type n, size_type /* size_i */, size_type /* size_j */) {
+ it -= n;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_j (I &it, size_type size_i, size_type /* size_j */) {
+ it += size_i;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void increment_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) {
+ it += n * size_i;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_j (I &it, size_type size_i, size_type /* size_j */) {
+ it -= size_i;
+ }
+ template<class I>
+ static
+ BOOST_UBLAS_INLINE
+ void decrement_j (I &it, difference_type n, size_type size_i, size_type /* size_j */) {
+ it -= n* size_i;
+ }
+
+ // Triangular access
+ static
+ BOOST_UBLAS_INLINE
+ size_type triangular_size (size_type size_i, size_type size_j) {
+ size_type size = (std::max) (size_i, size_j);
+ // Guard against size_type overflow - simplified
+ BOOST_UBLAS_CHECK (size == 0 || size / 2 < (std::numeric_limits<size_type>::max) () / size /* +1/2 */, bad_size ());
+ return ((size + 1) * size) / 2;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type lower_element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ BOOST_UBLAS_CHECK (i >= j, bad_index ());
+ // FIXME size_type overflow
+ // sigma_j (size - j) = size * j - j * (j - 1) / 2
+ // j = 0 1 2 3, sigma = 0 4 7 9
+ return i - j + (j * (2 * (std::max) (size_i, size_j) - j + 1)) / 2;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type upper_element (size_type i, size_type size_i, size_type j, size_type size_j) {
+ BOOST_UBLAS_CHECK (i < size_i, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_j, bad_index ());
+ BOOST_UBLAS_CHECK (i <= j, bad_index ());
+ // FIXME size_type overflow
+ // sigma_j (j + 1) = (j + 1) * j / 2
+ // j = 0 1 2 3, sigma = 0 1 3 6
+ return i + ((j + 1) * j) / 2;
+ }
+
+ // Major and minor indices
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_M (size_type /* index1 */, size_type index2) {
+ return index2;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type index_m (size_type index1, size_type /* index2 */) {
+ return index1;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type size_M (size_type /* size_i */, size_type size_j) {
+ return size_j;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type size_m (size_type size_i, size_type /* size_j */) {
+ return size_i;
+ }
+ };
+
+
+ template <class Z>
+ struct basic_full {
+ typedef Z size_type;
+
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type packed_size (L, size_type size_i, size_type size_j) {
+ return L::storage_size (size_i, size_j);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool zero (size_type /* i */, size_type /* j */) {
+ return false;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool one (size_type /* i */, size_type /* j */) {
+ return false;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool other (size_type /* i */, size_type /* j */) {
+ return true;
+ }
+ // FIXME: this should not be used at all
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict1 (size_type i, size_type /* j */) {
+ return i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict2 (size_type /* i */, size_type j) {
+ return j;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict1 (size_type i, size_type /* j */) {
+ return i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict2 (size_type /* i */, size_type j) {
+ return j;
+ }
+ };
+
+ namespace detail {
+ template < class L >
+ struct transposed_structure {
+ typedef typename L::size_type size_type;
+
+ template<class LAYOUT>
+ static
+ BOOST_UBLAS_INLINE
+ size_type packed_size (LAYOUT l, size_type size_i, size_type size_j) {
+ return L::packed_size(l, size_j, size_i);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool zero (size_type i, size_type j) {
+ return L::zero(j, i);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool one (size_type i, size_type j) {
+ return L::one(j, i);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool other (size_type i, size_type j) {
+ return L::other(j, i);
+ }
+ template<class LAYOUT>
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (LAYOUT /* l */, size_type i, size_type size_i, size_type j, size_type size_j) {
+ return L::element(typename LAYOUT::transposed_layout(), j, size_j, i, size_i);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
+ return L::restrict2(j, i, size2, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
+ return L::restrict1(j, i, size2, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
+ return L::mutable_restrict2(j, i, size2, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
+ return L::mutable_restrict1(j, i, size2, size1);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return L::global_restrict2(index2, size2, index1, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return L::global_restrict1(index2, size2, index1, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return L::global_mutable_restrict2(index2, size2, index1, size1);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return L::global_mutable_restrict1(index2, size2, index1, size1);
+ }
+ };
+ }
+
+ template <class Z>
+ struct basic_lower {
+ typedef Z size_type;
+ typedef lower_tag triangular_type;
+
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type packed_size (L, size_type size_i, size_type size_j) {
+ return L::triangular_size (size_i, size_j);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool zero (size_type i, size_type j) {
+ return j > i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool one (size_type /* i */, size_type /* j */) {
+ return false;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool other (size_type i, size_type j) {
+ return j <= i;
+ }
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
+ return L::lower_element (i, size_i, j, size_j);
+ }
+
+ // return nearest valid index in column j
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
+ return (std::max)(j, (std::min) (size1, i));
+ }
+ // return nearest valid index in row i
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
+ return (std::max)(size_type(0), (std::min) (i+1, j));
+ }
+ // return nearest valid mutable index in column j
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
+ return (std::max)(j, (std::min) (size1, i));
+ }
+ // return nearest valid mutable index in row i
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
+ return (std::max)(size_type(0), (std::min) (i+1, j));
+ }
+
+ // return an index between the first and (1+last) filled row
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
+ return (std::max)(size_type(0), (std::min)(size1, index1) );
+ }
+ // return an index between the first and (1+last) filled column
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
+ return (std::max)(size_type(0), (std::min)(size2, index2) );
+ }
+
+ // return an index between the first and (1+last) filled mutable row
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
+ return (std::max)(size_type(0), (std::min)(size1, index1) );
+ }
+ // return an index between the first and (1+last) filled mutable column
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
+ return (std::max)(size_type(0), (std::min)(size2, index2) );
+ }
+ };
+
+ // the first row only contains a single 1. Thus it is not stored.
+ template <class Z>
+ struct basic_unit_lower : public basic_lower<Z> {
+ typedef Z size_type;
+ typedef unit_lower_tag triangular_type;
+
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type packed_size (L, size_type size_i, size_type size_j) {
+ // Zero size strict triangles are bad at this point
+ BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ());
+ return L::triangular_size (size_i - 1, size_j - 1);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool one (size_type i, size_type j) {
+ return j == i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool other (size_type i, size_type j) {
+ return j < i;
+ }
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
+ // Zero size strict triangles are bad at this point
+ BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ());
+ return L::lower_element (i-1, size_i - 1, j, size_j - 1);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict1 (size_type i, size_type j, size_type size1, size_type /* size2 */) {
+ return (std::max)(j+1, (std::min) (size1, i));
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type mutable_restrict2 (size_type i, size_type j, size_type /* size1 */, size_type /* size2 */) {
+ return (std::max)(size_type(0), (std::min) (i, j));
+ }
+
+ // return an index between the first and (1+last) filled mutable row
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict1 (size_type index1, size_type size1, size_type /* index2 */, size_type /* size2 */) {
+ return (std::max)(size_type(1), (std::min)(size1, index1) );
+ }
+ // return an index between the first and (1+last) filled mutable column
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_mutable_restrict2 (size_type /* index1 */, size_type /* size1 */, size_type index2, size_type size2) {
+ BOOST_UBLAS_CHECK( size2 >= 1 , external_logic() );
+ return (std::max)(size_type(0), (std::min)(size2-1, index2) );
+ }
+ };
+
+ // the first row only contains no element. Thus it is not stored.
+ template <class Z>
+ struct basic_strict_lower : public basic_unit_lower<Z> {
+ typedef Z size_type;
+ typedef strict_lower_tag triangular_type;
+
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type packed_size (L, size_type size_i, size_type size_j) {
+ // Zero size strict triangles are bad at this point
+ BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0, bad_index ());
+ return L::triangular_size (size_i - 1, size_j - 1);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool zero (size_type i, size_type j) {
+ return j >= i;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool one (size_type /*i*/, size_type /*j*/) {
+ return false;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ bool other (size_type i, size_type j) {
+ return j < i;
+ }
+ template<class L>
+ static
+ BOOST_UBLAS_INLINE
+ size_type element (L, size_type i, size_type size_i, size_type j, size_type size_j) {
+ // Zero size strict triangles are bad at this point
+ BOOST_UBLAS_CHECK (size_i != 0 && size_j != 0 && i != 0, bad_index ());
+ return L::lower_element (i-1, size_i - 1, j, size_j - 1);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict1 (size_type i, size_type j, size_type size1, size_type size2) {
+ return basic_unit_lower<Z>::mutable_restrict1(i, j, size1, size2);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ size_type restrict2 (size_type i, size_type j, size_type size1, size_type size2) {
+ return basic_unit_lower<Z>::mutable_restrict2(i, j, size1, size2);
+ }
+
+ // return an index between the first and (1+last) filled row
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict1 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return basic_unit_lower<Z>::global_mutable_restrict1(index1, size1, index2, size2);
+ }
+ // return an index between the first and (1+last) filled column
+ static
+ BOOST_UBLAS_INLINE
+ size_type global_restrict2 (size_type index1, size_type size1, size_type index2, size_type size2) {
+ return basic_unit_lower<Z>::global_mutable_restrict2(index1, size1, index2, size2);
+ }
+ };
+
+
+ template <class Z>
+ struct basic_upper : public detail::transposed_structure<basic_lower<Z> >
+ {
+ typedef upper_tag triangular_type;
+ };
+
+ template <class Z>
+ struct basic_unit_upper : public detail::transposed_structure<basic_unit_lower<Z> >
+ {
+ typedef unit_upper_tag triangular_type;
+ };
+
+ template <class Z>
+ struct basic_strict_upper : public detail::transposed_structure<basic_strict_lower<Z> >
+ {
+ typedef strict_upper_tag triangular_type;
+ };
+
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch, David Bellot
+//
+// 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.
+//
+
+/// \file fwd.hpp is essentially used to forward declare the main types
+
+#ifndef BOOST_UBLAS_FWD_H
+#define BOOST_UBLAS_FWD_H
+
+#include <memory>
+
+namespace boost { namespace numeric { namespace ublas {
+
+ // Storage types
+ template<class T, class ALLOC = std::allocator<T> >
+ class unbounded_array;
+
+ template<class T, std::size_t N, class ALLOC = std::allocator<T> >
+ class bounded_array;
+
+ template <class Z = std::size_t, class D = std::ptrdiff_t>
+ class basic_range;
+ template <class Z = std::size_t, class D = std::ptrdiff_t>
+ class basic_slice;
+ typedef basic_range<> range;
+ typedef basic_slice<> slice;
+ template<class A = unbounded_array<std::size_t> >
+ class indirect_array;
+
+ template<class I, class T, class ALLOC = std::allocator<std::pair<const I, T> > >
+ class map_std;
+ template<class I, class T, class ALLOC = std::allocator<std::pair<I, T> > >
+ class map_array;
+
+ // Expression types
+ struct scalar_tag {};
+
+ struct vector_tag {};
+ template<class E>
+ class vector_expression;
+ template<class C>
+ class vector_container;
+
+ template<class E>
+ class vector_reference;
+
+ struct matrix_tag {};
+
+ template<class E>
+ class matrix_expression;
+ template<class C>
+ class matrix_container;
+
+ template<class E>
+ class matrix_reference;
+
+ template<class V>
+ class vector_range;
+ template<class V>
+ class vector_slice;
+ template<class V, class IA = indirect_array<> >
+ class vector_indirect;
+
+ template<class M>
+ class matrix_row;
+ template<class M>
+ class matrix_column;
+ template<class M>
+ class matrix_vector_range;
+ template<class M>
+ class matrix_vector_slice;
+ template<class M, class IA = indirect_array<> >
+ class matrix_vector_indirect;
+ template<class M>
+ class matrix_range;
+ template<class M>
+ class matrix_slice;
+ template<class M, class IA = indirect_array<> >
+ class matrix_indirect;
+
+ template<class T, class A = unbounded_array<T> >
+ class vector;
+ template<class T, std::size_t N>
+ class bounded_vector;
+
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class unit_vector;
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class zero_vector;
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class scalar_vector;
+
+ template<class T, std::size_t N>
+ class c_vector;
+
+ // Sparse vectors
+ template<class T, class A = map_std<std::size_t, T> >
+ class mapped_vector;
+ template<class T, std::size_t IB = 0, class IA = unbounded_array<std::size_t>, class TA = unbounded_array<T> >
+ class compressed_vector;
+ template<class T, std::size_t IB = 0, class IA = unbounded_array<std::size_t>, class TA = unbounded_array<T> >
+ class coordinate_vector;
+
+ // Matrix orientation type
+ struct unknown_orientation_tag {};
+ struct row_major_tag {};
+ struct column_major_tag {};
+
+ // Matrix storage layout parameterisation
+ template <class Z = std::size_t, class D = std::ptrdiff_t>
+ struct basic_row_major;
+ typedef basic_row_major<> row_major;
+
+ template <class Z = std::size_t, class D = std::ptrdiff_t>
+ struct basic_column_major;
+ typedef basic_column_major<> column_major;
+
+ template<class T, class L = row_major, class A = unbounded_array<T> >
+ class matrix;
+ template<class T, std::size_t M, std::size_t N, class L = row_major>
+ class bounded_matrix;
+
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class identity_matrix;
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class zero_matrix;
+ template<class T = int, class ALLOC = std::allocator<T> >
+ class scalar_matrix;
+
+ template<class T, std::size_t M, std::size_t N>
+ class c_matrix;
+
+ template<class T, class L = row_major, class A = unbounded_array<unbounded_array<T> > >
+ class vector_of_vector;
+
+ template<class T, class L = row_major, class A = vector<compressed_vector<T> > >
+ class generalized_vector_of_vector;
+
+ // Triangular matrix type
+ struct lower_tag {};
+ struct upper_tag {};
+ struct unit_lower_tag : public lower_tag {};
+ struct unit_upper_tag : public upper_tag {};
+ struct strict_lower_tag : public lower_tag {};
+ struct strict_upper_tag : public upper_tag {};
+
+ // Triangular matrix parameterisation
+ template <class Z = std::size_t>
+ struct basic_full;
+ typedef basic_full<> full;
+
+ template <class Z = std::size_t>
+ struct basic_lower;
+ typedef basic_lower<> lower;
+
+ template <class Z = std::size_t>
+ struct basic_upper;
+ typedef basic_upper<> upper;
+
+ template <class Z = std::size_t>
+ struct basic_unit_lower;
+ typedef basic_unit_lower<> unit_lower;
+
+ template <class Z = std::size_t>
+ struct basic_unit_upper;
+ typedef basic_unit_upper<> unit_upper;
+
+ template <class Z = std::size_t>
+ struct basic_strict_lower;
+ typedef basic_strict_lower<> strict_lower;
+
+ template <class Z = std::size_t>
+ struct basic_strict_upper;
+ typedef basic_strict_upper<> strict_upper;
+
+ // Special matrices
+ template<class T, class L = row_major, class A = unbounded_array<T> >
+ class banded_matrix;
+ template<class T, class L = row_major, class A = unbounded_array<T> >
+ class diagonal_matrix;
+
+ template<class T, class TRI = lower, class L = row_major, class A = unbounded_array<T> >
+ class triangular_matrix;
+ template<class M, class TRI = lower>
+ class triangular_adaptor;
+
+ template<class T, class TRI = lower, class L = row_major, class A = unbounded_array<T> >
+ class symmetric_matrix;
+ template<class M, class TRI = lower>
+ class symmetric_adaptor;
+
+ template<class T, class TRI = lower, class L = row_major, class A = unbounded_array<T> >
+ class hermitian_matrix;
+ template<class M, class TRI = lower>
+ class hermitian_adaptor;
+
+ // Sparse matrices
+ template<class T, class L = row_major, class A = map_std<std::size_t, T> >
+ class mapped_matrix;
+ template<class T, class L = row_major, class A = map_std<std::size_t, map_std<std::size_t, T> > >
+ class mapped_vector_of_mapped_vector;
+ template<class T, class L = row_major, std::size_t IB = 0, class IA = unbounded_array<std::size_t>, class TA = unbounded_array<T> >
+ class compressed_matrix;
+ template<class T, class L = row_major, std::size_t IB = 0, class IA = unbounded_array<std::size_t>, class TA = unbounded_array<T> >
+ class coordinate_matrix;
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch, David Bellot
+//
+// 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_HERMITIAN_H
+#define BOOST_UBLAS_HERMITIAN_H
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/triangular.hpp> // for resize_preserve
+#include <boost/numeric/ublas/detail/temporary.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+// Hermitian matrices are square. Thanks to Peter Schmitteckert for spotting this.
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class M>
+ bool is_hermitian (const M &m) {
+ typedef typename M::size_type size_type;
+
+ if (m.size1 () != m.size2 ())
+ return false;
+ size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
+ for (size_type i = 0; i < size; ++ i) {
+ for (size_type j = i; j < size; ++ j) {
+ if (m (i, j) != conj (m (j, i)))
+ return false;
+ }
+ }
+ return true;
+ }
+
+#ifdef BOOST_UBLAS_STRICT_HERMITIAN
+
+ template<class M>
+ class hermitian_matrix_element:
+ public container_reference<M> {
+ public:
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element (matrix_type &m, size_type i, size_type j, value_type d):
+ container_reference<matrix_type> (m), i_ (i), j_ (j), d_ (d), dirty_ (false) {}
+ BOOST_UBLAS_INLINE
+ ~hermitian_matrix_element () {
+ if (dirty_)
+ (*this) ().insert_element (i_, j_, d_);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator = (const hermitian_matrix_element &p) {
+ // Overide the implict copy assignment
+ d_ = p.d_;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator = (const D &d) {
+ d_ = d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator += (const D &d) {
+ d_ += d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator -= (const D &d) {
+ d_ -= d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator *= (const D &d) {
+ d_ *= d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix_element &operator /= (const D &d) {
+ d_ /= d;
+ dirty_ = true;
+ return *this;
+ }
+
+ // Comparison
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator == (const D &d) const {
+ return d_ == d;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator != (const D &d) const {
+ return d_ != d;
+ }
+
+ // Conversion
+ BOOST_UBLAS_INLINE
+ operator const_reference () const {
+ return d_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (hermitian_matrix_element p) {
+ if (this != &p) {
+ dirty_ = true;
+ p.dirty_ = true;
+ std::swap (d_, p.d_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (hermitian_matrix_element p1, hermitian_matrix_element p2) {
+ p1.swap (p2);
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ value_type d_;
+ bool dirty_;
+ };
+
+ template<class M>
+ struct type_traits<hermitian_matrix_element<M> > {
+ typedef typename M::value_type element_type;
+ typedef type_traits<hermitian_matrix_element<M> > self_type;
+ typedef typename type_traits<element_type>::value_type value_type;
+ typedef typename type_traits<element_type>::const_reference const_reference;
+ typedef hermitian_matrix_element<M> reference;
+ typedef typename type_traits<element_type>::real_type real_type;
+ typedef typename type_traits<element_type>::precision_type precision_type;
+
+ static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
+ static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type real (const_reference t) {
+ return type_traits<element_type>::real (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type imag (const_reference t) {
+ return type_traits<element_type>::imag (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type conj (const_reference t) {
+ return type_traits<element_type>::conj (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type type_abs (const_reference t) {
+ return type_traits<element_type>::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type type_sqrt (const_reference t) {
+ return type_traits<element_type>::type_sqrt (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_1 (const_reference t) {
+ return type_traits<element_type>::norm_1 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_2 (const_reference t) {
+ return type_traits<element_type>::norm_2 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_inf (const_reference t) {
+ return type_traits<element_type>::norm_inf (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool equals (const_reference t1, const_reference t2) {
+ return type_traits<element_type>::equals (t1, t2);
+ }
+ };
+
+ template<class M1, class T2>
+ struct promote_traits<hermitian_matrix_element<M1>, T2> {
+ typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type, T2>::promote_type promote_type;
+ };
+ template<class T1, class M2>
+ struct promote_traits<T1, hermitian_matrix_element<M2> > {
+ typedef typename promote_traits<T1, typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
+ };
+ template<class M1, class M2>
+ struct promote_traits<hermitian_matrix_element<M1>, hermitian_matrix_element<M2> > {
+ typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type,
+ typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
+ };
+
+#endif
+ /** \brief A hermitian matrix of values of type \c T
+ *
+ * For a \f$(n \times n)\f$-dimensional matrix and \f$ 0 \leq i < n, 0 \leq j < n\f$, every element
+ * \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the container for row major orientation
+ * or the \f$(i + j.m)\f$-th element of the container for column major orientation. And
+ * \f$\forall i,j\f$, \f$m_{i,j} = \overline{m_{i,j}}\f$.
+ *
+ * Orientation and storage can also be specified, otherwise a row major and unbounded array are used.
+ * It is \b not required by the storage to initialize elements of the matrix.
+ * Moreover, only the given triangular matrix is stored and the storage of hermitian matrices is packed.
+ *
+ * See http://en.wikipedia.org/wiki/Hermitian_matrix for more details on hermitian matrices.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam TRI the type of triangular matrix is either \c lower or \c upper. Default is \c lower
+ * \tparam L the storage organization. It is either \c row_major or \c column_major. Default is \c row_major
+ * \tparam A the type of Storage array. Default is \unbounded_array.
+ */
+ template<class T, class TRI, class L, class A>
+ class hermitian_matrix:
+ public matrix_container<hermitian_matrix<T, TRI, L, A> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef TRI triangular_type;
+ typedef L layout_type;
+ typedef hermitian_matrix<T, TRI, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ // FIXME no better way to not return the address of a temporary?
+ // typedef const T &const_reference;
+ typedef const T const_reference;
+#ifndef BOOST_UBLAS_STRICT_HERMITIAN
+ typedef T &reference;
+#else
+ typedef hermitian_matrix_element<self_type> reference;
+#endif
+ typedef A array_type;
+
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, A> vector_temporary_type;
+ typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
+ typedef packed_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ hermitian_matrix ():
+ matrix_container<self_type> (),
+ size_ (0), data_ (0) {}
+ BOOST_UBLAS_INLINE
+ hermitian_matrix (size_type size):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
+ }
+ BOOST_UBLAS_INLINE
+ hermitian_matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
+ }
+ BOOST_UBLAS_INLINE
+ hermitian_matrix (size_type size, const array_type &data):
+ matrix_container<self_type> (),
+ size_ (size), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ hermitian_matrix (const hermitian_matrix &m):
+ matrix_container<self_type> (),
+ size_ (m.size_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix (const matrix_expression<AE> &ae):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
+ data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ if (preserve) {
+ self_type temporary (size, size);
+ detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
+ }
+ else {
+ data ().resize (triangular_type::packed_size (layout_type (), size, size));
+ size_ = size;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ resize (BOOST_UBLAS_SAME (size1, size2), preserve);
+ }
+ BOOST_UBLAS_INLINE
+ void resize_packed_preserve (size_type size) {
+ size_ = BOOST_UBLAS_SAME (size, size);
+ data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ // if (i == j)
+ // return type_traits<value_type>::real (data () [triangular_type::element (layout_type (), i, size_, i, size_)]);
+ // else
+ if (triangular_type::other (i, j))
+ return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
+ else
+ return type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]);
+ }
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ BOOST_UBLAS_CHECK (triangular_type::other (i, j), bad_index ());
+ return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_HERMITIAN
+ if (!triangular_type::other (i, j)) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return at_element (i, j);
+#else
+ if (triangular_type::other (i, j))
+ return reference (*this, i, j, data () [triangular_type::element (layout_type (), i, size_, j, size_)]);
+ else
+ return reference (*this, i, j, type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]));
+#endif
+ }
+
+ // Element assignemnt
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ if (triangular_type::other (i, j)) {
+ return (data () [triangular_type::element (layout_type (), i, size_, j, size_)] = t);
+ } else {
+ return (data () [triangular_type::element (layout_type (), j, size_, i, size_)] = type_traits<value_type>::conj (t));
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ data () [triangular_type::element (layout_type (), i, size_, j, size_)] = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ std::fill (data ().begin (), data ().end (), value_type/*zero*/());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &operator = (const hermitian_matrix &m) {
+ size_ = m.size_;
+ data () = m.data ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &assign_temporary (hermitian_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix& operator *= (const AT &at) {
+ // Multiplication is only allowed for real scalars,
+ // otherwise the resulting matrix isn't hermitian.
+ // Thanks to Peter Schmitteckert for spotting this.
+ BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ hermitian_matrix& operator /= (const AT &at) {
+ // Multiplication is only allowed for real scalars,
+ // otherwise the resulting matrix isn't hermitian.
+ // Thanks to Peter Schmitteckert for spotting this.
+ BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (hermitian_matrix &m) {
+ if (this != &m) {
+ std::swap (size_, m.size_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (hermitian_matrix &m1, hermitian_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+ return const_iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
+ if (rank == 0)
+ i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
+ return iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+ return const_iterator2 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
+ if (rank == 0)
+ j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
+ return iterator2 (*this, i, j);
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<hermitian_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename hermitian_matrix::value_type value_type;
+ typedef typename hermitian_matrix::difference_type difference_type;
+ typedef typename hermitian_matrix::const_reference reference;
+ typedef const typename hermitian_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<hermitian_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename hermitian_matrix::value_type value_type;
+ typedef typename hermitian_matrix::difference_type difference_type;
+ typedef typename hermitian_matrix::true_reference reference;
+ typedef typename hermitian_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) ().at_element (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<hermitian_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename hermitian_matrix::value_type value_type;
+ typedef typename hermitian_matrix::difference_type difference_type;
+ typedef typename hermitian_matrix::const_reference reference;
+ typedef const typename hermitian_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<hermitian_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename hermitian_matrix::value_type value_type;
+ typedef typename hermitian_matrix::difference_type difference_type;
+ typedef typename hermitian_matrix::true_reference reference;
+ typedef typename hermitian_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) ().at_element (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ };
+
+ /** \brief A Hermitian matrix adaptator: convert a any matrix into a Hermitian matrix expression
+ *
+ * For a \f$(m\times n)\f$-dimensional matrix, the \c hermitian_adaptor will provide a hermitian matrix.
+ * Storage and location are based on those of the underlying matrix. This is important because
+ * a \c hermitian_adaptor does not copy the matrix data to a new place. Therefore, modifying values
+ * in a \c hermitian_adaptor matrix will also modify the underlying matrix too.
+ *
+ * \tparam M the type of matrix used to generate a hermitian matrix
+ */
+ template<class M, class TRI>
+ class hermitian_adaptor:
+ public matrix_expression<hermitian_adaptor<M, TRI> > {
+
+ typedef hermitian_adaptor<M, TRI> self_type;
+ typedef typename M::value_type &true_reference;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef const M const_matrix_type;
+ typedef M matrix_type;
+ typedef TRI triangular_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::value_type const_reference;
+#ifndef BOOST_UBLAS_STRICT_HERMITIAN
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::value_type,
+ typename M::reference>::type reference;
+#else
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::value_type,
+ hermitian_matrix_element<self_type> >::type reference;
+#endif
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ // Replaced by _temporary_traits to avoid type requirements on M
+ //typedef typename M::vector_temporary_type vector_temporary_type;
+ //typedef typename M::matrix_temporary_type matrix_temporary_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ packed_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor (matrix_type &data):
+ matrix_expression<self_type> (),
+ data_ (data) {
+ BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
+ }
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor (const hermitian_adaptor &m):
+ matrix_expression<self_type> (),
+ data_ (m.data_) {
+ BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return data_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return data_.size2 ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ // if (i == j)
+ // return type_traits<value_type>::real (data () (i, i));
+ // else
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else
+ return type_traits<value_type>::conj (data () (j, i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+#ifndef BOOST_UBLAS_STRICT_HERMITIAN
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else {
+ external_logic ().raise ();
+ return conj_ = type_traits<value_type>::conj (data () (j, i));
+ }
+#else
+ if (triangular_type::other (i, j))
+ return reference (*this, i, j, data () (i, j));
+ else
+ return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, value_type t) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ // if (i == j)
+ // data () (i, i) = type_traits<value_type>::real (t);
+ // else
+ if (triangular_type::other (i, j))
+ return data () (i, j) = t;
+ else
+ return data () (j, i) = type_traits<value_type>::conj (t);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+#ifndef BOOST_UBLAS_STRICT_HERMITIAN
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else {
+ external_logic ().raise ();
+ return conj_ = type_traits<value_type>::conj (data () (j, i));
+ }
+#else
+ if (triangular_type::other (i, j))
+ return reference (*this, i, j, data () (i, j));
+ else
+ return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, value_type t) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ // if (i == j)
+ // data () (i, i) = type_traits<value_type>::real (t);
+ // else
+ if (triangular_type::other (i, j))
+ return data () (i, j) = t;
+ else
+ return data () (j, i) = type_traits<value_type>::conj (t);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &operator = (const hermitian_adaptor &m) {
+ matrix_assign<scalar_assign, triangular_type> (*this, m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
+ *this = m;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor& operator *= (const AT &at) {
+ // Multiplication is only allowed for real scalars,
+ // otherwise the resulting matrix isn't hermitian.
+ // Thanks to Peter Schmitteckert for spotting this.
+ BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ hermitian_adaptor& operator /= (const AT &at) {
+ // Multiplication is only allowed for real scalars,
+ // otherwise the resulting matrix isn't hermitian.
+ // Thanks to Peter Schmitteckert for spotting this.
+ BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const hermitian_adaptor &ha) const {
+ return (*this).data ().same_closure (ha.data ());
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (hermitian_adaptor &m) {
+ if (this != &m)
+ matrix_swap<scalar_swap, triangular_type> (*this, m);
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use matrix iterator
+ typedef typename M::const_iterator1 const_subiterator1_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator1_type;
+ typedef typename M::const_iterator2 const_subiterator2_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (triangular_type::other (i, j)) {
+ if (triangular_type::other (size1 (), j)) {
+ return const_iterator1 (*this, 0, 0,
+ data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
+ data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
+ } else {
+ return const_iterator1 (*this, 0, 1,
+ data ().find1 (rank, i, j), data ().find1 (rank, j, j),
+ data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
+ }
+ } else {
+ if (triangular_type::other (size1 (), j)) {
+ return const_iterator1 (*this, 1, 0,
+ data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
+ data ().find2 (rank, j, i), data ().find2 (rank, j, j));
+ } else {
+ return const_iterator1 (*this, 1, 1,
+ data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
+ data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
+ }
+ }
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
+ if (rank == 0)
+ i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
+ return iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (triangular_type::other (i, j)) {
+ if (triangular_type::other (i, size2 ())) {
+ return const_iterator2 (*this, 1, 1,
+ data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
+ data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
+ } else {
+ return const_iterator2 (*this, 1, 0,
+ data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
+ data ().find2 (rank, i, j), data ().find2 (rank, i, i));
+ }
+ } else {
+ if (triangular_type::other (i, size2 ())) {
+ return const_iterator2 (*this, 0, 1,
+ data ().find1 (rank, j, i), data ().find1 (rank, i, i),
+ data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
+ } else {
+ return const_iterator2 (*this, 0, 0,
+ data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
+ data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
+ }
+ }
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
+ if (rank == 0)
+ j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
+ return iterator2 (*this, data ().find2 (rank, i, j));
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<hermitian_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
+ const_iterator1, value_type> {
+ public:
+ typedef typename const_subiterator1_type::value_type value_type;
+ typedef typename const_subiterator1_type::difference_type difference_type;
+ // FIXME no better way to not return the address of a temporary?
+ // typedef typename const_subiterator1_type::reference reference;
+ typedef typename const_subiterator1_type::value_type reference;
+ typedef typename const_subiterator1_type::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (),
+ begin_ (-1), end_ (-1), current_ (-1),
+ it1_begin_ (), it1_end_ (), it1_ (),
+ it2_begin_ (), it2_end_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int begin, int end,
+ const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
+ const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
+ container_const_reference<self_type> (m),
+ begin_ (begin), end_ (end), current_ (begin),
+ it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
+ it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
+ if (current_ == 0 && it1_ == it1_end_)
+ current_ = 1;
+ if (current_ == 1 && it2_ == it2_end_)
+ current_ = 0;
+ if ((current_ == 0 && it1_ == it1_end_) ||
+ (current_ == 1 && it2_ == it2_end_))
+ current_ = end_;
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+ // FIXME cannot compile
+ // iterator1 does not have these members!
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()),
+ begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
+ it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
+ it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ ++ it1_;
+ if (it1_ == it1_end_ && end_ == 1) {
+ it2_ = it2_begin_;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ ++ it2_;
+ if (it2_ == it2_end_ && end_ == 0) {
+ it1_ = it1_begin_;
+ current_ = 0;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ if (it1_ == it1_begin_ && begin_ == 1) {
+ it2_ = it2_end_;
+ BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
+ -- it2_;
+ current_ = 1;
+ } else {
+ -- it1_;
+ }
+ } else /* if (current_ == 1) */ {
+ if (it2_ == it2_begin_ && begin_ == 0) {
+ it1_ = it1_end_;
+ BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
+ -- it1_;
+ current_ = 0;
+ } else {
+ -- it2_;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_end_ - it1_);
+ it1_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_begin_ + d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_end_ - it2_);
+ it2_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_begin_ + d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_ - it1_begin_);
+ it1_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_end_ - d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_ - it2_begin_);
+ it2_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_end_ - d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ if (current_ == 0 && it.current_ == 0) {
+ return it1_ - it.it1_;
+ } else if (current_ == 0 && it.current_ == 1) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
+ }
+
+ } else if (current_ == 1 && it.current_ == 0) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
+ }
+ } else /* if (current_ == 1 && it.current_ == 1) */ {
+ return it2_ - it.it2_;
+ }
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ if (triangular_type::other (index1 (), index2 ()))
+ return *it1_;
+ else
+ return type_traits<value_type>::conj (*it1_);
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ if (triangular_type::other (index1 (), index2 ()))
+ return *it2_;
+ else
+ return type_traits<value_type>::conj (*it2_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index1 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index2 ();
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index2 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index1 ();
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ begin_ = it.begin_;
+ end_ = it.end_;
+ current_ = it.current_;
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+ it1_ = it.it1_;
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
+ (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it - *this > 0;
+ }
+
+ private:
+ int begin_;
+ int end_;
+ int current_;
+ const_subiterator1_type it1_begin_;
+ const_subiterator1_type it1_end_;
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_begin_;
+ const_subiterator2_type it2_end_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<hermitian_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator1, value_type> {
+ public:
+ typedef typename subiterator1_type::value_type value_type;
+ typedef typename subiterator1_type::difference_type difference_type;
+ typedef typename subiterator1_type::reference reference;
+ typedef typename subiterator1_type::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator1_type &it1):
+ container_reference<self_type> (m), it1_ (it1) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it1_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<hermitian_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
+ const_iterator2, value_type> {
+ public:
+ typedef typename const_subiterator2_type::value_type value_type;
+ typedef typename const_subiterator2_type::difference_type difference_type;
+ // FIXME no better way to not return the address of a temporary?
+ // typedef typename const_subiterator2_type::reference reference;
+ typedef typename const_subiterator2_type::value_type reference;
+ typedef typename const_subiterator2_type::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (),
+ begin_ (-1), end_ (-1), current_ (-1),
+ it1_begin_ (), it1_end_ (), it1_ (),
+ it2_begin_ (), it2_end_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int begin, int end,
+ const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
+ const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
+ container_const_reference<self_type> (m),
+ begin_ (begin), end_ (end), current_ (begin),
+ it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
+ it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
+ if (current_ == 0 && it1_ == it1_end_)
+ current_ = 1;
+ if (current_ == 1 && it2_ == it2_end_)
+ current_ = 0;
+ if ((current_ == 0 && it1_ == it1_end_) ||
+ (current_ == 1 && it2_ == it2_end_))
+ current_ = end_;
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+ // FIXME cannot compiler
+ // iterator2 does not have these members!
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()),
+ begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
+ it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
+ it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ ++ it1_;
+ if (it1_ == it1_end_ && end_ == 1) {
+ it2_ = it2_begin_;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ ++ it2_;
+ if (it2_ == it2_end_ && end_ == 0) {
+ it1_ = it1_begin_;
+ current_ = 0;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ if (it1_ == it1_begin_ && begin_ == 1) {
+ it2_ = it2_end_;
+ BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
+ -- it2_;
+ current_ = 1;
+ } else {
+ -- it1_;
+ }
+ } else /* if (current_ == 1) */ {
+ if (it2_ == it2_begin_ && begin_ == 0) {
+ it1_ = it1_end_;
+ BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
+ -- it1_;
+ current_ = 0;
+ } else {
+ -- it2_;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_end_ - it1_);
+ it1_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_begin_ + d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_end_ - it2_);
+ it2_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_begin_ + d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_ - it1_begin_);
+ it1_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_end_ - d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_ - it2_begin_);
+ it2_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_end_ - d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ if (current_ == 0 && it.current_ == 0) {
+ return it1_ - it.it1_;
+ } else if (current_ == 0 && it.current_ == 1) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
+ }
+
+ } else if (current_ == 1 && it.current_ == 0) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
+ }
+ } else /* if (current_ == 1 && it.current_ == 1) */ {
+ return it2_ - it.it2_;
+ }
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ if (triangular_type::other (index1 (), index2 ()))
+ return *it1_;
+ else
+ return type_traits<value_type>::conj (*it1_);
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ if (triangular_type::other (index1 (), index2 ()))
+ return *it2_;
+ else
+ return type_traits<value_type>::conj (*it2_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index2 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index1 ();
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index1 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index2 ();
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ begin_ = it.begin_;
+ end_ = it.end_;
+ current_ = it.current_;
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+ it1_ = it.it1_;
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
+ (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it - *this > 0;
+ }
+
+ private:
+ int begin_;
+ int end_;
+ int current_;
+ const_subiterator1_type it1_begin_;
+ const_subiterator1_type it1_end_;
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_begin_;
+ const_subiterator2_type it2_end_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<hermitian_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator2, value_type> {
+ public:
+ typedef typename subiterator2_type::value_type value_type;
+ typedef typename subiterator2_type::difference_type difference_type;
+ typedef typename subiterator2_type::reference reference;
+ typedef typename subiterator2_type::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator2_type &it2):
+ container_reference<self_type> (m), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it2_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ static value_type conj_;
+ };
+
+ template<class M, class TRI>
+ typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
+
+ // Specialization for temporary_traits
+ template <class M, class TRI>
+ struct vector_temporary_traits< hermitian_adaptor<M, TRI> >
+ : vector_temporary_traits< M > {} ;
+ template <class M, class TRI>
+ struct vector_temporary_traits< const hermitian_adaptor<M, TRI> >
+ : vector_temporary_traits< M > {} ;
+
+ template <class M, class TRI>
+ struct matrix_temporary_traits< hermitian_adaptor<M, TRI> >
+ : matrix_temporary_traits< M > {} ;
+ template <class M, class TRI>
+ struct matrix_temporary_traits< const hermitian_adaptor<M, TRI> >
+ : matrix_temporary_traits< M > {} ;
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch, David Bellot
+//
+// 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_IO_
+#define _BOOST_UBLAS_IO_
+
+// Only forward definition required to define stream operations
+#include <iosfwd>
+#include <sstream>
+#include <boost/numeric/ublas/matrix_expression.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief output stream operator for vector expressions
+ *
+ * Any vector expressions can be written to a standard output stream
+ * as defined in the C++ standard library. For example:
+ * \code
+ * vector<float> v1(3),v2(3);
+ * for(size_t i=0; i<3; i++)
+ * {
+ * v1(i) = i+0.2;
+ * v2(i) = i+0.3;
+ * }
+ * cout << v1+v2 << endl;
+ * \endcode
+ * will display the some of the 2 vectors like this:
+ * \code
+ * [3](0.5,2.5,4.5)
+ * \endcode
+ *
+ * \param os is a standard basic output stream
+ * \param v is a vector expression
+ * \return a reference to the resulting output stream
+ */
+ template<class E, class T, class VE>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os,
+ const vector_expression<VE> &v) {
+ typedef typename VE::size_type size_type;
+ size_type size = v ().size ();
+ std::basic_ostringstream<E, T, std::allocator<E> > s;
+ s.flags (os.flags ());
+ s.imbue (os.getloc ());
+ s.precision (os.precision ());
+ s << '[' << size << "](";
+ if (size > 0)
+ s << v () (0);
+ for (size_type i = 1; i < size; ++ i)
+ s << ',' << v () (i);
+ s << ')';
+ return os << s.str ().c_str ();
+ }
+
+ /** \brief input stream operator for vectors
+ *
+ * This is used to feed in vectors with data stored as an ASCII representation
+ * from a standard input stream.
+ *
+ * From a file or any valid stream, the format is:
+ * \c [<vector size>](<data1>,<data2>,...<dataN>) like for example:
+ * \code
+ * [5](1,2.1,3.2,3.14,0.2)
+ * \endcode
+ *
+ * You can use it like this
+ * \code
+ * my_input_stream >> my_vector;
+ * \endcode
+ *
+ * You can only put data into a valid \c vector<> not a \c vector_expression
+ *
+ * \param is is a standard basic input stream
+ * \param v is a vector
+ * \return a reference to the resulting input stream
+ */
+ template<class E, class T, class VT, class VA>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
+ vector<VT, VA> &v) {
+ typedef typename vector<VT, VA>::size_type size_type;
+ E ch;
+ size_type size;
+ if (is >> ch && ch != '[') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (is >> size >> ch && ch != ']') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ vector<VT, VA> s (size);
+ if (is >> ch && ch != '(') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ for (size_type i = 0; i < size; i ++) {
+ if (is >> s (i) >> ch && ch != ',') {
+ is.putback (ch);
+ if (i < size - 1)
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ if (is >> ch && ch != ')') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ }
+ }
+ if (! is.fail ())
+ v.swap (s);
+ }
+ return is;
+ }
+
+ /** \brief output stream operator for matrix expressions
+ *
+ * it outpus the content of a \f$(M \times N)\f$ matrix to a standard output
+ * stream using the following format:
+ * \c[<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>))
+ *
+ * For example:
+ * \code
+ * matrix<float> m(3,3) = scalar_matrix<float>(3,3,1.0) - diagonal_matrix<float>(3,3,1.0);
+ * cout << m << endl;
+ * \encode
+ * will display
+ * \code
+ * [3,3]((0,1,1),(1,0,1),(1,1,0))
+ * \endcode
+ * This output is made for storing and retrieving matrices in a simple way but you can
+ * easily recognize the following:
+ * \f[ \left( \begin{array}{ccc} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{array} \right) - \left( \begin{array}{ccc} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{array} \right) = \left( \begin{array}{ccc} 0 & 1 & 1\\ 1 & 0 & 1\\ 1 & 1 & 0 \end{array} \right) \f]
+ *
+ * \param os is a standard basic output stream
+ * \param m is a matrix expression
+ * \return a reference to the resulting output stream
+ */
+ template<class E, class T, class ME>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os,
+ const matrix_expression<ME> &m) {
+ typedef typename ME::size_type size_type;
+ size_type size1 = m ().size1 ();
+ size_type size2 = m ().size2 ();
+ std::basic_ostringstream<E, T, std::allocator<E> > s;
+ s.flags (os.flags ());
+ s.imbue (os.getloc ());
+ s.precision (os.precision ());
+ s << '[' << size1 << ',' << size2 << "](";
+ if (size1 > 0) {
+ s << '(' ;
+ if (size2 > 0)
+ s << m () (0, 0);
+ for (size_type j = 1; j < size2; ++ j)
+ s << ',' << m () (0, j);
+ s << ')';
+ }
+ for (size_type i = 1; i < size1; ++ i) {
+ s << ",(" ;
+ if (size2 > 0)
+ s << m () (i, 0);
+ for (size_type j = 1; j < size2; ++ j)
+ s << ',' << m () (i, j);
+ s << ')';
+ }
+ s << ')';
+ return os << s.str ().c_str ();
+ }
+
+ /** \brief input stream operator for matrices
+ *
+ * This is used to feed in matrices with data stored as an ASCII representation
+ * from a standard input stream.
+ *
+ * From a file or any valid standard stream, the format is:
+ * \c[<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>))
+ *
+ * You can use it like this
+ * \code
+ * my_input_stream >> my_matrix;
+ * \endcode
+ *
+ * You can only put data into a valid \c matrix<> not a \c matrix_expression
+ *
+ * \param is is a standard basic input stream
+ * \param m is a matrix
+ * \return a reference to the resulting input stream
+ */
+ template<class E, class T, class MT, class MF, class MA>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
+ matrix<MT, MF, MA> &m) {
+ typedef typename matrix<MT, MF, MA>::size_type size_type;
+ E ch;
+ size_type size1, size2;
+ if (is >> ch && ch != '[') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (is >> size1 >> ch && ch != ',') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (is >> size2 >> ch && ch != ']') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ matrix<MT, MF, MA> s (size1, size2);
+ if (is >> ch && ch != '(') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ for (size_type i = 0; i < size1; i ++) {
+ if (is >> ch && ch != '(') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ for (size_type j = 0; j < size2; j ++) {
+ if (is >> s (i, j) >> ch && ch != ',') {
+ is.putback (ch);
+ if (j < size2 - 1) {
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ }
+ if (is >> ch && ch != ')') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ if (is >> ch && ch != ',') {
+ is.putback (ch);
+ if (i < size1 - 1) {
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ }
+ if (is >> ch && ch != ')') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ }
+ }
+ if (! is.fail ())
+ m.swap (s);
+ }
+ return is;
+ }
+
+ /** \brief special input stream operator for symmetric matrices
+ *
+ * This is used to feed in symmetric matrices with data stored as an ASCII
+ * representation from a standard input stream.
+ *
+ * You can simply write your matrices in a file or any valid stream and read them again
+ * at a later time with this function. The format is the following:
+ * \code [<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>)) \endcode
+ *
+ * You can use it like this
+ * \code
+ * my_input_stream >> my_symmetric_matrix;
+ * \endcode
+ *
+ * You can only put data into a valid \c symmetric_matrix<>, not in a \c matrix_expression
+ * This function also checks that input data form a valid symmetric matrix
+ *
+ * \param is is a standard basic input stream
+ * \param m is a \c symmetric_matrix
+ * \return a reference to the resulting input stream
+ */
+ template<class E, class T, class MT, class MF1, class MF2, class MA>
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
+ symmetric_matrix<MT, MF1, MF2, MA> &m) {
+ typedef typename symmetric_matrix<MT, MF1, MF2, MA>::size_type size_type;
+ E ch;
+ size_type size1, size2;
+ MT value;
+ if (is >> ch && ch != '[') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (is >> size1 >> ch && ch != ',') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (is >> size2 >> ch && (size2 != size1 || ch != ']')) { // symmetric matrix must be square
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ symmetric_matrix<MT, MF1, MF2, MA> s (size1, size2);
+ if (is >> ch && ch != '(') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ } else if (! is.fail ()) {
+ for (size_type i = 0; i < size1; i ++) {
+ if (is >> ch && ch != '(') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ for (size_type j = 0; j < size2; j ++) {
+ if (is >> value >> ch && ch != ',') {
+ is.putback (ch);
+ if (j < size2 - 1) {
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ if (i <= j) {
+ // this is the first time we read this element - set the value
+ s(i,j) = value;
+ }
+ else if ( s(i,j) != value ) {
+ // matrix is not symmetric
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ if (is >> ch && ch != ')') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ if (is >> ch && ch != ',') {
+ is.putback (ch);
+ if (i < size1 - 1) {
+ is.setstate (std::ios_base::failbit);
+ break;
+ }
+ }
+ }
+ if (is >> ch && ch != ')') {
+ is.putback (ch);
+ is.setstate (std::ios_base::failbit);
+ }
+ }
+ if (! is.fail ())
+ m.swap (s);
+ }
+ return is;
+ }
+
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_LU_
+#define _BOOST_UBLAS_LU_
+
+#include <boost/numeric/ublas/operation.hpp>
+#include <boost/numeric/ublas/vector_proxy.hpp>
+#include <boost/numeric/ublas/matrix_proxy.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/triangular.hpp>
+
+// LU factorizations in the spirit of LAPACK and Golub & van Loan
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief
+ *
+ * \tparam T
+ * \tparam A
+ */
+ template<class T = std::size_t, class A = unbounded_array<T> >
+ class permutation_matrix:
+ public vector<T, A> {
+ public:
+ typedef vector<T, A> vector_type;
+ typedef typename vector_type::size_type size_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit
+ permutation_matrix (size_type size):
+ vector<T, A> (size) {
+ for (size_type i = 0; i < size; ++ i)
+ (*this) (i) = i;
+ }
+ BOOST_UBLAS_INLINE
+ explicit
+ permutation_matrix (const vector_type & init)
+ : vector_type(init)
+ { }
+ BOOST_UBLAS_INLINE
+ ~permutation_matrix () {}
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ permutation_matrix &operator = (const permutation_matrix &m) {
+ vector_type::operator = (m);
+ return *this;
+ }
+ };
+
+ template<class PM, class MV>
+ BOOST_UBLAS_INLINE
+ void swap_rows (const PM &pm, MV &mv, vector_tag) {
+ typedef typename PM::size_type size_type;
+ typedef typename MV::value_type value_type;
+
+ size_type size = pm.size ();
+ for (size_type i = 0; i < size; ++ i) {
+ if (i != pm (i))
+ std::swap (mv (i), mv (pm (i)));
+ }
+ }
+ template<class PM, class MV>
+ BOOST_UBLAS_INLINE
+ void swap_rows (const PM &pm, MV &mv, matrix_tag) {
+ typedef typename PM::size_type size_type;
+ typedef typename MV::value_type value_type;
+
+ size_type size = pm.size ();
+ for (size_type i = 0; i < size; ++ i) {
+ if (i != pm (i))
+ row (mv, i).swap (row (mv, pm (i)));
+ }
+ }
+ // Dispatcher
+ template<class PM, class MV>
+ BOOST_UBLAS_INLINE
+ void swap_rows (const PM &pm, MV &mv) {
+ swap_rows (pm, mv, typename MV::type_category ());
+ }
+
+ // LU factorization without pivoting
+ template<class M>
+ typename M::size_type lu_factorize (M &m) {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix_type cm (m);
+#endif
+ size_type singular = 0;
+ size_type size1 = m.size1 ();
+ size_type size2 = m.size2 ();
+ size_type size = (std::min) (size1, size2);
+ for (size_type i = 0; i < size; ++ i) {
+ matrix_column<M> mci (column (m, i));
+ matrix_row<M> mri (row (m, i));
+ if (m (i, i) != value_type/*zero*/()) {
+ value_type m_inv = value_type (1) / m (i, i);
+ project (mci, range (i + 1, size1)) *= m_inv;
+ } else if (singular == 0) {
+ singular = i + 1;
+ }
+ project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign (
+ outer_prod (project (mci, range (i + 1, size1)),
+ project (mri, range (i + 1, size2))));
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (singular != 0 ||
+ detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
+ triangular_adaptor<matrix_type, upper> (m)),
+ cm), internal_logic ());
+#endif
+ return singular;
+ }
+
+ // LU factorization with partial pivoting
+ template<class M, class PM>
+ typename M::size_type lu_factorize (M &m, PM &pm) {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix_type cm (m);
+#endif
+ size_type singular = 0;
+ size_type size1 = m.size1 ();
+ size_type size2 = m.size2 ();
+ size_type size = (std::min) (size1, size2);
+ for (size_type i = 0; i < size; ++ i) {
+ matrix_column<M> mci (column (m, i));
+ matrix_row<M> mri (row (m, i));
+ size_type i_norm_inf = i + index_norm_inf (project (mci, range (i, size1)));
+ BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
+ if (m (i_norm_inf, i) != value_type/*zero*/()) {
+ if (i_norm_inf != i) {
+ pm (i) = i_norm_inf;
+ row (m, i_norm_inf).swap (mri);
+ } else {
+ BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
+ }
+ value_type m_inv = value_type (1) / m (i, i);
+ project (mci, range (i + 1, size1)) *= m_inv;
+ } else if (singular == 0) {
+ singular = i + 1;
+ }
+ project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign (
+ outer_prod (project (mci, range (i + 1, size1)),
+ project (mri, range (i + 1, size2))));
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ swap_rows (pm, cm);
+ BOOST_UBLAS_CHECK (singular != 0 ||
+ detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
+ triangular_adaptor<matrix_type, upper> (m)), cm), internal_logic ());
+#endif
+ return singular;
+ }
+
+ template<class M, class PM>
+ typename M::size_type axpy_lu_factorize (M &m, PM &pm) {
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ typedef vector<value_type> vector_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix_type cm (m);
+#endif
+ size_type singular = 0;
+ size_type size1 = m.size1 ();
+ size_type size2 = m.size2 ();
+ size_type size = (std::min) (size1, size2);
+#ifndef BOOST_UBLAS_LU_WITH_INPLACE_SOLVE
+ matrix_type mr (m);
+ mr.assign (zero_matrix<value_type> (size1, size2));
+ vector_type v (size1);
+ for (size_type i = 0; i < size; ++ i) {
+ matrix_range<matrix_type> lrr (project (mr, range (0, i), range (0, i)));
+ vector_range<matrix_column<matrix_type> > urr (project (column (mr, i), range (0, i)));
+ urr.assign (solve (lrr, project (column (m, i), range (0, i)), unit_lower_tag ()));
+ project (v, range (i, size1)).assign (
+ project (column (m, i), range (i, size1)) -
+ axpy_prod<vector_type> (project (mr, range (i, size1), range (0, i)), urr));
+ size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1)));
+ BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
+ if (v (i_norm_inf) != value_type/*zero*/()) {
+ if (i_norm_inf != i) {
+ pm (i) = i_norm_inf;
+ std::swap (v (i_norm_inf), v (i));
+ project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2)));
+ } else {
+ BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
+ }
+ project (column (mr, i), range (i + 1, size1)).assign (
+ project (v, range (i + 1, size1)) / v (i));
+ if (i_norm_inf != i) {
+ project (row (mr, i_norm_inf), range (0, i)).swap (project (row (mr, i), range (0, i)));
+ }
+ } else if (singular == 0) {
+ singular = i + 1;
+ }
+ mr (i, i) = v (i);
+ }
+ m.assign (mr);
+#else
+ matrix_type lr (m);
+ matrix_type ur (m);
+ lr.assign (identity_matrix<value_type> (size1, size2));
+ ur.assign (zero_matrix<value_type> (size1, size2));
+ vector_type v (size1);
+ for (size_type i = 0; i < size; ++ i) {
+ matrix_range<matrix_type> lrr (project (lr, range (0, i), range (0, i)));
+ vector_range<matrix_column<matrix_type> > urr (project (column (ur, i), range (0, i)));
+ urr.assign (project (column (m, i), range (0, i)));
+ inplace_solve (lrr, urr, unit_lower_tag ());
+ project (v, range (i, size1)).assign (
+ project (column (m, i), range (i, size1)) -
+ axpy_prod<vector_type> (project (lr, range (i, size1), range (0, i)), urr));
+ size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1)));
+ BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ());
+ if (v (i_norm_inf) != value_type/*zero*/()) {
+ if (i_norm_inf != i) {
+ pm (i) = i_norm_inf;
+ std::swap (v (i_norm_inf), v (i));
+ project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2)));
+ } else {
+ BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ());
+ }
+ project (column (lr, i), range (i + 1, size1)).assign (
+ project (v, range (i + 1, size1)) / v (i));
+ if (i_norm_inf != i) {
+ project (row (lr, i_norm_inf), range (0, i)).swap (project (row (lr, i), range (0, i)));
+ }
+ } else if (singular == 0) {
+ singular = i + 1;
+ }
+ ur (i, i) = v (i);
+ }
+ m.assign (triangular_adaptor<matrix_type, strict_lower> (lr) +
+ triangular_adaptor<matrix_type, upper> (ur));
+#endif
+#if BOOST_UBLAS_TYPE_CHECK
+ swap_rows (pm, cm);
+ BOOST_UBLAS_CHECK (singular != 0 ||
+ detail::expression_type_check (prod (triangular_adaptor<matrix_type, unit_lower> (m),
+ triangular_adaptor<matrix_type, upper> (m)), cm), internal_logic ());
+#endif
+ return singular;
+ }
+
+ // LU substitution
+ template<class M, class E>
+ void lu_substitute (const M &m, vector_expression<E> &e) {
+ typedef const M const_matrix_type;
+ typedef vector<typename E::value_type> vector_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ vector_type cv1 (e);
+#endif
+ inplace_solve (m, e, unit_lower_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, unit_lower> (m), e), cv1), internal_logic ());
+ vector_type cv2 (e);
+#endif
+ inplace_solve (m, e, upper_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, upper> (m), e), cv2), internal_logic ());
+#endif
+ }
+ template<class M, class E>
+ void lu_substitute (const M &m, matrix_expression<E> &e) {
+ typedef const M const_matrix_type;
+ typedef matrix<typename E::value_type> matrix_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix_type cm1 (e);
+#endif
+ inplace_solve (m, e, unit_lower_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, unit_lower> (m), e), cm1), internal_logic ());
+ matrix_type cm2 (e);
+#endif
+ inplace_solve (m, e, upper_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor<const_matrix_type, upper> (m), e), cm2), internal_logic ());
+#endif
+ }
+ template<class M, class PMT, class PMA, class MV>
+ void lu_substitute (const M &m, const permutation_matrix<PMT, PMA> &pm, MV &mv) {
+ swap_rows (pm, mv);
+ lu_substitute (m, mv);
+ }
+ template<class E, class M>
+ void lu_substitute (vector_expression<E> &e, const M &m) {
+ typedef const M const_matrix_type;
+ typedef vector<typename E::value_type> vector_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ vector_type cv1 (e);
+#endif
+ inplace_solve (e, m, upper_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, upper> (m)), cv1), internal_logic ());
+ vector_type cv2 (e);
+#endif
+ inplace_solve (e, m, unit_lower_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, unit_lower> (m)), cv2), internal_logic ());
+#endif
+ }
+ template<class E, class M>
+ void lu_substitute (matrix_expression<E> &e, const M &m) {
+ typedef const M const_matrix_type;
+ typedef matrix<typename E::value_type> matrix_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix_type cm1 (e);
+#endif
+ inplace_solve (e, m, upper_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, upper> (m)), cm1), internal_logic ());
+ matrix_type cm2 (e);
+#endif
+ inplace_solve (e, m, unit_lower_tag ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor<const_matrix_type, unit_lower> (m)), cm2), internal_logic ());
+#endif
+ }
+ template<class MV, class M, class PMT, class PMA>
+ void lu_substitute (MV &mv, const M &m, const permutation_matrix<PMT, PMA> &pm) {
+ swap_rows (pm, mv);
+ lu_substitute (mv, m);
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch, Gunter Winkler, David Bellot
+//
+// 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_MATRIX_
+#define _BOOST_UBLAS_MATRIX_
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix_expression.hpp>
+#include <boost/numeric/ublas/detail/matrix_assign.hpp>
+#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/nvp.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric {
+
+ /** \brief main namespace of uBLAS.
+ *
+ * Use this namespace for all operations with uBLAS. It can also be abbreviated with
+ * \code namespace ublas = boost::numeric::ublas; \endcode
+ *
+ * A common practice is to bring this namespace into the current scope with
+ * \code using namespace boost::numeric::ublas; \endcode.
+ *
+ * However, be warned that using the ublas namespace and the std::vector at the same time can lead to the compiler to confusion.
+ * The solution is simply to prefix each ublas vector like \c boost::numeric::ublas::vector<T>. If you think it's too long to
+ * write, you can define a new namespace like \c namespace ublas = boost::numeric::ublas and then just declare your vectors
+ * with \c ublas::vector<T>. STL vectors will be declared as vector<T>. No need to prefix with \c std::
+ */
+ namespace ublas {
+
+ namespace detail {
+ using namespace boost::numeric::ublas;
+
+ // Matrix resizing algorithm
+ template <class L, class M>
+ BOOST_UBLAS_INLINE
+ void matrix_resize_preserve (M& m, M& temporary) {
+ typedef L layout_type;
+ typedef typename M::size_type size_type;
+ const size_type msize1 (m.size1 ()); // original size
+ const size_type msize2 (m.size2 ());
+ const size_type size1 (temporary.size1 ()); // new size is specified by temporary
+ const size_type size2 (temporary.size2 ());
+ // Common elements to preserve
+ const size_type size1_min = (std::min) (size1, msize1);
+ const size_type size2_min = (std::min) (size2, msize2);
+ // Order for major and minor sizes
+ const size_type major_size = layout_type::size_M (size1_min, size2_min);
+ const size_type minor_size = layout_type::size_m (size1_min, size2_min);
+ // Indexing copy over major
+ for (size_type major = 0; major != major_size; ++major) {
+ for (size_type minor = 0; minor != minor_size; ++minor) {
+ // find indexes - use invertability of element_ functions
+ const size_type i1 = layout_type::index_M(major, minor);
+ const size_type i2 = layout_type::index_m(major, minor);
+ temporary.data () [layout_type::element (i1, size1, i2, size2)] =
+ m.data() [layout_type::element (i1, msize1, i2, msize2)];
+ }
+ }
+ m.assign_temporary (temporary);
+ }
+ }
+
+ /** \brief A dense matrix of values of type \c T.
+ *
+ * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$ m_{i,j} \f$ is mapped to
+ * the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$ (i + j.m) \f$-th element of
+ * the container for column major orientation. In a dense matrix all elements are represented in memory in a
+ * contiguous chunk of memory by definition.
+ *
+ * Orientation and storage can also be specified, otherwise a \c row_major and \c unbounded_array are used. It is \b not
+ * required by the storage to initialize elements of the matrix.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
+ * \tparam A the type of Storage array. Default is \c unbounded_array
+ */
+ template<class T, class L, class A>
+ class matrix:
+ public matrix_container<matrix<T, L, A> > {
+
+ typedef T *pointer;
+ typedef L layout_type;
+ typedef matrix<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef A array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, A> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef dense_tag storage_category;
+ // This could be better for performance,
+ // typedef typename unknown_orientation_tag orientation_category;
+ // but others depend on the orientation information...
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+
+ /// Default dense matrix constructor. Make a dense matrix of size (0,0)
+ BOOST_UBLAS_INLINE
+ matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ () {}
+
+ /** Dense matrix constructor with defined size
+ * \param size1 number of rows
+ * \param size2 number of columns
+ */
+ BOOST_UBLAS_INLINE
+ matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
+ }
+
+ /** Dense matrix constructor with defined size a initial value for all the matrix elements
+ * \param size1 number of rows
+ * \param size2 number of columns
+ * \param init initial value assigned to all elements
+ */
+ matrix (size_type size1, size_type size2, const value_type &init):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2), init) {
+ }
+
+ /** Dense matrix constructor with defined size and an initial data array
+ * \param size1 number of rows
+ * \param size2 number of columns
+ * \param data array to copy into the matrix. Must have the same dimension as the matrix
+ */
+ BOOST_UBLAS_INLINE
+ matrix (size_type size1, size_type size2, const array_type &data):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (data) {}
+
+ /** Copy-constructor of a dense matrix
+ * \param m is a dense matrix
+ */
+ BOOST_UBLAS_INLINE
+ matrix (const matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
+
+ /** Copy-constructor of a dense matrix from a matrix expression
+ * \param ae is a matrix expression
+ */
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix (const matrix_expression<AE> &ae):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ /** Return the number of rows of the matrix
+ * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a matrix
+ */
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+
+ /** Return the number of colums of the matrix
+ * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a matrix
+ */
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Storage accessors
+ /** Return a constant reference to the internal storage of a dense matrix, i.e. the raw data
+ * It's type depends on the type used by the matrix to store its data
+ */
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ /** Return a reference to the internal storage of a dense matrix, i.e. the raw data
+ * It's type depends on the type used by the matrix to store its data
+ */
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ /** Resize a matrix to new dimensions
+ * If data are preserved, then if the size if bigger at least on one dimension, extra values are filled with zeros.
+ * If data are not preserved, then nothing has to be assumed regarding the content of the matrix after resizing.
+ * \param size1 the new number of rows
+ * \param size2 the new number of colums
+ * \param preserve a boolean to say if one wants the data to be preserved during the resizing. Default is true.
+ */
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ if (preserve) {
+ self_type temporary (size1, size2);
+ detail::matrix_resize_preserve<layout_type> (*this, temporary);
+ }
+ else {
+ data ().resize (layout_type::storage_size (size1, size2));
+ size1_ = size1;
+ size2_ = size2;
+ }
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return data () [layout_type::element (i, size1_, j, size2_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ return data () [layout_type::element (i, size1_, j, size2_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return at_element (i, j);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (at_element (i, j) = t);
+ }
+ void erase_element (size_type i, size_type j) {
+ at_element (i, j) = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ std::fill (data ().begin (), data ().end (), value_type/*zero*/());
+ }
+
+ // Assignment
+#ifdef BOOST_UBLAS_MOVE_SEMANTICS
+
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ matrix &operator = (matrix m) {
+ assign_temporary(m);
+ return *this;
+ }
+#else
+ BOOST_UBLAS_INLINE
+ matrix &operator = (const matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ return *this;
+ }
+#endif
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ matrix &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix &assign_temporary (matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ matrix &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ matrix &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix &m1, matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // 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_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, i, j);
+#else
+ return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, i, j);
+#else
+ return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename matrix::value_type value_type;
+ typedef typename matrix::difference_type difference_type;
+ typedef typename matrix::const_reference reference;
+ typedef const typename matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+
+ friend class iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename matrix::value_type value_type;
+ typedef typename matrix::difference_type difference_type;
+ typedef typename matrix::reference reference;
+ typedef typename matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator_type &it):
+ container_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ self_type &m = (*this) ();
+ return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ self_type &m = (*this) ();
+ return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename matrix::value_type value_type;
+ typedef typename matrix::difference_type difference_type;
+ typedef typename matrix::const_reference reference;
+ typedef const typename matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+
+ friend class iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename matrix::value_type value_type;
+ typedef typename matrix::difference_type difference_type;
+ typedef typename matrix::reference reference;
+ typedef typename matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator_type &it):
+ container_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ self_type &m = (*this) ();
+ return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ self_type &m = (*this) ();
+ return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("data",data_);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ };
+
+ /** \brief A dense matrix of values of type \c T with a variable size bounded to a maximum of \f$M\f$ by \f$N\f$.
+ *
+ * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$m_{i,j}\f$ is mapped
+ * to the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$(i + j.m)\f$-th element
+ * of the container for column major orientation. Finally in a dense matrix all elements are represented in memory
+ * in a contiguous chunk of memory.
+ *
+ * Orientation can be specified. Default is \c row_major
+ * The default constructor creates the matrix with size \f$M\f$ by \f$N\f$. Elements are constructed by the storage
+ * type \c bounded_array, which need not initialise their value.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam M maximum and default number of rows (if not specified at construction)
+ * \tparam N maximum and default number of columns (if not specified at construction)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
+ */
+ template<class T, std::size_t M, std::size_t N, class L>
+ class bounded_matrix:
+ public matrix<T, L, bounded_array<T, M * N> > {
+
+ typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
+ public:
+ typedef typename matrix_type::size_type size_type;
+ static const size_type max_size1 = M;
+ static const size_type max_size2 = N;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ bounded_matrix ():
+ matrix_type (M, N) {}
+ BOOST_UBLAS_INLINE
+ bounded_matrix (size_type size1, size_type size2):
+ matrix_type (size1, size2) {}
+ BOOST_UBLAS_INLINE
+ bounded_matrix (const bounded_matrix &m):
+ matrix_type (m) {}
+ template<class A2> // Allow matrix<T, L, bounded_array<M,N> > construction
+ BOOST_UBLAS_INLINE
+ bounded_matrix (const matrix<T, L, A2> &m):
+ matrix_type (m) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ bounded_matrix (const matrix_expression<AE> &ae):
+ matrix_type (ae) {}
+ BOOST_UBLAS_INLINE
+ ~bounded_matrix () {}
+
+ // Assignment
+#ifdef BOOST_UBLAS_MOVE_SEMANTICS
+
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ bounded_matrix &operator = (bounded_matrix m) {
+ matrix_type::operator = (m);
+ return *this;
+ }
+#else
+ BOOST_UBLAS_INLINE
+ bounded_matrix &operator = (const bounded_matrix &m) {
+ matrix_type::operator = (m);
+ return *this;
+ }
+#endif
+ template<class L2, class A2> // Generic matrix assignment
+ BOOST_UBLAS_INLINE
+ bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
+ matrix_type::operator = (m);
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ bounded_matrix &operator = (const matrix_container<C> &m) {
+ matrix_type::operator = (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ bounded_matrix &operator = (const matrix_expression<AE> &ae) {
+ matrix_type::operator = (ae);
+ return *this;
+ }
+ };
+
+ /** \brief A dense matrix of values of type \c T stored as a vector of vectors.
+ *
+ * Rows or columns are not stored into contiguous chunks of memory but data inside rows (or columns) are.
+ * Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used.
+ * The data is stored as a vector of vectors, meaning that rows or columns might not be stored into contiguous chunks
+ * of memory. Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used.
+ * The storage type defaults to \c unbounded_array<unbounded_array<T>> and orientation is \c row_major. It is \b not
+ * required by the storage to initialize elements of the matrix. For a \f$(m \times n)\f$-dimensional matrix and
+ * \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the
+ * container for row major orientation or the \f$(i + j.m)\f$-th element of the container for column major orientation.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major
+ * \tparam A the type of Storage array. By default, it is an \unbounded_array<unbounder_array<T>>
+ */
+ template<class T, class L, class A>
+ class vector_of_vector:
+ public matrix_container<vector_of_vector<T, L, A> > {
+
+ typedef T *pointer;
+ typedef L layout_type;
+ typedef vector_of_vector<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef A array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, typename A::value_type> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef dense_tag storage_category;
+ // This could be better for performance,
+ // typedef typename unknown_orientation_tag orientation_category;
+ // but others depend on the orientation information...
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_of_vector ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ (1) {}
+ BOOST_UBLAS_INLINE
+ vector_of_vector (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (1) {
+ resize (size1, size2, true);
+ }
+ BOOST_UBLAS_INLINE
+ vector_of_vector (const vector_of_vector &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector (const matrix_expression<AE> &ae):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
+ for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
+ data ()[k].resize (layout_type::size_m (size1_, size2_));
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ size1_ = size1;
+ size2_ = size2;
+ if (preserve)
+ data ().resize (layout_type::size_M (size1, size2) + 1, typename array_type::value_type ());
+ else
+ data ().resize (layout_type::size_M (size1, size2) + 1);
+ for (size_type k = 0; k < layout_type::size_M (size1, size2); ++ k) {
+ if (preserve)
+ data () [k].resize (layout_type::size_m (size1, size2), value_type ());
+ else
+ data () [k].resize (layout_type::size_m (size1, size2));
+ }
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return at_element (i, j);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (at_element (i, j) = t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ at_element (i, j) = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
+ std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ vector_of_vector &operator = (const vector_of_vector &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ vector_of_vector &assign_temporary (vector_of_vector &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ vector_of_vector &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ vector_of_vector &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ vector_of_vector &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_of_vector& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_of_vector& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (vector_of_vector &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use the vector iterator
+ typedef typename A::value_type::const_iterator const_subiterator_type;
+ typedef typename A::value_type::iterator subiterator_type;
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int /*rank*/, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, i, j);
+#else
+ return iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int /*rank*/, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, i, j);
+#else
+ return iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<vector_of_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename vector_of_vector::value_type value_type;
+ typedef typename vector_of_vector::difference_type difference_type;
+ typedef typename vector_of_vector::const_reference reference;
+ typedef const typename vector_of_vector::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ i_;
+ const self_type &m = (*this) ();
+ if (layout_type::fast_i ())
+ ++ it_;
+ else
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- i_;
+ const self_type &m = (*this) ();
+ if (layout_type::fast_i ())
+ -- it_;
+ else
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ i_ += n;
+ const self_type &m = (*this) ();
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ i_ -= n;
+ const self_type &m = (*this) ();
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return index1 () - it.index1 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_subiterator_type it_;
+
+ friend class iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<vector_of_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename vector_of_vector::value_type value_type;
+ typedef typename vector_of_vector::difference_type difference_type;
+ typedef typename vector_of_vector::reference reference;
+ typedef typename vector_of_vector::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
+ container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ i_;
+ self_type &m = (*this) ();
+ if (layout_type::fast_i ())
+ ++ it_;
+ else
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- i_;
+ self_type &m = (*this) ();
+ if (layout_type::fast_i ())
+ -- it_;
+ else
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ i_ += n;
+ self_type &m = (*this) ();
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ i_ -= n;
+ self_type &m = (*this) ();
+ it_ = m.find1 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return index1 () - it.index1 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<vector_of_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename vector_of_vector::value_type value_type;
+ typedef typename vector_of_vector::difference_type difference_type;
+ typedef typename vector_of_vector::const_reference reference;
+ typedef const typename vector_of_vector::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ j_;
+ const self_type &m = (*this) ();
+ if (layout_type::fast_j ())
+ ++ it_;
+ else
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- j_;
+ const self_type &m = (*this) ();
+ if (layout_type::fast_j ())
+ -- it_;
+ else
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ j_ += n;
+ const self_type &m = (*this) ();
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ j_ -= n;
+ const self_type &m = (*this) ();
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return index2 () - it.index2 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_subiterator_type it_;
+
+ friend class iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<vector_of_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename vector_of_vector::value_type value_type;
+ typedef typename vector_of_vector::difference_type difference_type;
+ typedef typename vector_of_vector::reference reference;
+ typedef typename vector_of_vector::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
+ container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ j_;
+ self_type &m = (*this) ();
+ if (layout_type::fast_j ())
+ ++ it_;
+ else
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- j_;
+ self_type &m = (*this) ();
+ if (layout_type::fast_j ())
+ -- it_;
+ else
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ j_ += n;
+ self_type &m = (*this) ();
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ j_ -= n;
+ self_type &m = (*this) ();
+ it_ = m.find2 (1, i_, j_).it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return index2 () - it.index2 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
+ return it_ < it.it_;
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("data",data_);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ };
+
+
+ /** \brief A matrix with all values of type \c T equal to zero
+ *
+ * Changing values does not affect the matrix, however assigning it to a normal matrix will put zero
+ * everywhere in the target matrix. All accesses are constant time, due to the trivial value.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam ALLOC an allocator for storing the zero element. By default, a standar allocator is used.
+ */
+ template<class T, class ALLOC>
+ class zero_matrix:
+ public matrix_container<zero_matrix<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef zero_matrix<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef sparse_tag storage_category;
+ typedef unknown_orientation_tag orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ zero_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0) {}
+ BOOST_UBLAS_INLINE
+ zero_matrix (size_type size):
+ matrix_container<self_type> (),
+ size1_ (size), size2_ (size) {}
+ BOOST_UBLAS_INLINE
+ zero_matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2) {}
+ BOOST_UBLAS_INLINE
+ zero_matrix (const zero_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ size1_ = size;
+ size2_ = size;
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
+ size1_ = size1;
+ size2_ = size2;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type /* i */, size_type /* j */) const {
+ return zero_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ zero_matrix &operator = (const zero_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ zero_matrix &assign_temporary (zero_matrix &m) {
+ swap (m);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (zero_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (zero_matrix &m1, zero_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ public:
+ class const_iterator1;
+ class const_iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
+ return const_iterator1 (*this);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
+ return const_iterator2 (*this);
+ }
+
+ class const_iterator1:
+ public container_const_reference<zero_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename zero_matrix::value_type value_type;
+ typedef typename zero_matrix::difference_type difference_type;
+ typedef typename zero_matrix::const_reference reference;
+ typedef typename zero_matrix::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m):
+ container_const_reference<self_type> (m) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return zero_; // arbitary return value
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return const_iterator2 ((*this) ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return const_iterator2 ((*this) ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return 0; // arbitary return value
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return 0; // arbitary return value
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ detail::ignore_unused_variable_warning(it);
+ return true;
+ }
+ };
+
+ typedef const_iterator1 iterator1;
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return const_iterator1 (*this);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return const_iterator1 (*this);
+ }
+
+ class const_iterator2:
+ public container_const_reference<zero_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename zero_matrix::value_type value_type;
+ typedef typename zero_matrix::difference_type difference_type;
+ typedef typename zero_matrix::const_reference reference;
+ typedef typename zero_matrix::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m):
+ container_const_reference<self_type> (m) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return zero_; // arbitary return value
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return const_iterator1 ((*this) ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return const_iterator1 ((*this) ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return 0; // arbitary return value
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return 0; // arbitary return value
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ detail::ignore_unused_variable_warning(it);
+ return true;
+ }
+ };
+
+ typedef const_iterator2 iterator2;
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ static const value_type zero_;
+ };
+
+ template<class T, class ALLOC>
+ const typename zero_matrix<T, ALLOC>::value_type zero_matrix<T, ALLOC>::zero_ = T(/*zero*/);
+
+ /** \brief An identity matrix with values of type \c T
+ *
+ * Elements or cordinates \f$(i,i)\f$ are equal to 1 (one) and all others to 0 (zero).
+ * Changing values does not affect the matrix, however assigning it to a normal matrix will
+ * make the matrix equal to an identity matrix. All accesses are constant du to the trivial values.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam ALLOC an allocator for storing the zeros and one elements. By default, a standar allocator is used.
+ */
+ template<class T, class ALLOC>
+ class identity_matrix:
+ public matrix_container<identity_matrix<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef identity_matrix<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef sparse_tag storage_category;
+ typedef unknown_orientation_tag orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ identity_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), size_common_ (0) {}
+ BOOST_UBLAS_INLINE
+ identity_matrix (size_type size):
+ matrix_container<self_type> (),
+ size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
+ BOOST_UBLAS_INLINE
+ identity_matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
+ BOOST_UBLAS_INLINE
+ identity_matrix (const identity_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ size1_ = size;
+ size2_ = size;
+ size_common_ = ((std::min)(size1_, size2_));
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
+ size1_ = size1;
+ size2_ = size2;
+ size_common_ = ((std::min)(size1_, size2_));
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ if (i == j)
+ return one_;
+ else
+ return zero_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ identity_matrix &operator = (const identity_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ size_common_ = m.size_common_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ identity_matrix &assign_temporary (identity_matrix &m) {
+ swap (m);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (identity_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ std::swap (size_common_, m.size_common_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (identity_matrix &m1, identity_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use an index
+ typedef size_type const_subiterator_type;
+
+ public:
+ class const_iterator1;
+ class const_iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ i = (std::max) (i, j);
+ i = (std::min) (i, j + 1);
+ }
+ return const_iterator1 (*this, i);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (rank == 1) {
+ j = (std::max) (j, i);
+ j = (std::min) (j, i + 1);
+ }
+ return const_iterator2 (*this, j);
+ }
+
+
+ class const_iterator1:
+ public container_const_reference<identity_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename identity_matrix::value_type value_type;
+ typedef typename identity_matrix::difference_type difference_type;
+ typedef typename identity_matrix::const_reference reference;
+ typedef typename identity_matrix::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
+ ++it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
+ --it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return one_;
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return const_iterator2 ((*this) (), it_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return const_iterator2 ((*this) (), it_ + 1);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+
+ typedef const_iterator1 iterator1;
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return const_iterator1 (*this, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return const_iterator1 (*this, size_common_);
+ }
+
+ class const_iterator2:
+ public container_const_reference<identity_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename identity_matrix::value_type value_type;
+ typedef typename identity_matrix::difference_type difference_type;
+ typedef typename identity_matrix::const_reference reference;
+ typedef typename identity_matrix::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
+ ++it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
+ --it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return one_;
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return const_iterator1 ((*this) (), it_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return const_iterator1 ((*this) (), it_ + 1);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+
+ typedef const_iterator2 iterator2;
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return const_iterator2 (*this, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return const_iterator2 (*this, size_common_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ size_common_ = ((std::min)(size1_, size2_));
+ }
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ size_type size_common_;
+ static const value_type zero_;
+ static const value_type one_;
+ };
+
+ template<class T, class ALLOC>
+ const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::zero_ = T(/*zero*/);
+ template<class T, class ALLOC>
+ const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here
+
+
+ /** \brief A matrix with all values of type \c T equal to the same value
+ *
+ * Changing one value has the effect of changing all the values. Assigning it to a normal matrix will copy
+ * the same value everywhere in this matrix. All accesses are constant time, due to the trivial value.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam ALLOC an allocator for storing the unique value. By default, a standar allocator is used.
+ */
+ template<class T, class ALLOC>
+ class scalar_matrix:
+ public matrix_container<scalar_matrix<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef scalar_matrix<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef dense_tag storage_category;
+ typedef unknown_orientation_tag orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ scalar_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), value_ () {}
+ BOOST_UBLAS_INLINE
+ scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), value_ (value) {}
+ BOOST_UBLAS_INLINE
+ scalar_matrix (const scalar_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
+ size1_ = size1;
+ size2_ = size2;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type /*i*/, size_type /*j*/) const {
+ return value_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ scalar_matrix &operator = (const scalar_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ value_ = m.value_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ scalar_matrix &assign_temporary (scalar_matrix &m) {
+ swap (m);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (scalar_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ std::swap (value_, m.value_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use an index
+ typedef size_type const_subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class const_iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
+ return const_iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
+ return const_iterator2 (*this, i, j);
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<scalar_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename scalar_matrix::value_type value_type;
+ typedef typename scalar_matrix::difference_type difference_type;
+ typedef typename scalar_matrix::const_reference reference;
+ typedef typename scalar_matrix::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
+ container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (index1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const scalar_matrix &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const scalar_matrix &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<scalar_matrix>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator_type it1_;
+ const_subiterator_type it2_;
+ };
+
+ typedef const_iterator1 iterator1;
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<scalar_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename scalar_matrix::value_type value_type;
+ typedef typename scalar_matrix::difference_type difference_type;
+ typedef typename scalar_matrix::const_reference reference;
+ typedef typename scalar_matrix::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
+ container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return (*this) () (index1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const scalar_matrix &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const scalar_matrix &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<scalar_matrix>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator_type it1_;
+ const_subiterator_type it2_;
+ };
+
+ typedef const_iterator2 iterator2;
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+
+ ar & serialization::make_nvp("value", value_);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ value_type value_;
+ };
+
+
+ /** \brief An array based matrix class which size is defined at type specification or object instanciation
+ *
+ * This matrix is directly based on a predefined C-style arry of data, thus providing the fastest
+ * implementation possible. The constraint is that dimensions of the matrix must be specified at
+ * the instanciation or the type specification.
+ *
+ * For instance, \code typedef c_matrix<double,4,4> my_4by4_matrix \endcode
+ * defines a 4 by 4 double-precision matrix. You can also instantiate it directly with
+ * \code c_matrix<int,8,5> my_fast_matrix \endcode. This will make a 8 by 5 integer matrix. The
+ * price to pay for this speed is that you cannot resize it to a size larger than the one defined
+ * in the template parameters. In the previous example, a size of 4 by 5 or 3 by 2 is acceptable,
+ * but a new size of 9 by 5 or even 10 by 10 will raise a bad_size() exception.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam N the default maximum number of rows
+ * \tparam M the default maximum number of columns
+ */
+ template<class T, std::size_t N, std::size_t M>
+ class c_matrix:
+ public matrix_container<c_matrix<T, N, M> > {
+
+ typedef c_matrix<T, N, M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef T *pointer;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef c_vector<T, N * M> vector_temporary_type; // vector able to store all elements of c_matrix
+ typedef self_type matrix_temporary_type;
+ typedef dense_tag storage_category;
+ // This could be better for performance,
+ // typedef typename unknown_orientation_tag orientation_category;
+ // but others depend on the orientation information...
+ typedef row_major_tag orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ c_matrix ():
+ size1_ (N), size2_ (M) /* , data_ () */ {
+ }
+ BOOST_UBLAS_INLINE
+ c_matrix (size_type size1, size_type size2):
+ size1_ (size1), size2_ (size2) /* , data_ () */ {
+ if (size1_ > N || size2_ > M)
+ bad_size ().raise ();
+ }
+ BOOST_UBLAS_INLINE
+ c_matrix (const c_matrix &m):
+ size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
+ if (size1_ > N || size2_ > M)
+ bad_size ().raise ();
+ assign(m);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix (const matrix_expression<AE> &ae):
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
+ if (size1_ > N || size2_ > M)
+ bad_size ().raise ();
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer data () const {
+ return reinterpret_cast<const_pointer> (data_);
+ }
+ BOOST_UBLAS_INLINE
+ pointer data () {
+ return reinterpret_cast<pointer> (data_);
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ if (size1 > N || size2 > M)
+ bad_size ().raise ();
+ if (preserve) {
+ self_type temporary (size1, size2);
+ // Common elements to preserve
+ const size_type size1_min = (std::min) (size1, size1_);
+ const size_type size2_min = (std::min) (size2, size2_);
+ for (size_type i = 0; i != size1_min; ++i) { // indexing copy over major
+ for (size_type j = 0; j != size2_min; ++j) {
+ temporary.data_[i][j] = data_[i][j];
+ }
+ }
+ assign_temporary (temporary);
+ }
+ else {
+ size1_ = size1;
+ size2_ = size2;
+ }
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+ return data_ [i] [j];
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+ return data_ [i] [j];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return at_element (i, j);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (at_element (i, j) = t);
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ for (size_type i = 0; i < size1_; ++ i)
+ std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
+ }
+
+ // Assignment
+#ifdef BOOST_UBLAS_MOVE_SEMANTICS
+
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ c_matrix &operator = (c_matrix m) {
+ assign_temporary(m);
+ return *this;
+ }
+#else
+ BOOST_UBLAS_INLINE
+ c_matrix &operator = (const c_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ for (size_type i = 0; i < m.size1_; ++ i)
+ std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
+ return *this;
+ }
+#endif
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_matrix &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ c_matrix &assign_temporary (c_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_matrix &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_matrix &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ c_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ c_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (c_matrix &m) {
+ if (this != &m) {
+ BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
+ BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ for (size_type i = 0; i < size1_; ++ i)
+ std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (c_matrix &m1, c_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use pointers for iterator
+ typedef const_pointer const_subiterator_type;
+ typedef pointer subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, &data_ [i] [j]);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, i, j);
+#else
+ return iterator1 (*this, &data_ [i] [j]);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, &data_ [i] [j]);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, i, j);
+#else
+ return iterator2 (*this, &data_ [i] [j]);
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<c_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename c_matrix::difference_type difference_type;
+ typedef typename c_matrix::value_type value_type;
+ typedef typename c_matrix::const_reference reference;
+ typedef typename c_matrix::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ it_ += M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ it_ -= M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n * M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n * M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return (it_ - it.it_) / M;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin1 ().it_) / M;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin1 ().it_) % M;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+
+ friend class iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<c_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+
+ typedef typename c_matrix::difference_type difference_type;
+ typedef typename c_matrix::value_type value_type;
+ typedef typename c_matrix::reference reference;
+ typedef typename c_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator_type &it):
+ container_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ it_ += M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ it_ -= M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it_ += n * M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it_ -= n * M;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return (it_ - it.it_) / M;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin1 ().it_) / M;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin1 ().it_) % M;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<c_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename c_matrix::difference_type difference_type;
+ typedef typename c_matrix::value_type value_type;
+ typedef typename c_matrix::const_reference reference;
+ typedef typename c_matrix::const_reference pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin2 ().it_) / M;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin2 ().it_) % M;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+
+ friend class iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<c_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename c_matrix::difference_type difference_type;
+ typedef typename c_matrix::value_type value_type;
+ typedef typename c_matrix::reference reference;
+ typedef typename c_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator_type &it):
+ container_reference<self_type> (m), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin2 ().it_) / M;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ const self_type &m = (*this) ();
+ return (it_ - m.begin2 ().it_) % M;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ // could probably use make_array( &(data[0][0]), N*M )
+ ar & serialization::make_array(data_, N);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ value_type data_ [N] [M];
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_MATRIX_EXPRESSION_
+#define _BOOST_UBLAS_MATRIX_EXPRESSION_
+
+#include <boost/numeric/ublas/vector_expression.hpp>
+
+// Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
+// Iterators based on ideas of Jeremy Siek
+//
+// Classes that model the Matrix Expression concept
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class E>
+ class matrix_reference:
+ public matrix_expression<matrix_reference<E> > {
+
+ typedef matrix_reference<E> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename E::value_type value_type;
+ typedef typename E::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_reference,
+ typename E::reference>::type reference;
+ typedef E referred_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename E::orientation_category orientation_category;
+ typedef typename E::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_reference (referred_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size2 ();
+ }
+
+ public:
+ // Expression accessors - const correct
+ BOOST_UBLAS_INLINE
+ const referred_type &expression () const {
+ return e_;
+ }
+ BOOST_UBLAS_INLINE
+ referred_type &expression () {
+ return e_;
+ }
+
+ public:
+ // Element access
+#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return expression () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return expression () (i, j);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ return expression () (i, j);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator = (const matrix_reference &m) {
+ expression ().operator = (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator = (const matrix_expression<AE> &ae) {
+ expression ().operator = (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &assign (const matrix_expression<AE> &ae) {
+ expression ().assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator += (const matrix_expression<AE> &ae) {
+ expression ().operator += (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
+ expression ().plus_assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator -= (const matrix_expression<AE> &ae) {
+ expression ().operator -= (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
+ expression ().minus_assign (ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator *= (const AT &at) {
+ expression ().operator *= (at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_reference &operator /= (const AT &at) {
+ expression ().operator /= (at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_reference &m) {
+ expression ().swap (m.expression ());
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_reference &mr) const {
+ return &(*this).e_ == &mr.e_;
+ }
+
+ // Iterator types
+ typedef typename E::const_iterator1 const_iterator1;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_iterator1,
+ typename E::iterator1>::type iterator1;
+ typedef typename E::const_iterator2 const_iterator2;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_iterator2,
+ typename E::iterator2>::type iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ return expression ().find1 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ return expression ().find1 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ return expression ().find2 (rank, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ return expression ().find2 (rank, i, j);
+ }
+
+ // Iterators are the iterators of the referenced expression.
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return expression ().begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return expression ().end1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return expression ().begin1 ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return expression ().end1 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return expression ().begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return expression ().end2 ();
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return expression ().begin2 ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return expression ().end2 ();
+ }
+
+ // Reverse iterators
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ referred_type &e_;
+ };
+
+
+ template<class E1, class E2, class F>
+ class vector_matrix_binary:
+ public matrix_expression<vector_matrix_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef vector_matrix_binary<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef F functor_type;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i), e2_ (j));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_matrix_binary &vmb) const {
+ return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
+ (*this).expression2 ().same_closure (vmb.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator const_subiterator1_type;
+ typedef typename E2::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
+ typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e1_.find (i));
+ const_subiterator1_type it1_end (e1_.find (size1 ()));
+ const_subiterator2_type it2 (e2_.find (j));
+ const_subiterator2_type it2_end (e2_.find (size2 ()));
+ if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type/*zero*/()))) {
+ it1 = it1_end;
+ it2 = it2_end;
+ }
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it1.index (), it2.index ());
+#else
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type/*zero*/());
+#else
+ return const_iterator1 (*this, it1, it2);
+#endif
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e2_.find (j));
+ const_subiterator2_type it2_end (e2_.find (size2 ()));
+ const_subiterator1_type it1 (e1_.find (i));
+ const_subiterator1_type it1_end (e1_.find (size1 ()));
+ if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type/*zero*/()))) {
+ it2 = it2_end;
+ it1 = it1_end;
+ }
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it1.index (), it2.index ());
+#else
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type/*zero*/());
+#else
+ return const_iterator2 (*this, it1, it2);
+#endif
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expressions
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<vector_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename vector_matrix_binary::difference_type difference_type;
+ typedef typename vector_matrix_binary::value_type value_type;
+ typedef typename vector_matrix_binary::const_reference reference;
+ typedef typename vector_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (*it1_, t2_);
+#else
+ return functor_type::apply (*it1_, *it2_);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ t2_ = it.t2_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ const_subiterator1_type it1_;
+ // Mutable due to assignment
+ /* const */ const_subiterator2_type it2_;
+ value_type t2_;
+#else
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<vector_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename vector_matrix_binary::difference_type difference_type;
+ typedef typename vector_matrix_binary::value_type value_type;
+ typedef typename vector_matrix_binary::const_reference reference;
+ typedef typename vector_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (t1_, *it2_);
+#else
+ return functor_type::apply (*it1_, *it2_);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ t1_ = it.t1_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ // Mutable due to assignment
+ /* const */ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ value_type t1_;
+#else
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct vector_matrix_binary_traits {
+ typedef vector_matrix_binary<E1, E2, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ // ISSUE matrix is arbitary temporary type
+ typedef matrix<typename F::value_type> result_type;
+#endif
+ };
+
+ // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
+ outer_prod (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ template<class E, class F>
+ class matrix_unary1:
+ public matrix_expression<matrix_unary1<E, F> > {
+
+ typedef E expression_type;
+ typedef F functor_type;
+ public:
+ typedef typename E::const_closure_type expression_closure_type;
+ private:
+ typedef matrix_unary1<E, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_unary1 (const expression_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size2 ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e_ (i, j));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_unary1 &mu1) const {
+ return (*this).expression ().same_closure (mu1.expression ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E::const_iterator1 const_subiterator1_type;
+ typedef typename E::const_iterator2 const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e_.find1 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it1.index1 (), it1.index2 ());
+#else
+ return const_iterator1 (*this, it1);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e_.find2 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it2.index1 (), it2.index2 ());
+#else
+ return const_iterator2 (*this, it2);
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expression
+ // with the unary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_unary1>,
+ public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_unary1::difference_type difference_type;
+ typedef typename matrix_unary1::value_type value_type;
+ typedef typename matrix_unary1::const_reference reference;
+ typedef typename matrix_unary1::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator1_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_unary1>,
+ public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_unary1::difference_type difference_type;
+ typedef typename matrix_unary1::value_type value_type;
+ typedef typename matrix_unary1::const_reference reference;
+ typedef typename matrix_unary1::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator2_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression_closure_type e_;
+ };
+
+ template<class E, class F>
+ struct matrix_unary1_traits {
+ typedef matrix_unary1<E, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E::matrix_temporary_type result_type;
+#endif
+ };
+
+ // (- m) [i] [j] = - m [i] [j]
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
+ operator - (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (conj m) [i] [j] = conj (m [i] [j])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
+ conj (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (real m) [i] [j] = real (m [i] [j])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
+ real (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (imag m) [i] [j] = imag (m [i] [j])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
+ imag (const matrix_expression<E> &e) {
+ typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E, class F>
+ class matrix_unary2:
+ public matrix_expression<matrix_unary2<E, F> > {
+
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
+ E,
+ const E>::type expression_type;
+ typedef F functor_type;
+ public:
+ typedef typename boost::mpl::if_<boost::is_const<expression_type>,
+ typename E::const_closure_type,
+ typename E::closure_type>::type expression_closure_type;
+ private:
+ typedef matrix_unary2<E, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
+ typename E::reference,
+ value_type>::type reference;
+
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
+ row_major_tag>,
+ column_major_tag,
+ typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
+ column_major_tag>,
+ row_major_tag,
+ typename E::orientation_category>::type>::type orientation_category;
+ typedef typename E::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ // matrix_unary2 may be used as mutable expression -
+ // this is the only non const expression constructor
+ explicit matrix_unary2 (expression_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e_.size2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e_.size1 ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e_ (j, i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
+ return e_ (j, i);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_unary2 &mu2) const {
+ return (*this).expression ().same_closure (mu2.expression ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E::const_iterator1 const_subiterator2_type;
+ typedef typename E::const_iterator2 const_subiterator1_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (e_.find2 (rank, j, i));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it1.index2 (), it1.index1 ());
+#else
+ return const_iterator1 (*this, it1);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (e_.find1 (rank, j, i));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it2.index2 (), it2.index1 ());
+#else
+ return const_iterator2 (*this, it2);
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expression
+ // with the unary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_unary2>,
+ public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_unary2::difference_type difference_type;
+ typedef typename matrix_unary2::value_type value_type;
+ typedef typename matrix_unary2::const_reference reference;
+ typedef typename matrix_unary2::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator1_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_unary2>,
+ public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_unary2::difference_type difference_type;
+ typedef typename matrix_unary2::value_type value_type;
+ typedef typename matrix_unary2::const_reference reference;
+ typedef typename matrix_unary2::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
+ container_const_reference<self_type> (mu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator2_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression_closure_type e_;
+ };
+
+ template<class E, class F>
+ struct matrix_unary2_traits {
+ typedef matrix_unary2<E, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E::matrix_temporary_type result_type;
+#endif
+ };
+
+ // (trans m) [i] [j] = m [j] [i]
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
+ trans (const matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
+ trans (matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (herm m) [i] [j] = conj (m [j] [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
+ herm (const matrix_expression<E> &e) {
+ typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E1, class E2, class F>
+ class matrix_binary:
+ public matrix_expression<matrix_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef matrix_binary<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary (const E1 &e1, const E2 &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i, j), e2_ (i, j));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary &mb) const {
+ return (*this).expression1 ().same_closure (mb.expression1 ()) &&
+ (*this).expression2 ().same_closure (mb.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
+ typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
+ typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator11_type it11 (e1_.find1 (rank, i, j));
+ const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
+ const_iterator21_type it21 (e2_.find1 (rank, i, j));
+ const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
+ BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
+ BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
+ i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
+ it21 != it21_end ? it21.index1 () : size1 ());
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator12_type it12 (e1_.find2 (rank, i, j));
+ const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
+ const_iterator22_type it22 (e2_.find2 (rank, i, j));
+ const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
+ BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
+ BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
+ j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
+ it22 != it22_end ? it22.index2 () : size2 ());
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator1::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_binary::difference_type difference_type;
+ typedef typename matrix_binary::value_type value_type;
+ typedef typename matrix_binary::const_reference reference;
+ typedef typename matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mb, size_type i, size_type j,
+ const const_iterator11_type &it1, const const_iterator11_type &it1_end,
+ const const_iterator21_type &it2, const const_iterator21_type &it2_end):
+ container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
+
+ private:
+ // Dense specializations
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag) {
+ ++ i_; ++ it1_; ++ it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag) {
+ -- i_; -- it1_; -- it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag, difference_type n) {
+ i_ += n; it1_ += n; it2_ += n;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag, difference_type n) {
+ i_ -= n; it1_ -= n; it2_ -= n;
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ return functor_type::apply (*it1_, *it2_);
+ }
+
+ // Packed specializations
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (it1_.index1 () <= i_)
+ ++ it1_;
+ if (it2_ != it2_end_)
+ if (it2_.index1 () <= i_)
+ ++ it2_;
+ ++ i_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (i_ <= it1_.index1 ())
+ -- it1_;
+ if (it2_ != it2_end_)
+ if (i_ <= it2_.index1 ())
+ -- it2_;
+ -- i_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
+ if (it1_.index1 () == i_)
+ t1 = *it1_;
+ }
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
+ if (it2_.index1 () == i_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ // Sparse specializations
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size1 ();
+ if (it1_ != it1_end_) {
+ if (it1_.index1 () <= i_)
+ ++ it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index1 ();
+ }
+ size_type index2 = (*this) ().size1 ();
+ if (it2_ != it2_end_)
+ if (it2_.index1 () <= i_)
+ ++ it2_;
+ if (it2_ != it2_end_) {
+ index2 = it2_.index1 ();
+ }
+ i_ = (std::min) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size1 ();
+ if (it1_ != it1_end_) {
+ if (i_ <= it1_.index1 ())
+ -- it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index1 ();
+ }
+ size_type index2 = (*this) ().size1 ();
+ if (it2_ != it2_end_) {
+ if (i_ <= it2_.index1 ())
+ -- it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index1 ();
+ }
+ i_ = (std::max) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
+ if (it1_.index1 () == i_)
+ t1 = *it1_;
+ }
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
+ if (it2_.index1 () == i_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ increment (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ decrement (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ increment (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ decrement (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () - it.index1 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ // if (it1_ != it1_end_ && it2_ != it2_end_)
+ // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
+ // else
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ i_ = it.i_;
+ j_ = it.j_;
+ it1_ = it.it1_;
+ it1_end_ = it.it1_end_;
+ it2_ = it.it2_;
+ it2_end_ = it.it2_end_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () == it.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
+ return index1 () < it.index1 ();
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_iterator11_type it1_;
+ const_iterator11_type it1_end_;
+ const_iterator21_type it2_;
+ const_iterator21_type it2_end_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_binary::difference_type difference_type;
+ typedef typename matrix_binary::value_type value_type;
+ typedef typename matrix_binary::const_reference reference;
+ typedef typename matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mb, size_type i, size_type j,
+ const const_iterator12_type &it1, const const_iterator12_type &it1_end,
+ const const_iterator22_type &it2, const const_iterator22_type &it2_end):
+ container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
+
+ private:
+ // Dense access specializations
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag) {
+ ++ j_; ++ it1_; ++ it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag) {
+ -- j_; -- it1_; -- it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag, difference_type n) {
+ j_ += n; it1_ += n; it2_ += n;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag, difference_type n) {
+ j_ -= n; it1_ -= n; it2_ -= n;
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ return functor_type::apply (*it1_, *it2_);
+ }
+
+ // Packed specializations
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (it1_.index2 () <= j_)
+ ++ it1_;
+ if (it2_ != it2_end_)
+ if (it2_.index2 () <= j_)
+ ++ it2_;
+ ++ j_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (j_ <= it1_.index2 ())
+ -- it1_;
+ if (it2_ != it2_end_)
+ if (j_ <= it2_.index2 ())
+ -- it2_;
+ -- j_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
+ if (it1_.index2 () == j_)
+ t1 = *it1_;
+ }
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
+ if (it2_.index2 () == j_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ // Sparse specializations
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size2 ();
+ if (it1_ != it1_end_) {
+ if (it1_.index2 () <= j_)
+ ++ it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index2 ();
+ }
+ size_type index2 = (*this) ().size2 ();
+ if (it2_ != it2_end_) {
+ if (it2_.index2 () <= j_)
+ ++ it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index2 ();
+ }
+ j_ = (std::min) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size2 ();
+ if (it1_ != it1_end_) {
+ if (j_ <= it1_.index2 ())
+ -- it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index2 ();
+ }
+ size_type index2 = (*this) ().size2 ();
+ if (it2_ != it2_end_) {
+ if (j_ <= it2_.index2 ())
+ -- it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index2 ();
+ }
+ j_ = (std::max) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_) {
+ BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
+ if (it1_.index2 () == j_)
+ t1 = *it1_;
+ }
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_) {
+ BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
+ if (it2_.index2 () == j_)
+ t2 = *it2_;
+ }
+ return functor_type::apply (t1, t2);
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ increment (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ decrement (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ increment (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ decrement (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () - it.index2 ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ // if (it1_ != it1_end_ && it2_ != it2_end_)
+ // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
+ // else
+ return i_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return j_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ i_ = it.i_;
+ j_ = it.j_;
+ it1_ = it.it1_;
+ it1_end_ = it.it1_end_;
+ it2_ = it.it2_;
+ it2_end_ = it.it2_end_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () == it.index2 ();
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
+ return index2 () < it.index2 ();
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ const_iterator12_type it1_;
+ const_iterator12_type it1_end_;
+ const_iterator22_type it2_;
+ const_iterator22_type it2_end_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct matrix_binary_traits {
+ typedef matrix_binary<E1, E2, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+ };
+
+ // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ operator + (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ operator - (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ element_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ element_div (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ template<class E1, class E2, class F>
+ class matrix_binary_scalar1:
+ public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ typedef const E1& expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ typedef matrix_binary_scalar1<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E2::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e2_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size2 ();
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (expression1_type (e1_), e2_ (i, j));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary_scalar1 &mbs1) const {
+ return &e1_ == &(mbs1.e1_) &&
+ (*this).e2_.same_closure (mbs1.e2_);
+ }
+
+ // Iterator types
+ private:
+ typedef expression1_type const_subiterator1_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator21_type it21 (e2_.find1 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it21.index1 (), it21.index2 ());
+#else
+ return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator22_type it22 (e2_.find2 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it22.index1 (), it22.index2 ());
+#else
+ return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_binary_scalar1>,
+ public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E2::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar1::difference_type difference_type;
+ typedef typename matrix_binary_scalar1::value_type value_type;
+ typedef typename matrix_binary_scalar1::const_reference reference;
+ typedef typename matrix_binary_scalar1::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it2_ ;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_iterator21_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_binary_scalar1>,
+ public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E2::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar1::difference_type difference_type;
+ typedef typename matrix_binary_scalar1::value_type value_type;
+ typedef typename matrix_binary_scalar1::const_reference reference;
+ typedef typename matrix_binary_scalar1::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_iterator22_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct matrix_binary_scalar1_traits {
+ typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E2::matrix_temporary_type result_type;
+#endif
+ };
+
+ // (t * m) [i] [j] = t * m [i] [j]
+ template<class T1, class E2>
+ BOOST_UBLAS_INLINE
+ typename enable_if< is_convertible<T1, typename E2::value_type >,
+ typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
+ >::type
+ operator * (const T1 &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1, e2 ());
+ }
+
+
+ template<class E1, class E2, class F>
+ class matrix_binary_scalar2:
+ public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef const E2& expression2_closure_type;
+ private:
+ typedef matrix_binary_scalar2<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef typename E1::orientation_category orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e1_.size2 ();
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_ (i, j), expression2_type (e2_));
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_binary_scalar2 &mbs2) const {
+ return (*this).e1_.same_closure (mbs2.e1_) &&
+ &e2_ == &(mbs2.e2_);
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef expression2_type const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_iterator11_type it11 (e1_.find1 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it11.index1 (), it11.index2 ());
+#else
+ return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_iterator12_type it12 (e1_.find2 (rank, i, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it12.index1 (), it12.index2 ());
+#else
+ return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
+#endif
+ }
+
+ // Iterators enhance the iterators of the referenced expression
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_binary_scalar2>,
+ public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename E1::const_iterator1::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar2::difference_type difference_type;
+ typedef typename matrix_binary_scalar2::value_type value_type;
+ typedef typename matrix_binary_scalar2::const_reference reference;
+ typedef typename matrix_binary_scalar2::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_ ;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator11_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_binary_scalar2>,
+ public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename E1::const_iterator2::iterator_category iterator_category;
+ typedef typename matrix_binary_scalar2::difference_type difference_type;
+ typedef typename matrix_binary_scalar2::value_type value_type;
+ typedef typename matrix_binary_scalar2::const_reference reference;
+ typedef typename matrix_binary_scalar2::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator12_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct matrix_binary_scalar2_traits {
+ typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+ };
+
+ // (m * t) [i] [j] = m [i] [j] * t
+ template<class E1, class T2>
+ BOOST_UBLAS_INLINE
+ typename enable_if< is_convertible<T2, typename E1::value_type>,
+ typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
+ >::type
+ operator * (const matrix_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+ }
+
+ // (m / t) [i] [j] = m [i] [j] / t
+ template<class E1, class T2>
+ BOOST_UBLAS_INLINE
+ typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
+ operator / (const matrix_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+ }
+
+
+ template<class E1, class E2, class F>
+ class matrix_vector_binary1:
+ public vector_expression<matrix_vector_binary1<E1, E2, F> > {
+
+ public:
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ private:
+ typedef F functor_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef matrix_vector_binary1<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e1_.size1 ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_, e2_, i);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_binary1 &mvb1) const {
+ return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
+ (*this).expression2 ().same_closure (mvb1.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator1 const_subiterator1_type;
+ typedef typename E2::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ const_subiterator1_type it1 (e1_.find1 (0, i, 0));
+ return const_iterator (*this, it1.index1 ());
+#else
+ return const_iterator (*this, e1_.find1 (0, i, 0));
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<matrix_vector_binary1>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_vector_binary1::difference_type difference_type;
+ typedef typename matrix_vector_binary1::value_type value_type;
+ typedef typename matrix_vector_binary1::const_reference reference;
+ typedef typename matrix_vector_binary1::const_pointer pointer;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (mvb), it1_ (it1) {}
+#endif
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mvb = (*this) ();
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return mvb (index ());
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_.begin (), e2_begin_);
+#else
+ return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
+#endif
+#else
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_.begin (), e2_begin_);
+#else
+ return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
+#endif
+ else
+ return mvb (index ());
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
+#else
+ const self_type &mvb = (*this) ();
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ mvb.expression2 ().begin (), mvb.expression2 ().end ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ mvb.expression2 ().begin (), mvb.expression2 ().end ());
+#endif
+#endif
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
+#else
+ const self_type &mvb = (*this) ();
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it1_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ e2_begin_ = it.e2_begin_;
+ e2_end_ = it.e2_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ // Mutable due to assignment
+ /* const */ const_subiterator2_type e2_begin_;
+ /* const */ const_subiterator2_type e2_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class T1, class E1, class T2, class E2>
+ struct matrix_vector_binary1_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef row_major_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::vector_temporary_type result_type;
+#endif
+ };
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ unknown_storage_tag,
+ row_major_tag) {
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E2::complexity == 0);
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ unknown_storage_tag,
+ row_major_tag) {
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E2::complexity == 0);
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v) {
+ return v.assign (prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v) {
+ return v.assign (prec_prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ return V (prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ prec_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ return V (prec_prod (e1, e2));
+ }
+
+ template<class E1, class E2, class F>
+ class matrix_vector_binary2:
+ public vector_expression<matrix_vector_binary2<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef matrix_vector_binary2<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e2_.size2 ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+ public:
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type j) const {
+ return functor_type::apply (e1_, e2_, j);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_binary2 &mvb2) const {
+ return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
+ (*this).expression2 ().same_closure (mvb2.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator const_subiterator1_type;
+ typedef typename E2::const_iterator2 const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ const_subiterator2_type it2 (e2_.find2 (0, 0, j));
+ return const_iterator (*this, it2.index2 ());
+#else
+ return const_iterator (*this, e2_.find2 (0, 0, j));
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<matrix_vector_binary2>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_vector_binary2::difference_type difference_type;
+ typedef typename matrix_vector_binary2::value_type value_type;
+ typedef typename matrix_vector_binary2::const_reference reference;
+ typedef typename matrix_vector_binary2::const_pointer pointer;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvb), it2_ (it2) {}
+#endif
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mvb = (*this) ();
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return mvb (index ());
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, e1_begin_, it2_.begin ());
+#else
+ return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
+#endif
+#else
+ difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, e1_begin_, it2_.begin ());
+#else
+ return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
+#endif
+ else
+ return mvb (index ());
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
+#else
+ const self_type &mvb = (*this) ();
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ it2_.begin (), it2_.end ());
+#else
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()));
+#endif
+#endif
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+#else
+ const self_type &mvb = (*this) ();
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+#else
+ return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ e1_begin_ = it.e1_begin_;
+ e1_end_ = it.e1_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator2_type it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ // Mutable due to assignment
+ /* const */ const_subiterator1_type e1_begin_;
+ /* const */ const_subiterator1_type e1_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class T1, class E1, class T2, class E2>
+ struct matrix_vector_binary2_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef column_major_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E2::vector_temporary_type result_type;
+#endif
+ };
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ column_major_tag) {
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0);
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ column_major_tag) {
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0);
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v) {
+ return v.assign (prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v) {
+ return v.assign (prec_prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return V (prod (e1, e2));
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ prec_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return V (prec_prod (e1, e2));
+ }
+
+ template<class E1, class E2, class F>
+ class matrix_matrix_binary:
+ public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
+
+ public:
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ private:
+ typedef F functor_type;
+ public:
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef matrix_matrix_binary<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ static const unsigned complexity = 1;
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_orientation_tag orientation_category;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return e1_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return e2_.size2 ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return functor_type::apply (e1_, e2_, i, j);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_matrix_binary &mmb) const {
+ return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
+ (*this).expression2 ().same_closure (mmb.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator1 const_iterator11_type;
+ typedef typename E1::const_iterator2 const_iterator12_type;
+ typedef typename E2::const_iterator1 const_iterator21_type;
+ typedef typename E2::const_iterator2 const_iterator22_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
+ typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
+ typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
+ typedef const_iterator1 iterator1;
+ typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
+ typedef const_iterator2 iterator2;
+#else
+ class const_iterator1;
+ typedef const_iterator1 iterator1;
+ class const_iterator2;
+ typedef const_iterator2 iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+ // FIXME sparse matrix tests fail!
+ // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
+ const_iterator11_type it11 (e1_.find1 (0, i, 0));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it11.index1 (), j);
+#else
+ // FIXME sparse matrix tests fail!
+ // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
+ const_iterator22_type it22 (e2_.find2 (0, 0, j));
+ return const_iterator1 (*this, it11, it22);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+ // FIXME sparse matrix tests fail!
+ // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
+ const_iterator22_type it22 (e2_.find2 (0, 0, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, it22.index2 ());
+#else
+ // FIXME sparse matrix tests fail!
+ // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
+ const_iterator11_type it11 (e1_.find1 (0, i, 0));
+ return const_iterator2 (*this, it11, it22);
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_matrix_binary::difference_type difference_type;
+ typedef typename matrix_matrix_binary::value_type value_type;
+ typedef typename matrix_matrix_binary::const_reference reference;
+ typedef typename matrix_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ private:
+ // Random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mmb = (*this) ();
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return mmb (index1 (), index2 ());
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_.begin (), it2_begin_);
+#else
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
+#endif
+#else
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_.begin (), it2_begin_);
+#else
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
+#endif
+ else
+ return mmb (index1 (), index2 ());
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_begin_, it2_end_, packed_random_access_iterator_tag ());
+#else
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
+#endif
+#endif
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
+#else
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_iterator11_type it1_;
+ // Mutable due to assignment
+ /* const */ const_iterator22_type it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ /* const */ const_iterator21_type it2_begin_;
+ /* const */ const_iterator21_type it2_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_matrix_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
+ typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
+ typedef typename matrix_matrix_binary::difference_type difference_type;
+ typedef typename matrix_matrix_binary::value_type value_type;
+ typedef typename matrix_matrix_binary::const_reference reference;
+ typedef typename matrix_matrix_binary::const_pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
+#else
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
+ container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
+#endif
+
+ private:
+ // Random access specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ const self_type &mmb = (*this) ();
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return mmb (index1 (), index2 ());
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_begin_, it2_.begin ());
+#else
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
+#endif
+#else
+ difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (size, it1_begin_, it2_.begin ());
+#else
+ return functor_type::apply (size, it1_.begin (), it2_.begin ());
+#endif
+ else
+ return mmb (index1 (), index2 ());
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_begin_, it1_end_,
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+#else
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
+#endif
+#endif
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ return functor_type::apply (it1_begin_, it1_end_,
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+#else
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ return functor_type::apply (it1_.begin (), it1_.end (),
+ it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
+#else
+ return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
+ boost::numeric::ublas::end (it1_, iterator1_tag ()),
+ boost::numeric::ublas::begin (it2_, iterator2_tag ()),
+ boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
+#endif
+#endif
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+#endif
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ // Mutable due to assignment
+ /* const */ const_iterator11_type it1_;
+ const_iterator22_type it2_;
+#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
+ /* const */ const_iterator12_type it1_begin_;
+ /* const */ const_iterator12_type it1_end_;
+#endif
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class T1, class E1, class T2, class E2>
+ struct matrix_matrix_binary_traits {
+ typedef unknown_storage_tag storage_category;
+ typedef unknown_orientation_tag orientation_category;
+ typedef typename promote_traits<T1, T2>::promote_type promote_type;
+ typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::matrix_temporary_type result_type;
+#endif
+ };
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ unknown_orientation_tag) {
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::result_type
+ prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::storage_category storage_category;
+ typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
+ typename E2::value_type, E2>::orientation_category orientation_category;
+ return prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ unknown_storage_tag,
+ unknown_orientation_tag) {
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
+ prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
+ typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
+ typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
+ return prec_prod (e1, e2, storage_category (), orientation_category ());
+ }
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m) {
+ return m.assign (prod (e1, e2));
+ }
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m) {
+ return m.assign (prec_prod (e1, e2));
+ }
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return M (prod (e1, e2));
+ }
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ prec_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ return M (prec_prod (e1, e2));
+ }
+
+ template<class E, class F>
+ class matrix_scalar_unary:
+ public scalar_expression<matrix_scalar_unary<E, F> > {
+ public:
+ typedef E expression_type;
+ typedef F functor_type;
+ typedef typename F::result_type value_type;
+ typedef typename E::const_closure_type expression_closure_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit matrix_scalar_unary (const expression_type &e):
+ e_ (e) {}
+
+ private:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+ public:
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return functor_type::apply (e_);
+ }
+
+ private:
+ expression_closure_type e_;
+ };
+
+ template<class E, class F>
+ struct matrix_scalar_unary_traits {
+ typedef matrix_scalar_unary<E, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename F::result_type result_type;
+#endif
+ };
+
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
+ norm_1 (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
+ norm_frobenius (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
+ norm_inf (const matrix_expression<E> &e) {
+ typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_MATRIX_PROXY_
+#define _BOOST_UBLAS_MATRIX_PROXY_
+
+#include <boost/numeric/ublas/matrix_expression.hpp>
+#include <boost/numeric/ublas/detail/vector_assign.hpp>
+#include <boost/numeric/ublas/detail/matrix_assign.hpp>
+#include <boost/numeric/ublas/detail/temporary.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief
+ */
+ template<class M>
+ class matrix_row:
+ public vector_expression<matrix_row<M> > {
+
+ typedef matrix_row<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_row (matrix_type &data, size_type i):
+ data_ (data), i_ (i) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return data_.size2 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return i_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type j) const {
+ return data_ (i_, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type j) {
+ return data_ (i_, j);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type j) const {
+ return (*this) (j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type j) {
+ return (*this) (j);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type j) const {
+ return data_ (i_, j);
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type j) const {
+ return (*this) (j);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_row &operator = (const matrix_row &mr) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mr));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_row &assign_temporary (matrix_row &mr) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, mr);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_row &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_row &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_row &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_row &mr) const {
+ return (*this).data_.same_closure (mr.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_row &mr) const {
+ return (*this).data_ == mr.data_ && index () == mr.index ();
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_row mr) {
+ if (this != &mr) {
+ BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), mr.begin ());
+ vector_swap<scalar_swap> (*this, mr);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_row mr1, matrix_row mr2) {
+ mr1.swap (mr2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename M::const_iterator2 const_subiterator_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator<matrix_row<matrix_type>,
+ typename subiterator_type::iterator_category> iterator;
+ typedef indexed_const_iterator<matrix_row<matrix_type>,
+ typename const_subiterator_type::iterator_category> const_iterator;
+#else
+ class const_iterator;
+ class iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type j) const {
+ const_subiterator_type it2 (data_.find2 (1, i_, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, it2.index2 ());
+#else
+ return const_iterator (*this, it2);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type j) {
+ subiterator_type it2 (data_.find2 (1, i_, j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, it2.index2 ());
+#else
+ return iterator (*this, it2);
+#endif
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<matrix_row>,
+ public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename const_subiterator_type::value_type value_type;
+ typedef typename const_subiterator_type::difference_type difference_type;
+ typedef typename const_subiterator_type::reference reference;
+ typedef typename const_subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mr, const const_subiterator_type &it):
+ container_const_reference<self_type> (mr), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<matrix_row>,
+ public iterator_base_traits<typename subiterator_type::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ typedef typename subiterator_type::value_type value_type;
+ typedef typename subiterator_type::difference_type difference_type;
+ typedef typename subiterator_type::reference reference;
+ typedef typename subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &mr, const subiterator_type &it):
+ container_reference<self_type> (mr), 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) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index2 ();
+ }
+
+ // 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) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ size_type i_;
+ };
+
+ // Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_row<M> row (M &data, typename M::size_type i) {
+ return matrix_row<M> (data, i);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_row<const M> row (const M &data, typename M::size_type i) {
+ return matrix_row<const M> (data, i);
+ }
+
+ // Specialize temporary
+ template <class M>
+ struct vector_temporary_traits< matrix_row<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const matrix_row<M> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based column vector class
+ template<class M>
+ class matrix_column:
+ public vector_expression<matrix_column<M> > {
+
+ typedef matrix_column<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_column (matrix_type &data, size_type j):
+ data_ (data), j_ (j) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return data_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return j_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (i, j_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (i, j_);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (i, j_);
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_column &operator = (const matrix_column &mc) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mc));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_column &assign_temporary (matrix_column &mc) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, mc);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_column &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_column &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_column &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_column &mc) const {
+ return (*this).data_.same_closure (mc.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_column &mc) const {
+ return (*this).data_ == mc.data_ && index () == mc.index ();
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_column mc) {
+ if (this != &mc) {
+ BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), mc.begin ());
+ vector_swap<scalar_swap> (*this, mc);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_column mc1, matrix_column mc2) {
+ mc1.swap (mc2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename M::const_iterator1 const_subiterator_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator<matrix_column<matrix_type>,
+ typename subiterator_type::iterator_category> iterator;
+ typedef indexed_const_iterator<matrix_column<matrix_type>,
+ typename const_subiterator_type::iterator_category> const_iterator;
+#else
+ class const_iterator;
+ class iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ const_subiterator_type it1 (data_.find1 (1, i, j_));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, it1.index1 ());
+#else
+ return const_iterator (*this, it1);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ subiterator_type it1 (data_.find1 (1, i, j_));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, it1.index1 ());
+#else
+ return iterator (*this, it1);
+#endif
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<matrix_column>,
+ public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename const_subiterator_type::value_type value_type;
+ typedef typename const_subiterator_type::difference_type difference_type;
+ typedef typename const_subiterator_type::reference reference;
+ typedef typename const_subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mc, const const_subiterator_type &it):
+ container_const_reference<self_type> (mc), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index1 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<matrix_column>,
+ public iterator_base_traits<typename subiterator_type::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ typedef typename subiterator_type::value_type value_type;
+ typedef typename subiterator_type::difference_type difference_type;
+ typedef typename subiterator_type::reference reference;
+ typedef typename subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &mc, const subiterator_type &it):
+ container_reference<self_type> (mc), 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) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index1 ();
+ }
+
+ // 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) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ size_type j_;
+ };
+
+ // Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_column<M> column (M &data, typename M::size_type j) {
+ return matrix_column<M> (data, j);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_column<const M> column (const M &data, typename M::size_type j) {
+ return matrix_column<const M> (data, j);
+ }
+
+ // Specialize temporary
+ template <class M>
+ struct vector_temporary_traits< matrix_column<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const matrix_column<M> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based vector range class
+ template<class M>
+ class matrix_vector_range:
+ public vector_expression<matrix_vector_range<M> > {
+
+ typedef matrix_vector_range<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_range (matrix_type &data, const range_type &r1, const range_type &r2):
+ data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
+ // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
+ // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
+ // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start1 () const {
+ return r1_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type start2 () const {
+ return r2_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return BOOST_UBLAS_SAME (r1_.size (), r2_.size ());
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (r1_ (i), r2_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (r1_ (i), r2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (r1_ (i), r2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator = (const matrix_vector_range &mvr) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvr));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &assign_temporary (matrix_vector_range &mvr) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, mvr);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_range &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_range &mvr) const {
+ return (*this).data_.same_closure (mvr.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_vector_range &mvr) const {
+ return (*this).data_ == mvr.data_ && r1_ == mvr.r1_ && r2_ == mvr.r2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_vector_range mvr) {
+ if (this != &mvr) {
+ BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), mvr.begin ());
+ vector_swap<scalar_swap> (*this, mvr);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_vector_range mvr1, matrix_vector_range mvr2) {
+ mvr1.swap (mvr2);
+ }
+
+ // Iterator types
+ private:
+ // Use range as an index - FIXME this fails for packed assignment
+ typedef typename range_type::const_iterator const_subiterator1_type;
+ typedef typename range_type::const_iterator subiterator1_type;
+ typedef typename range_type::const_iterator const_subiterator2_type;
+ typedef typename range_type::const_iterator subiterator2_type;
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, r1_.begin () + i, r2_.begin () + i);
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ return iterator (*this, r1_.begin () + i, r2_.begin () + i);
+ }
+
+ class const_iterator:
+ public container_const_reference<matrix_vector_range>,
+ public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_range::value_type value_type;
+ typedef typename matrix_vector_range::difference_type difference_type;
+ typedef typename matrix_vector_range::const_reference reference;
+ typedef const typename matrix_vector_range::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvr, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ class iterator:
+ public container_reference<matrix_vector_range>,
+ public iterator_base_traits<typename M::iterator1::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_range::value_type value_type;
+ typedef typename matrix_vector_range::difference_type difference_type;
+ typedef typename matrix_vector_range::reference reference;
+ typedef typename matrix_vector_range::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &mvr, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator &operator = (const iterator &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ range_type r1_;
+ range_type r2_;
+ };
+
+ // Specialize temporary
+ template <class M>
+ struct vector_temporary_traits< matrix_vector_range<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const matrix_vector_range<M> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based vector slice class
+ template<class M>
+ class matrix_vector_slice:
+ public vector_expression<matrix_vector_slice<M> > {
+
+ typedef matrix_vector_slice<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef basic_slice<size_type, difference_type> slice_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
+ data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
+ // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
+ // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start1 () const {
+ return s1_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type start2 () const {
+ return s2_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride1 () const {
+ return s1_.stride ();
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride2 () const {
+ return s2_.stride ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return BOOST_UBLAS_SAME (s1_.size (), s2_.size ());
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (s1_ (i), s2_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (s1_ (i), s2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (s1_ (i), s2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator = (const matrix_vector_slice &mvs) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvs));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, mvs);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_slice &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_slice &mvs) const {
+ return (*this).data_.same_closure (mvs.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_vector_slice &mvs) const {
+ return (*this).data_ == mvs.data_ && s1_ == mvs.s1_ && s2_ == mvs.s2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_vector_slice mvs) {
+ if (this != &mvs) {
+ BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), mvs.begin ());
+ vector_swap<scalar_swap> (*this, mvs);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_vector_slice mvs1, matrix_vector_slice mvs2) {
+ mvs1.swap (mvs2);
+ }
+
+ // Iterator types
+ private:
+ // Use slice as an index - FIXME this fails for packed assignment
+ typedef typename slice_type::const_iterator const_subiterator1_type;
+ typedef typename slice_type::const_iterator subiterator1_type;
+ typedef typename slice_type::const_iterator const_subiterator2_type;
+ typedef typename slice_type::const_iterator subiterator2_type;
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, s1_.begin () + i, s2_.begin () + i);
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ return iterator (*this, s1_.begin () + i, s2_.begin () + i);
+ }
+
+ // Iterators simply are indices.
+
+ class const_iterator:
+ public container_const_reference<matrix_vector_slice>,
+ public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_slice::value_type value_type;
+ typedef typename matrix_vector_slice::difference_type difference_type;
+ typedef typename matrix_vector_slice::const_reference reference;
+ typedef const typename matrix_vector_slice::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
+ 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 ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ class iterator:
+ public container_reference<matrix_vector_slice>,
+ public iterator_base_traits<typename M::iterator1::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_slice::value_type value_type;
+ typedef typename matrix_vector_slice::difference_type difference_type;
+ typedef typename matrix_vector_slice::reference reference;
+ typedef typename matrix_vector_slice::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &mvs, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator &operator = (const iterator &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ slice_type s1_;
+ slice_type s2_;
+ };
+
+ // Specialize temporary
+ template <class M>
+ struct vector_temporary_traits< matrix_vector_slice<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const matrix_vector_slice<M> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based vector indirection class
+
+ template<class M, class IA>
+ class matrix_vector_indirect:
+ public vector_expression<matrix_vector_indirect<M, IA> > {
+
+ typedef matrix_vector_indirect<M, IA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef IA indirect_array_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect (matrix_type &data, size_type size):
+ data_ (data), ia1_ (size), ia2_ (size) {}
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
+ data_ (data), ia1_ (ia1), ia2_ (ia2) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return BOOST_UBLAS_SAME (ia1_.size (), ia2_.size ());
+ }
+ BOOST_UBLAS_INLINE
+ const indirect_array_type &indirect1 () const {
+ return ia1_;
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array_type &indirect1 () {
+ return ia1_;
+ }
+ BOOST_UBLAS_INLINE
+ const indirect_array_type &indirect2 () const {
+ return ia2_;
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array_type &indirect2 () {
+ return ia2_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (ia1_ (i), ia2_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (ia1_ (i), ia2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (ia1_ (i), ia2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvi));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, mvi);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_vector_indirect &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_vector_indirect &mvi) const {
+ return (*this).data_.same_closure (mvi.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_vector_indirect &mvi) const {
+ return (*this).data_ == mvi.data_ && ia1_ == mvi.ia1_ && ia2_ == mvi.ia2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_vector_indirect mvi) {
+ if (this != &mvi) {
+ BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), mvi.begin ());
+ vector_swap<scalar_swap> (*this, mvi);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_vector_indirect mvi1, matrix_vector_indirect mvi2) {
+ mvi1.swap (mvi2);
+ }
+
+ // Iterator types
+ private:
+ // Use indirect array as an index - FIXME this fails for packed assignment
+ typedef typename IA::const_iterator const_subiterator1_type;
+ typedef typename IA::const_iterator subiterator1_type;
+ typedef typename IA::const_iterator const_subiterator2_type;
+ typedef typename IA::const_iterator subiterator2_type;
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ return iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
+ }
+
+ // Iterators simply are indices.
+
+ class const_iterator:
+ public container_const_reference<matrix_vector_indirect>,
+ public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_indirect::value_type value_type;
+ typedef typename matrix_vector_indirect::difference_type difference_type;
+ typedef typename matrix_vector_indirect::const_reference reference;
+ typedef const typename matrix_vector_indirect::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &mvi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ class iterator:
+ public container_reference<matrix_vector_indirect>,
+ public iterator_base_traits<typename M::iterator1::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ // FIXME Iterator can never be different code was:
+ // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
+ BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
+
+ typedef typename matrix_vector_indirect::value_type value_type;
+ typedef typename matrix_vector_indirect::difference_type difference_type;
+ typedef typename matrix_vector_indirect::reference reference;
+ typedef typename matrix_vector_indirect::value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &mvi, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator &operator ++ () {
+ ++ it1_;
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -- () {
+ -- it1_;
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator += (difference_type n) {
+ it1_ += n;
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator &operator = (const iterator &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ == it.it1_ && it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it1_ < it.it1_ && it2_ < it.it2_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ indirect_array_type ia1_;
+ indirect_array_type ia2_;
+ };
+
+ // Specialize temporary
+ template <class M, class IA>
+ struct vector_temporary_traits< matrix_vector_indirect<M,IA> >
+ : vector_temporary_traits< M > {} ;
+ template <class M, class IA>
+ struct vector_temporary_traits< const matrix_vector_indirect<M,IA> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based range class
+ template<class M>
+ class matrix_range:
+ public matrix_expression<matrix_range<M> > {
+
+ typedef matrix_range<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_range (matrix_type &data, const range_type &r1, const range_type &r2):
+ data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
+ // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
+ // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
+ }
+ BOOST_UBLAS_INLINE
+ matrix_range (const matrix_closure_type &data, const range_type &r1, const range_type &r2, int):
+ data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
+ // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
+ // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start1 () const {
+ return r1_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return r1_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type start2() const {
+ return r2_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return r2_.size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return data_ (r1_ (i), r2_ (j));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return data_ (r1_ (i), r2_ (j));
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ return data_ (r1_ (i), r2_ (j));
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that matrix_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ matrix_range<matrix_type> project (const range_type &r1, const range_type &r2) const {
+ return matrix_range<matrix_type> (data_, r1_.compose (r1.preprocess (data_.size1 ())), r2_.compose (r2.preprocess (data_.size2 ())), 0);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_range &operator = (const matrix_range &mr) {
+ matrix_assign<scalar_assign> (*this, mr);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_range &assign_temporary (matrix_range &mr) {
+ return *this = mr;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_range &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_range& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_range& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_range &mr) const {
+ return (*this).data_.same_closure (mr.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_range &mr) const {
+ return (*this).data_ == (mr.data_) && r1_ == mr.r1_ && r2_ == mr.r2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_range mr) {
+ if (this != &mr) {
+ BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ());
+ matrix_swap<scalar_swap> (*this, mr);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_range mr1, matrix_range mr2) {
+ mr1.swap (mr2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename M::const_iterator1 const_subiterator1_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator1_type;
+ typedef typename M::const_iterator2 const_subiterator2_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<matrix_range<matrix_type>,
+ typename subiterator1_type::iterator_category> iterator1;
+ typedef indexed_iterator2<matrix_range<matrix_type>,
+ typename subiterator2_type::iterator_category> iterator2;
+ typedef indexed_const_iterator1<matrix_range<matrix_type>,
+ typename const_subiterator1_type::iterator_category> const_iterator1;
+ typedef indexed_const_iterator2<matrix_range<matrix_type>,
+ typename const_subiterator2_type::iterator_category> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ const_subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, it1.index1 (), it1.index2 ());
+#else
+ return const_iterator1 (*this, it1);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, it1.index1 (), it1.index2 ());
+#else
+ return iterator1 (*this, it1);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ const_subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, it2.index1 (), it2.index2 ());
+#else
+ return const_iterator2 (*this, it2);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, it2.index1 (), it2.index2 ());
+#else
+ return iterator2 (*this, it2);
+#endif
+ }
+
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_range>,
+ public iterator_base_traits<typename const_subiterator1_type::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename const_subiterator1_type::value_type value_type;
+ typedef typename const_subiterator1_type::difference_type difference_type;
+ typedef typename const_subiterator1_type::reference reference;
+ typedef typename const_subiterator1_type::pointer pointer;
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mr, const const_subiterator1_type &it):
+ container_const_reference<self_type> (mr), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &mr = (*this) ();
+ return mr.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &mr = (*this) ();
+ return mr.find2 (1, index1 (), mr.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 () - (*this) ().start1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 () - (*this) ().start2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator1_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<matrix_range>,
+ public iterator_base_traits<typename subiterator1_type::iterator_category>::template
+ iterator_base<iterator1, value_type>::type {
+ public:
+ typedef typename subiterator1_type::value_type value_type;
+ typedef typename subiterator1_type::difference_type difference_type;
+ typedef typename subiterator1_type::reference reference;
+ typedef typename subiterator1_type::pointer pointer;
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &mr, const subiterator1_type &it):
+ container_reference<self_type> (mr), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &mr = (*this) ();
+ return mr.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &mr = (*this) ();
+ return mr.find2 (1, index1 (), mr.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 () - (*this) ().start1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 () - (*this) ().start2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator1_type it_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_range>,
+ public iterator_base_traits<typename const_subiterator2_type::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename const_subiterator2_type::value_type value_type;
+ typedef typename const_subiterator2_type::difference_type difference_type;
+ typedef typename const_subiterator2_type::reference reference;
+ typedef typename const_subiterator2_type::pointer pointer;
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mr, const const_subiterator2_type &it):
+ container_const_reference<self_type> (mr), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &mr = (*this) ();
+ return mr.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &mr = (*this) ();
+ return mr.find1 (1, mr.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 () - (*this) ().start1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 () - (*this) ().start2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator2_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<matrix_range>,
+ public iterator_base_traits<typename subiterator2_type::iterator_category>::template
+ iterator_base<iterator2, value_type>::type {
+ public:
+ typedef typename subiterator2_type::value_type value_type;
+ typedef typename subiterator2_type::difference_type difference_type;
+ typedef typename subiterator2_type::reference reference;
+ typedef typename subiterator2_type::pointer pointer;
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &mr, const subiterator2_type &it):
+ container_reference<self_type> (mr), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &mr = (*this) ();
+ return mr.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &mr = (*this) ();
+ return mr.find1 (1, mr.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it_.index1 () - (*this) ().start1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it_.index2 () - (*this) ().start2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator2_type it_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ range_type r1_;
+ range_type r2_;
+ };
+
+ // Simple Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_range<M> subrange (M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
+ typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
+ return matrix_range<M> (data, range_type (start1, stop1), range_type (start2, stop2));
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_range<const M> subrange (const M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
+ typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
+ return matrix_range<const M> (data, range_type (start1, stop1), range_type (start2, stop2));
+ }
+
+ // Generic Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ return matrix_range<M> (data, r1, r2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_range<const M> project (const M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2);
+ return matrix_range<const M> (data, r1, r2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_range<M> project (matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+
+ // Specialization of temporary_traits
+ template <class M>
+ struct matrix_temporary_traits< matrix_range<M> >
+ : matrix_temporary_traits< M > {} ;
+ template <class M>
+ struct matrix_temporary_traits< const matrix_range<M> >
+ : matrix_temporary_traits< M > {} ;
+
+ template <class M>
+ struct vector_temporary_traits< matrix_range<M> >
+ : vector_temporary_traits< M > {} ;
+ template <class M>
+ struct vector_temporary_traits< const matrix_range<M> >
+ : vector_temporary_traits< M > {} ;
+
+ // Matrix based slice class
+ template<class M>
+ class matrix_slice:
+ public matrix_expression<matrix_slice<M> > {
+
+ typedef matrix_slice<M> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef basic_slice<size_type, difference_type> slice_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
+ data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
+ // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
+ // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
+ }
+ BOOST_UBLAS_INLINE
+ matrix_slice (const matrix_closure_type &data, const slice_type &s1, const slice_type &s2, int):
+ data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
+ // Early checking of preconditions.
+ // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
+ // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
+ // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
+ // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start1 () const {
+ return s1_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type start2 () const {
+ return s2_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride1 () const {
+ return s1_.stride ();
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride2 () const {
+ return s2_.stride ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return s1_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return s2_.size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return data_ (s1_ (i), s2_ (j));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return data_ (s1_ (i), s2_ (j));
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ return data_ (s1_ (i), s2_ (j));
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that matrix_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ matrix_slice<matrix_type> project (const range_type &r1, const range_type &r2) const {
+ return matrix_slice<matrix_type> (data_, s1_.compose (r1.preprocess (data_.size1 ())), s2_.compose (r2.preprocess (data_.size2 ())), 0);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_slice<matrix_type> project (const slice_type &s1, const slice_type &s2) const {
+ return matrix_slice<matrix_type> (data_, s1_.compose (s1.preprocess (data_.size1 ())), s2_.compose (s2.preprocess (data_.size2 ())), 0);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_slice &operator = (const matrix_slice &ms) {
+ matrix_assign<scalar_assign> (*this, ms);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_slice &assign_temporary (matrix_slice &ms) {
+ return *this = ms;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_slice &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_slice& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_slice& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_slice &ms) const {
+ return (*this).data_.same_closure (ms.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_slice &ms) const {
+ return (*this).data_ == ms.data_ && s1_ == ms.s1_ && s2_ == ms.s2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_slice ms) {
+ if (this != &ms) {
+ BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ());
+ matrix_swap<scalar_swap> (*this, ms);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_slice ms1, matrix_slice ms2) {
+ ms1.swap (ms2);
+ }
+
+ // Iterator types
+ private:
+ // Use slice as an index - FIXME this fails for packed assignment
+ typedef typename slice_type::const_iterator const_subiterator1_type;
+ typedef typename slice_type::const_iterator subiterator1_type;
+ typedef typename slice_type::const_iterator const_subiterator2_type;
+ typedef typename slice_type::const_iterator subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<matrix_slice<matrix_type>,
+ typename matrix_type::iterator1::iterator_category> iterator1;
+ typedef indexed_iterator2<matrix_slice<matrix_type>,
+ typename matrix_type::iterator2::iterator_category> iterator2;
+ typedef indexed_const_iterator1<matrix_slice<matrix_type>,
+ typename matrix_type::const_iterator1::iterator_category> const_iterator1;
+ typedef indexed_const_iterator2<matrix_slice<matrix_type>,
+ typename matrix_type::const_iterator2::iterator_category> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, i, j);
+#else
+ return iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, i, j);
+#else
+ return iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
+#endif
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_slice>,
+ public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename M::const_iterator1::value_type value_type;
+ typedef typename M::const_iterator1::difference_type difference_type;
+ typedef typename M::const_reference reference; //FIXME due to indexing access
+ typedef typename M::const_iterator1::pointer pointer;
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return const_iterator2 ((*this) (), it1_, it2_ ().end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<matrix_slice>,
+ public iterator_base_traits<typename M::iterator1::iterator_category>::template
+ iterator_base<iterator1, value_type>::type {
+ public:
+ typedef typename M::iterator1::value_type value_type;
+ typedef typename M::iterator1::difference_type difference_type;
+ typedef typename M::reference reference; //FIXME due to indexing access
+ typedef typename M::iterator1::pointer pointer;
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return iterator2 ((*this) (), it1_, it2_ ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return iterator2 ((*this) (), it1_, it2_ ().end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_slice>,
+ public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename M::const_iterator2::value_type value_type;
+ typedef typename M::const_iterator2::difference_type difference_type;
+ typedef typename M::const_reference reference; //FIXME due to indexing access
+ typedef typename M::const_iterator2::pointer pointer;
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return const_iterator1 ((*this) (), it1_ ().end (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<matrix_slice>,
+ public iterator_base_traits<typename M::iterator2::iterator_category>::template
+ iterator_base<iterator2, value_type>::type {
+ public:
+ typedef typename M::iterator2::value_type value_type;
+ typedef typename M::iterator2::difference_type difference_type;
+ typedef typename M::reference reference; //FIXME due to indexing access
+ typedef typename M::iterator2::pointer pointer;
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return iterator1 ((*this) (), it1_ ().begin (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return iterator1 ((*this) (), it1_ ().end (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ slice_type s1_;
+ slice_type s2_;
+ };
+
+ // Simple Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_slice<M> subslice (M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
+ typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
+ return matrix_slice<M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_slice<const M> subslice (const M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
+ typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
+ return matrix_slice<const M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
+ }
+
+ // Generic Projections
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
+ return matrix_slice<M> (data, s1, s2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
+ // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
+ return matrix_slice<const M> (data, s1, s2);
+ }
+ // ISSUE in the following two functions it would be logical to use matrix_slice<V>::range_type but this confuses VC7.1 and 8.0
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
+ return data.project (s1, s2);
+ }
+ template<class M>
+ BOOST_UBLAS_INLINE
+ const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
+ return data.project (s1, s2);
+ }
+
+ // Specialization of temporary_traits
+ template <class M>
+ struct matrix_temporary_traits< matrix_slice<M> >
+ : matrix_temporary_traits< M > {};
+ template <class M>
+ struct matrix_temporary_traits< const matrix_slice<M> >
+ : matrix_temporary_traits< M > {};
+
+ template <class M>
+ struct vector_temporary_traits< matrix_slice<M> >
+ : vector_temporary_traits< M > {};
+ template <class M>
+ struct vector_temporary_traits< const matrix_slice<M> >
+ : vector_temporary_traits< M > {};
+
+ // Matrix based indirection class
+ // Contributed by Toon Knapen.
+ // Extended and optimized by Kresimir Fresl.
+ /** \brief A matrix referencing a non continuous submatrix of elements given another matrix of indices.
+ *
+ * It is the most general version of any submatrices because it uses another matrix of indices to reference
+ * the submatrix.
+ *
+ * The matrix of indices can be of any type with the restriction that its elements must be
+ * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
+ * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
+ * - \c boost::numeric::ublas::matrix<int> can work too (\c int can be replaced by another integer type)
+ * - etc...
+ *
+ * An indirect matrix can be used as a normal matrix in any expression. If the specified indirect matrix
+ * falls outside that of the indices of the matrix, then the \c matrix_indirect is not a well formed
+ * \i Matrix \i Expression and access to an element outside of indices of the matrix is \b undefined.
+ *
+ * \tparam V the type of the referenced matrix, for example \c matrix<double>)
+ * \tparam IA the type of index matrix. Default is \c ublas::indirect_array<>
+ */
+ template<class M, class IA>
+ class matrix_indirect:
+ public matrix_expression<matrix_indirect<M, IA> > {
+
+ typedef matrix_indirect<M, IA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef M matrix_type;
+ typedef IA indirect_array_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef basic_slice<size_type, difference_type> slice_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ matrix_indirect (matrix_type &data, size_type size1, size_type size2):
+ data_ (data), ia1_ (size1), ia2_ (size2) {}
+ BOOST_UBLAS_INLINE
+ matrix_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
+ data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
+ BOOST_UBLAS_INLINE
+ matrix_indirect (const matrix_closure_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2, int):
+ data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return ia1_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return ia2_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ const indirect_array_type &indirect1 () const {
+ return ia1_;
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array_type &indirect1 () {
+ return ia1_;
+ }
+ BOOST_UBLAS_INLINE
+ const indirect_array_type &indirect2 () const {
+ return ia2_;
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array_type &indirect2 () {
+ return ia2_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ return data_ (ia1_ (i), ia2_ (j));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ return data_ (ia1_ (i), ia2_ (j));
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ return data_ (ia1_ (i), ia2_ (j));
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that matrix_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ matrix_indirect<matrix_type, indirect_array_type> project (const range_type &r1, const range_type &r2) const {
+ return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (r1.preprocess (data_.size1 ())), ia2_.compose (r2.preprocess (data_.size2 ())), 0);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_indirect<matrix_type, indirect_array_type> project (const slice_type &s1, const slice_type &s2) const {
+ return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (s1.preprocess (data_.size1 ())), ia2_.compose (s2.preprocess (data_.size2 ())), 0);
+ }
+ BOOST_UBLAS_INLINE
+ matrix_indirect<matrix_type, indirect_array_type> project (const indirect_array_type &ia1, const indirect_array_type &ia2) const {
+ return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (ia1.preprocess (data_.size1 ())), ia2_.compose (ia2.preprocess (data_.size2 ())), 0);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ matrix_indirect &operator = (const matrix_indirect &mi) {
+ matrix_assign<scalar_assign> (*this, mi);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_indirect &assign_temporary (matrix_indirect &mi) {
+ return *this = mi;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ matrix_indirect &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_indirect& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ matrix_indirect& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const matrix_indirect &mi) const {
+ return (*this).data_.same_closure (mi.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const matrix_indirect &mi) const {
+ return (*this).data_ == mi.data_ && ia1_ == mi.ia1_ && ia2_ == mi.ia2_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (matrix_indirect mi) {
+ if (this != &mi) {
+ BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ());
+ matrix_swap<scalar_swap> (*this, mi);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (matrix_indirect mi1, matrix_indirect mi2) {
+ mi1.swap (mi2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename IA::const_iterator const_subiterator1_type;
+ typedef typename IA::const_iterator subiterator1_type;
+ typedef typename IA::const_iterator const_subiterator2_type;
+ typedef typename IA::const_iterator subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
+ typename matrix_type::iterator1::iterator_category> iterator1;
+ typedef indexed_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
+ typename matrix_type::iterator2::iterator_category> iterator2;
+ typedef indexed_const_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
+ typename matrix_type::const_iterator1::iterator_category> const_iterator1;
+ typedef indexed_const_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
+ typename matrix_type::const_iterator2::iterator_category> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator1 (*this, i, j);
+#else
+ return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator1 (*this, i, j);
+#else
+ return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator2 (*this, i, j);
+#else
+ return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int /* rank */, size_type i, size_type j) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator2 (*this, i, j);
+#else
+ return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
+#endif
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<matrix_indirect>,
+ public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
+ iterator_base<const_iterator1, value_type>::type {
+ public:
+ typedef typename M::const_iterator1::value_type value_type;
+ typedef typename M::const_iterator1::difference_type difference_type;
+ typedef typename M::const_reference reference; //FIXME due to indexing access
+ typedef typename M::const_iterator1::pointer pointer;
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return const_iterator2 ((*this) (), it1_, it2_ ().end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<matrix_indirect>,
+ public iterator_base_traits<typename M::iterator1::iterator_category>::template
+ iterator_base<iterator1, value_type>::type {
+ public:
+ typedef typename M::iterator1::value_type value_type;
+ typedef typename M::iterator1::difference_type difference_type;
+ typedef typename M::reference reference; //FIXME due to indexing access
+ typedef typename M::iterator1::pointer pointer;
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return iterator2 ((*this) (), it1_, it2_ ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return iterator2 ((*this) (), it1_, it2_ ().end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<matrix_indirect>,
+ public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
+ iterator_base<const_iterator2, value_type>::type {
+ public:
+ typedef typename M::const_iterator2::value_type value_type;
+ typedef typename M::const_iterator2::difference_type difference_type;
+ typedef typename M::const_reference reference; //FIXME due to indexing access
+ typedef typename M::const_iterator2::pointer pointer;
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return const_iterator1 ((*this) (), it1_ ().end (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<matrix_indirect>,
+ public iterator_base_traits<typename M::iterator2::iterator_category>::template
+ iterator_base<iterator2, value_type>::type {
+ public:
+ typedef typename M::iterator2::value_type value_type;
+ typedef typename M::iterator2::difference_type difference_type;
+ typedef typename M::reference reference; //FIXME due to indexing access
+ typedef typename M::iterator2::pointer pointer;
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
+ container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ return (*this) ().data_ (*it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return iterator1 ((*this) (), it1_ ().begin (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return iterator1 ((*this) (), it1_ ().end (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator1_type it1_;
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ indirect_array_type ia1_;
+ indirect_array_type ia2_;
+ };
+
+ // Projections
+ template<class M, class A>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<M, indirect_array<A> > project (M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ return matrix_indirect<M, indirect_array<A> > (data, ia1, ia2);
+ }
+ template<class M, class A>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<const M, indirect_array<A> > project (const M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2);
+ return matrix_indirect<const M, indirect_array<A> > (data, ia1, ia2);
+ }
+ template<class M, class IA>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+ template<class M, class IA>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
+ return data.project (r1, r2);
+ }
+ template<class M, class IA>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
+ return data.project (s1, s2);
+ }
+ template<class M, class IA>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
+ return data.project (s1, s2);
+ }
+ template<class M, class A>
+ BOOST_UBLAS_INLINE
+ matrix_indirect<M, indirect_array<A> > project (matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ return data.project (ia1, ia2);
+ }
+ template<class M, class A>
+ BOOST_UBLAS_INLINE
+ const matrix_indirect<M, indirect_array<A> > project (const matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
+ return data.project (ia1, ia2);
+ }
+
+ /// Specialization of temporary_traits
+ template <class M>
+ struct matrix_temporary_traits< matrix_indirect<M> >
+ : matrix_temporary_traits< M > {};
+ template <class M>
+ struct matrix_temporary_traits< const matrix_indirect<M> >
+ : matrix_temporary_traits< M > {};
+
+ template <class M>
+ struct vector_temporary_traits< matrix_indirect<M> >
+ : vector_temporary_traits< M > {};
+ template <class M>
+ struct vector_temporary_traits< const matrix_indirect<M> >
+ : vector_temporary_traits< M > {};
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2007
+// Joerg Walter, Mathias Koch, Gunter Winkler
+//
+// 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_MATRIX_SPARSE_
+#define _BOOST_UBLAS_MATRIX_SPARSE_
+
+#include <boost/numeric/ublas/vector_sparse.hpp>
+#include <boost/numeric/ublas/matrix_expression.hpp>
+#include <boost/numeric/ublas/detail/matrix_assign.hpp>
+#if BOOST_UBLAS_TYPE_CHECK
+#include <boost/numeric/ublas/matrix.hpp>
+#endif
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+#ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+
+ template<class M>
+ class sparse_matrix_element:
+ public container_reference<M> {
+ public:
+ typedef M matrix_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ typedef const value_type &const_reference;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+
+ private:
+ // Proxied element operations
+ void get_d () const {
+ const_pointer p = (*this) ().find_element (i_, j_);
+ if (p)
+ d_ = *p;
+ else
+ d_ = value_type/*zero*/();
+ }
+
+ void set (const value_type &s) const {
+ pointer p = (*this) ().find_element (i_, j_);
+ if (!p)
+ (*this) ().insert_element (i_, j_, s);
+ else
+ *p = s;
+ }
+
+ public:
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element (matrix_type &m, size_type i, size_type j):
+ container_reference<matrix_type> (m), i_ (i), j_ (j) {
+ }
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element (const sparse_matrix_element &p):
+ container_reference<matrix_type> (p), i_ (p.i_), j_ (p.j_) {}
+ BOOST_UBLAS_INLINE
+ ~sparse_matrix_element () {
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator = (const sparse_matrix_element &p) {
+ // Overide the implict copy assignment
+ p.get_d ();
+ set (p.d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator = (const D &d) {
+ set (d);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator += (const D &d) {
+ get_d ();
+ d_ += d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator -= (const D &d) {
+ get_d ();
+ d_ -= d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator *= (const D &d) {
+ get_d ();
+ d_ *= d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_matrix_element &operator /= (const D &d) {
+ get_d ();
+ d_ /= d;
+ set (d_);
+ return *this;
+ }
+
+ // Comparison
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator == (const D &d) const {
+ get_d ();
+ return d_ == d;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator != (const D &d) const {
+ get_d ();
+ return d_ != d;
+ }
+
+ // Conversion - weak link in proxy as d_ is not a perfect alias for the element
+ BOOST_UBLAS_INLINE
+ operator const_reference () const {
+ get_d ();
+ return d_;
+ }
+
+ // Conversion to reference - may be invalidated
+ BOOST_UBLAS_INLINE
+ value_type& ref () const {
+ const pointer p = (*this) ().find_element (i_, j_);
+ if (!p)
+ return (*this) ().insert_element (i_, j_, value_type/*zero*/());
+ else
+ return *p;
+ }
+
+ private:
+ size_type i_;
+ size_type j_;
+ mutable value_type d_;
+ };
+
+ /*
+ * Generalise explicit reference access
+ */
+ namespace detail {
+ template <class V>
+ struct element_reference<sparse_matrix_element<V> > {
+ typedef typename V::value_type& reference;
+ static reference get_reference (const sparse_matrix_element<V>& sve)
+ {
+ return sve.ref ();
+ }
+ };
+ }
+
+
+ template<class M>
+ struct type_traits<sparse_matrix_element<M> > {
+ typedef typename M::value_type element_type;
+ typedef type_traits<sparse_matrix_element<M> > self_type;
+ typedef typename type_traits<element_type>::value_type value_type;
+ typedef typename type_traits<element_type>::const_reference const_reference;
+ typedef sparse_matrix_element<M> reference;
+ typedef typename type_traits<element_type>::real_type real_type;
+ typedef typename type_traits<element_type>::precision_type precision_type;
+
+ static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
+ static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type real (const_reference t) {
+ return type_traits<element_type>::real (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type imag (const_reference t) {
+ return type_traits<element_type>::imag (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type conj (const_reference t) {
+ return type_traits<element_type>::conj (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type type_abs (const_reference t) {
+ return type_traits<element_type>::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type type_sqrt (const_reference t) {
+ return type_traits<element_type>::type_sqrt (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_1 (const_reference t) {
+ return type_traits<element_type>::norm_1 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_2 (const_reference t) {
+ return type_traits<element_type>::norm_2 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_inf (const_reference t) {
+ return type_traits<element_type>::norm_inf (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool equals (const_reference t1, const_reference t2) {
+ return type_traits<element_type>::equals (t1, t2);
+ }
+ };
+
+ template<class M1, class T2>
+ struct promote_traits<sparse_matrix_element<M1>, T2> {
+ typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type, T2>::promote_type promote_type;
+ };
+ template<class T1, class M2>
+ struct promote_traits<T1, sparse_matrix_element<M2> > {
+ typedef typename promote_traits<T1, typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
+ };
+ template<class M1, class M2>
+ struct promote_traits<sparse_matrix_element<M1>, sparse_matrix_element<M2> > {
+ typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type,
+ typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
+ };
+
+#endif
+
+ /** \brief Index map based sparse matrix of values of type \c T
+ *
+ * This class represents a matrix by using a \c key to value mapping. The default type is
+ * \code template<class T, class L = row_major, class A = map_std<std::size_t, T> > class mapped_matrix; \endcode
+ * So, by default a STL map container is used to associate keys and values. The key is computed depending on
+ * the layout type \c L as \code key = layout_type::element(i, size1_, j, size2_); \endcode
+ * which means \code key = (i*size2+j) \endcode for a row major matrix.
+ * Limitations: The matrix size must not exceed \f$(size1*size2) < \f$ \code std::limits<std::size_t> \endcode.
+ * The \ref find1() and \ref find2() operations have a complexity of at least \f$\mathcal{O}(log(nnz))\f$, depending
+ * on the efficiency of \c std::lower_bound on the key set of the map.
+ * Orientation and storage can also be specified, otherwise a row major orientation is used.
+ * It is \b not required by the storage to initialize elements of the matrix. By default, the orientation is \c row_major.
+ *
+ * \sa fwd.hpp, storage_sparse.hpp
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major
+ */
+ template<class T, class L, class A>
+ class mapped_matrix:
+ public matrix_container<mapped_matrix<T, L, A> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T * const_pointer;
+ typedef L layout_type;
+ typedef mapped_matrix<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef A array_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ typedef typename detail::map_traits<A, T>::reference reference;
+#else
+ typedef sparse_matrix_element<self_type> reference;
+#endif
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef mapped_vector<T, A> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ mapped_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ () {}
+ BOOST_UBLAS_INLINE
+ mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ () {
+ detail::map_reserve (data (), restrict_capacity (non_zeros));
+ }
+ BOOST_UBLAS_INLINE
+ mapped_matrix (const mapped_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
+ detail::map_reserve (data (), restrict_capacity (non_zeros));
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return detail::map_capacity (data ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return data (). size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ size_type restrict_capacity (size_type non_zeros) const {
+ // Guarding against overflow - thanks to Alexei Novakov for the hint.
+ // non_zeros = (std::min) (non_zeros, size1_ * size2_);
+ if (size1_ > 0 && non_zeros / size1_ >= size2_)
+ non_zeros = size1_ * size2_;
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ // FIXME preserve unimplemented
+ BOOST_UBLAS_CHECK (!preserve, internal_logic ());
+ size1_ = size1;
+ size2_ = size2;
+ data ().clear ();
+ }
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type non_zeros, bool preserve = true) {
+ detail::map_reserve (data (), restrict_capacity (non_zeros));
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i, size_type j) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i, size_type j) const {
+ const size_type element = layout_type::element (i, size1_, j, size2_);
+ const_subiterator_type it (data ().find (element));
+ if (it == data ().end ())
+ return 0;
+ BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
+ return &(*it).second;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ const size_type element = layout_type::element (i, size1_, j, size2_);
+ const_subiterator_type it (data ().find (element));
+ if (it == data ().end ())
+ return zero_;
+ BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
+ return (*it).second;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ const size_type element = layout_type::element (i, size1_, j, size2_);
+ std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/())));
+ BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
+ return (ii.first)->second;
+#else
+ return reference (*this, i, j);
+#endif
+ }
+
+ // Element assingment
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
+ const size_type element = layout_type::element (i, size1_, j, size2_);
+ std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, t)));
+ BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
+ if (!ii.second) // existing element
+ (ii.first)->second = t;
+ return (ii.first)->second;
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_));
+ if (it == data ().end ())
+ return;
+ data ().erase (it);
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ data ().clear ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ mapped_matrix &operator = (const mapped_matrix &m) {
+ if (this != &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ }
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_matrix &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ mapped_matrix &assign_temporary (mapped_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae, detail::map_capacity (data ()));
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae, detail::map_capacity (data ()));
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_matrix &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae, detail::map_capacity (data ()));
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_matrix &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (mapped_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (mapped_matrix &m1, mapped_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use storage iterator
+ typedef typename A::const_iterator const_subiterator_type;
+ typedef typename A::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ const size_type element = layout_type::element (i, size1_, j, size2_);
+ subiterator_type it (data ().find (element));
+ BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
+ BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
+ return it->second;
+ }
+
+ public:
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
+ const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
+ const_subiterator_type it_end (data ().end ());
+ size_type index1 = size_type (-1);
+ size_type index2 = size_type (-1);
+ while (rank == 1 && it != it_end) {
+ index1 = layout_type::index_i ((*it).first, size1_, size2_);
+ index2 = layout_type::index_j ((*it).first, size1_, size2_);
+ if (direction > 0) {
+ if ((index1 >= i && index2 == j) || (i >= size1_))
+ break;
+ ++ i;
+ } else /* if (direction < 0) */ {
+ if ((index1 <= i && index2 == j) || (i == 0))
+ break;
+ -- i;
+ }
+ it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
+ }
+ if (rank == 1 && index2 != j) {
+ if (direction > 0)
+ i = size1_;
+ else /* if (direction < 0) */
+ i = 0;
+ rank = 0;
+ }
+ return const_iterator1 (*this, rank, i, j, it);
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
+ subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
+ subiterator_type it_end (data ().end ());
+ size_type index1 = size_type (-1);
+ size_type index2 = size_type (-1);
+ while (rank == 1 && it != it_end) {
+ index1 = layout_type::index_i ((*it).first, size1_, size2_);
+ index2 = layout_type::index_j ((*it).first, size1_, size2_);
+ if (direction > 0) {
+ if ((index1 >= i && index2 == j) || (i >= size1_))
+ break;
+ ++ i;
+ } else /* if (direction < 0) */ {
+ if ((index1 <= i && index2 == j) || (i == 0))
+ break;
+ -- i;
+ }
+ it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
+ }
+ if (rank == 1 && index2 != j) {
+ if (direction > 0)
+ i = size1_;
+ else /* if (direction < 0) */
+ i = 0;
+ rank = 0;
+ }
+ return iterator1 (*this, rank, i, j, it);
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
+ const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
+ const_subiterator_type it_end (data ().end ());
+ size_type index1 = size_type (-1);
+ size_type index2 = size_type (-1);
+ while (rank == 1 && it != it_end) {
+ index1 = layout_type::index_i ((*it).first, size1_, size2_);
+ index2 = layout_type::index_j ((*it).first, size1_, size2_);
+ if (direction > 0) {
+ if ((index2 >= j && index1 == i) || (j >= size2_))
+ break;
+ ++ j;
+ } else /* if (direction < 0) */ {
+ if ((index2 <= j && index1 == i) || (j == 0))
+ break;
+ -- j;
+ }
+ it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
+ }
+ if (rank == 1 && index1 != i) {
+ if (direction > 0)
+ j = size2_;
+ else /* if (direction < 0) */
+ j = 0;
+ rank = 0;
+ }
+ return const_iterator2 (*this, rank, i, j, it);
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
+ subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
+ subiterator_type it_end (data ().end ());
+ size_type index1 = size_type (-1);
+ size_type index2 = size_type (-1);
+ while (rank == 1 && it != it_end) {
+ index1 = layout_type::index_i ((*it).first, size1_, size2_);
+ index2 = layout_type::index_j ((*it).first, size1_, size2_);
+ if (direction > 0) {
+ if ((index2 >= j && index1 == i) || (j >= size2_))
+ break;
+ ++ j;
+ } else /* if (direction < 0) */ {
+ if ((index2 <= j && index1 == i) || (j == 0))
+ break;
+ -- j;
+ }
+ it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
+ }
+ if (rank == 1 && index1 != i) {
+ if (direction > 0)
+ j = size2_;
+ else /* if (direction < 0) */
+ j = 0;
+ rank = 0;
+ }
+ return iterator2 (*this, rank, i, j, it);
+ }
+
+
+ class const_iterator1:
+ public container_const_reference<mapped_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename mapped_matrix::value_type value_type;
+ typedef typename mapped_matrix::difference_type difference_type;
+ typedef typename mapped_matrix::const_reference reference;
+ typedef const typename mapped_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else
+ *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else
+ *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+ class iterator1:
+ public container_reference<mapped_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename mapped_matrix::value_type value_type;
+ typedef typename mapped_matrix::difference_type difference_type;
+ typedef typename mapped_matrix::true_reference reference;
+ typedef typename mapped_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else
+ *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else
+ *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+ class const_iterator2:
+ public container_const_reference<mapped_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename mapped_matrix::value_type value_type;
+ typedef typename mapped_matrix::difference_type difference_type;
+ typedef typename mapped_matrix::const_reference reference;
+ typedef const typename mapped_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else
+ *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else
+ *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ class iterator2:
+ public container_reference<mapped_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename mapped_matrix::value_type value_type;
+ typedef typename mapped_matrix::difference_type difference_type;
+ typedef typename mapped_matrix::true_reference reference;
+ typedef typename mapped_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else
+ *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else
+ *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ const self_type &m = (*this) ();
+ BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+ ar & serialization::make_nvp("size1",s1);
+ ar & serialization::make_nvp("size2",s2);
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("data", data_);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ static const value_type zero_;
+ };
+
+ template<class T, class L, class A>
+ const typename mapped_matrix<T, L, A>::value_type mapped_matrix<T, L, A>::zero_ = value_type/*zero*/();
+
+
+ // Vector index map based sparse matrix class
+ template<class T, class L, class A>
+ class mapped_vector_of_mapped_vector:
+ public matrix_container<mapped_vector_of_mapped_vector<T, L, A> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef A array_type;
+ typedef const A const_array_type;
+ typedef L layout_type;
+ typedef mapped_vector_of_mapped_vector<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ typedef typename detail::map_traits<typename A::data_value_type, T>::reference reference;
+#else
+ typedef sparse_matrix_element<self_type> reference;
+#endif
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef mapped_vector<T, typename A::value_type> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef typename A::value_type::second_type vector_data_value_type;
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ () {
+ data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
+ }
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ () {
+ data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
+ }
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
+ data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ size_type non_zeros = 0;
+ for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
+ non_zeros += detail::map_capacity (*itv);
+ return non_zeros;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ size_type filled = 0;
+ for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
+ filled += (*itv).size ();
+ return filled;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const_array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ // FIXME preserve unimplemented
+ BOOST_UBLAS_CHECK (!preserve, internal_logic ());
+ size1_ = size1;
+ size2_ = size2;
+ data ().clear ();
+ data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i, size_type j) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i, size_type j) const {
+ const size_type element1 = layout_type::index_M (i, j);
+ const size_type element2 = layout_type::index_m (i, j);
+ vector_const_subiterator_type itv (data ().find (element1));
+ if (itv == data ().end ())
+ return 0;
+ BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
+ const_subiterator_type it ((*itv).second.find (element2));
+ if (it == (*itv).second.end ())
+ return 0;
+ BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
+ return &(*it).second;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ const size_type element1 = layout_type::index_M (i, j);
+ const size_type element2 = layout_type::index_m (i, j);
+ vector_const_subiterator_type itv (data ().find (element1));
+ if (itv == data ().end ())
+ return zero_;
+ BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
+ const_subiterator_type it ((*itv).second.find (element2));
+ if (it == (*itv).second.end ())
+ return zero_;
+ BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
+ return (*it).second;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ const size_type element1 = layout_type::index_M (i, j);
+ const size_type element2 = layout_type::index_m (i, j);
+ vector_data_value_type& vd (data () [element1]);
+ std::pair<subiterator_type, bool> ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type/*zero*/())));
+ BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
+ return (ii.first)->second;
+#else
+ return reference (*this, i, j);
+#endif
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
+ const size_type element1 = layout_type::index_M (i, j);
+ const size_type element2 = layout_type::index_m (i, j);
+
+ vector_data_value_type& vd (data () [element1]);
+ std::pair<subiterator_type, bool> ii (vd.insert (typename vector_data_value_type::value_type (element2, t)));
+ BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
+ if (!ii.second) // existing element
+ (ii.first)->second = t;
+ return (ii.first)->second;
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ vector_subiterator_type itv (data ().find (layout_type::index_M (i, j)));
+ if (itv == data ().end ())
+ return;
+ subiterator_type it ((*itv).second.find (layout_type::index_m (i, j)));
+ if (it == (*itv).second.end ())
+ return;
+ (*itv).second.erase (it);
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ data ().clear ();
+ data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) {
+ if (this != &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ }
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 ());
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_vector_of_mapped_vector& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (mapped_vector_of_mapped_vector &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use storage iterators
+ typedef typename A::const_iterator vector_const_subiterator_type;
+ typedef typename A::iterator vector_subiterator_type;
+ typedef typename A::value_type::second_type::const_iterator const_subiterator_type;
+ typedef typename A::value_type::second_type::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ const size_type element1 = layout_type::index_M (i, j);
+ const size_type element2 = layout_type::index_m (i, j);
+ vector_subiterator_type itv (data ().find (element1));
+ BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ());
+ BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
+ subiterator_type it ((*itv).second.find (element2));
+ BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
+
+ return it->second;
+ }
+
+ public:
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
+ BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
+ for (;;) {
+ vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
+ vector_const_subiterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
+
+ const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
+ const_subiterator_type it_end ((*itv).second.end ());
+ if (rank == 0) {
+ // advance to the first available major index
+ size_type M = itv->first;
+ size_type m;
+ if (it != it_end) {
+ m = it->first;
+ } else {
+ m = layout_type::size_m(size1_, size2_);
+ }
+ size_type first_i = layout_type::index_M(M,m);
+ return const_iterator1 (*this, rank, first_i, j, itv, it);
+ }
+ if (it != it_end && (*it).first == layout_type::index_m (i, j))
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = (*it).first;
+ } else {
+ if (i >= size1_)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == (*itv).second.begin ())
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ -- it;
+ i = (*it).first;
+ } else {
+ if (i == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
+ BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
+ for (;;) {
+ vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
+ vector_subiterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
+
+ subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
+ subiterator_type it_end ((*itv).second.end ());
+ if (rank == 0) {
+ // advance to the first available major index
+ size_type M = itv->first;
+ size_type m;
+ if (it != it_end) {
+ m = it->first;
+ } else {
+ m = layout_type::size_m(size1_, size2_);
+ }
+ size_type first_i = layout_type::index_M(M,m);
+ return iterator1 (*this, rank, first_i, j, itv, it);
+ }
+ if (it != it_end && (*it).first == layout_type::index_m (i, j))
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = (*it).first;
+ } else {
+ if (i >= size1_)
+ return iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == (*itv).second.begin ())
+ return iterator1 (*this, rank, i, j, itv, it);
+ -- it;
+ i = (*it).first;
+ } else {
+ if (i == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
+ BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
+ for (;;) {
+ vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
+ vector_const_subiterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
+
+ const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
+ const_subiterator_type it_end ((*itv).second.end ());
+ if (rank == 0) {
+ // advance to the first available major index
+ size_type M = itv->first;
+ size_type m;
+ if (it != it_end) {
+ m = it->first;
+ } else {
+ m = layout_type::size_m(size1_, size2_);
+ }
+ size_type first_j = layout_type::index_m(M,m);
+ return const_iterator2 (*this, rank, i, first_j, itv, it);
+ }
+ if (it != it_end && (*it).first == layout_type::index_m (i, j))
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = (*it).first;
+ } else {
+ if (j >= size2_)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == (*itv).second.begin ())
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ -- it;
+ j = (*it).first;
+ } else {
+ if (j == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
+ BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
+ for (;;) {
+ vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
+ vector_subiterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
+
+ subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
+ subiterator_type it_end ((*itv).second.end ());
+ if (rank == 0) {
+ // advance to the first available major index
+ size_type M = itv->first;
+ size_type m;
+ if (it != it_end) {
+ m = it->first;
+ } else {
+ m = layout_type::size_m(size1_, size2_);
+ }
+ size_type first_j = layout_type::index_m(M,m);
+ return iterator2 (*this, rank, i, first_j, itv, it);
+ }
+ if (it != it_end && (*it).first == layout_type::index_m (i, j))
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = (*it).first;
+ } else {
+ if (j >= size2_)
+ return iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == (*itv).second.begin ())
+ return iterator2 (*this, rank, i, j, itv, it);
+ -- it;
+ j = (*it).first;
+ } else {
+ if (j == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+
+ class const_iterator1:
+ public container_const_reference<mapped_vector_of_mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename mapped_vector_of_mapped_vector::value_type value_type;
+ typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector_of_mapped_vector::const_reference reference;
+ typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ const self_type &m = (*this) ();
+ if (rank_ == 0) {
+ ++ itv_;
+ i_ = itv_->first;
+ } else {
+ i_ = index1 () + 1;
+ }
+ if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ const self_type &m = (*this) ();
+ if (rank_ == 0) {
+ -- itv_;
+ i_ = itv_->first;
+ } else {
+ i_ = index1 () - 1;
+ }
+ // FIXME: this expression should never become true!
+ if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*itv_).first, (*it_).first);
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*itv_).first, (*it_).first);
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+ class iterator1:
+ public container_reference<mapped_vector_of_mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename mapped_vector_of_mapped_vector::value_type value_type;
+ typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector_of_mapped_vector::true_reference reference;
+ typedef typename mapped_vector_of_mapped_vector::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ self_type &m = (*this) ();
+ if (rank_ == 0) {
+ ++ itv_;
+ i_ = itv_->first;
+ } else {
+ i_ = index1 () + 1;
+ }
+ if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ self_type &m = (*this) ();
+ if (rank_ == 0) {
+ -- itv_;
+ i_ = itv_->first;
+ } else {
+ i_ = index1 () - 1;
+ }
+ // FIXME: this expression should never become true!
+ if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*itv_).first, (*it_).first);
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*itv_).first, (*it_).first);
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+ class const_iterator2:
+ public container_const_reference<mapped_vector_of_mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename mapped_vector_of_mapped_vector::value_type value_type;
+ typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector_of_mapped_vector::const_reference reference;
+ typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ const self_type &m = (*this) ();
+ if (rank_ == 0) {
+ ++ itv_;
+ j_ = itv_->first;
+ } else {
+ j_ = index2 () + 1;
+ }
+ if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ const self_type &m = (*this) ();
+ if (rank_ == 0) {
+ -- itv_;
+ j_ = itv_->first;
+ } else {
+ j_ = index2 () - 1;
+ }
+ // FIXME: this expression should never become true!
+ if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*itv_).first, (*it_).first);
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*itv_).first, (*it_).first);
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ class iterator2:
+ public container_reference<mapped_vector_of_mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename mapped_vector_of_mapped_vector::value_type value_type;
+ typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector_of_mapped_vector::true_reference reference;
+ typedef typename mapped_vector_of_mapped_vector::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ self_type &m = (*this) ();
+ if (rank_ == 0) {
+ ++ itv_;
+ j_ = itv_->first;
+ } else {
+ j_ = index2 () + 1;
+ }
+ if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ self_type &m = (*this) ();
+ if (rank_ == 0) {
+ -- itv_;
+ j_ = itv_->first;
+ } else {
+ j_ = index2 () - 1;
+ }
+ // FIXME: this expression should never become true!
+ if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).second.begin ();
+ if (it_ == (*itv_).second.end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*it_).second;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*itv_).first, (*it_).first);
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*itv_).first, (*it_).first);
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+ ar & serialization::make_nvp("size1",s1);
+ ar & serialization::make_nvp("size2",s2);
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("data", data_);
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ static const value_type zero_;
+ };
+
+ template<class T, class L, class A>
+ const typename mapped_vector_of_mapped_vector<T, L, A>::value_type mapped_vector_of_mapped_vector<T, L, A>::zero_ = value_type/*zero*/();
+
+
+ // Comperssed array based sparse matrix class
+ // Thanks to Kresimir Fresl for extending this to cover different index bases.
+ template<class T, class L, std::size_t IB, class IA, class TA>
+ class compressed_matrix:
+ public matrix_container<compressed_matrix<T, L, IB, IA, TA> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef L layout_type;
+ typedef compressed_matrix<T, L, IB, IA, TA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ // ISSUE require type consistency check
+ // is_convertable (IA::size_type, TA::size_type)
+ typedef typename IA::value_type size_type;
+ // size_type for the data arrays.
+ typedef typename IA::size_type array_size_type;
+ // FIXME difference type for sparse storage iterators should it be in the container?
+ typedef typename IA::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ typedef T &reference;
+#else
+ typedef sparse_matrix_element<self_type> reference;
+#endif
+ typedef IA index_array_type;
+ typedef TA value_array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef compressed_vector<T, IB, IA, TA> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ compressed_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
+ filled1_ (1), filled2_ (0),
+ index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
+ filled1_ (1), filled2_ (0),
+ index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ compressed_matrix (const compressed_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
+ filled1_ (m.filled1_), filled2_ (m.filled2_),
+ index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
+ storage_invariants ();
+ }
+
+ BOOST_UBLAS_INLINE
+ compressed_matrix (const coordinate_matrix<T, L, IB, IA, TA> &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1()), size2_ (m.size2()),
+ index1_data_ (layout_type::size_M (size1_, size2_) + 1)
+ {
+ m.sort();
+ reserve(m.nnz(), false);
+ filled2_ = m.nnz();
+ const_subiterator_type i_start = m.index1_data().begin();
+ const_subiterator_type i_end = (i_start + filled2_);
+ const_subiterator_type i = i_start;
+ size_type r = 1;
+ for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) {
+ i = std::lower_bound(i, i_end, r);
+ index1_data_[r] = k_based( i - i_start );
+ }
+ filled1_ = r + 1;
+ std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin());
+ std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin());
+ index1_data_ [filled1_ - 1] = k_based(filled2_);
+ storage_invariants ();
+ }
+
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
+ filled1_ (1), filled2_ (0),
+ index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1),
+ index2_data_ (capacity_), value_data_ (capacity_) {
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ storage_invariants ();
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return capacity_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return filled2_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ static size_type index_base () {
+ return IB;
+ }
+ BOOST_UBLAS_INLINE
+ array_size_type filled1 () const {
+ return filled1_;
+ }
+ BOOST_UBLAS_INLINE
+ array_size_type filled2 () const {
+ return filled2_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index1_data () const {
+ return index1_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index2_data () const {
+ return index2_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const value_array_type &value_data () const {
+ return value_data_;
+ }
+ BOOST_UBLAS_INLINE
+ void set_filled (const array_size_type& filled1, const array_size_type& filled2) {
+ filled1_ = filled1;
+ filled2_ = filled2;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index1_data () {
+ return index1_data_;
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index2_data () {
+ return index2_data_;
+ }
+ BOOST_UBLAS_INLINE
+ value_array_type &value_data () {
+ return value_data_;
+ }
+ BOOST_UBLAS_INLINE
+ void complete_index1_data () {
+ while (filled1_ <= layout_type::size_M (size1_, size2_)) {
+ this->index1_data_ [filled1_] = k_based (filled2_);
+ ++ this->filled1_;
+ }
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ size_type restrict_capacity (size_type non_zeros) const {
+ non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_));
+ // Guarding against overflow - Thanks to Alexei Novakov for the hint.
+ // non_zeros = (std::min) (non_zeros, size1_ * size2_);
+ if (size1_ > 0 && non_zeros / size1_ >= size2_)
+ non_zeros = size1_ * size2_;
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ // FIXME preserve unimplemented
+ BOOST_UBLAS_CHECK (!preserve, internal_logic ());
+ size1_ = size1;
+ size2_ = size2;
+ capacity_ = restrict_capacity (capacity_);
+ filled1_ = 1;
+ filled2_ = 0;
+ index1_data_.resize (layout_type::size_M (size1_, size2_) + 1);
+ index2_data_.resize (capacity_);
+ value_data_.resize (capacity_);
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ storage_invariants ();
+ }
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type non_zeros, bool preserve = true) {
+ capacity_ = restrict_capacity (non_zeros);
+ if (preserve) {
+ index2_data_.resize (capacity_, size_type ());
+ value_data_.resize (capacity_, value_type ());
+ filled2_ = (std::min) (capacity_, filled2_);
+ }
+ else {
+ index2_data_.resize (capacity_);
+ value_data_.resize (capacity_);
+ filled1_ = 1;
+ filled2_ = 0;
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ }
+ storage_invariants ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i, size_type j) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i, size_type j) const {
+ size_type element1 (layout_type::index_M (i, j));
+ size_type element2 (layout_type::index_m (i, j));
+ if (filled1_ <= element1 + 1)
+ return 0;
+ vector_const_subiterator_type itv (index1_data_.begin () + element1);
+ const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
+ if (it == it_end || *it != k_based (element2))
+ return 0;
+ return &value_data_ [it - index2_data_.begin ()];
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ const_pointer p = find_element (i, j);
+ if (p)
+ return *p;
+ else
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ size_type element1 (layout_type::index_M (i, j));
+ size_type element2 (layout_type::index_m (i, j));
+ if (filled1_ <= element1 + 1)
+ return insert_element (i, j, value_type/*zero*/());
+ pointer p = find_element (i, j);
+ if (p)
+ return *p;
+ else
+ return insert_element (i, j, value_type/*zero*/());
+#else
+ return reference (*this, i, j);
+#endif
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
+ if (filled2_ >= capacity_)
+ reserve (2 * filled2_, true);
+ BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ while (filled1_ <= element1 + 1) {
+ index1_data_ [filled1_] = k_based (filled2_);
+ ++ filled1_;
+ }
+ vector_subiterator_type itv (index1_data_.begin () + element1);
+ subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
+ BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ()); // duplicate bound by lower_bound
+ ++ filled2_;
+ it = index2_data_.begin () + n;
+ std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_);
+ *it = k_based (element2);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_);
+ *itt = t;
+ while (element1 + 1 < filled1_) {
+ ++ index1_data_ [element1 + 1];
+ ++ element1;
+ }
+ storage_invariants ();
+ return *itt;
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ if (element1 + 1 >= filled1_)
+ return;
+ vector_subiterator_type itv (index1_data_.begin () + element1);
+ subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
+ if (it != it_end && *it == k_based (element2)) {
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
+ std::copy (it + 1, index2_data_.begin () + filled2_, it);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy (itt + 1, value_data_.begin () + filled2_, itt);
+ -- filled2_;
+ while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
+ index1_data_ [filled1_ - 1] = 0;
+ -- filled1_;
+ }
+ while (element1 + 1 < filled1_) {
+ -- index1_data_ [element1 + 1];
+ ++ element1;
+ }
+ }
+ storage_invariants ();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ filled1_ = 1;
+ filled2_ = 0;
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ storage_invariants ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ compressed_matrix &operator = (const compressed_matrix &m) {
+ if (this != &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ capacity_ = m.capacity_;
+ filled1_ = m.filled1_;
+ filled2_ = m.filled2_;
+ index1_data_ = m.index1_data_;
+ index2_data_ = m.index2_data_;
+ value_data_ = m.value_data_;
+ }
+ storage_invariants ();
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_matrix &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ compressed_matrix &assign_temporary (compressed_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_matrix &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_matrix &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ compressed_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ compressed_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (compressed_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ std::swap (capacity_, m.capacity_);
+ std::swap (filled1_, m.filled1_);
+ std::swap (filled2_, m.filled2_);
+ index1_data_.swap (m.index1_data_);
+ index2_data_.swap (m.index2_data_);
+ value_data_.swap (m.value_data_);
+ }
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (compressed_matrix &m1, compressed_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Back element insertion and erasure
+ BOOST_UBLAS_INLINE
+ void push_back (size_type i, size_type j, const_reference t) {
+ if (filled2_ >= capacity_)
+ reserve (2 * filled2_, true);
+ BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ while (filled1_ < element1 + 2) {
+ index1_data_ [filled1_] = k_based (filled2_);
+ ++ filled1_;
+ }
+ // must maintain sort order
+ BOOST_UBLAS_CHECK ((filled1_ == element1 + 2 &&
+ (filled2_ == zero_based (index1_data_ [filled1_ - 2]) ||
+ index2_data_ [filled2_ - 1] < k_based (element2))), external_logic ());
+ ++ filled2_;
+ index1_data_ [filled1_ - 1] = k_based (filled2_);
+ index2_data_ [filled2_ - 1] = k_based (element2);
+ value_data_ [filled2_ - 1] = t;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ void pop_back () {
+ BOOST_UBLAS_CHECK (filled1_ > 0 && filled2_ > 0, external_logic ());
+ -- filled2_;
+ while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
+ index1_data_ [filled1_ - 1] = 0;
+ -- filled1_;
+ }
+ -- index1_data_ [filled1_ - 1];
+ storage_invariants ();
+ }
+
+ // Iterator types
+ private:
+ // Use index array iterator
+ typedef typename IA::const_iterator vector_const_subiterator_type;
+ typedef typename IA::iterator vector_subiterator_type;
+ typedef typename IA::const_iterator const_subiterator_type;
+ typedef typename IA::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ pointer p = find_element (i, j);
+ BOOST_UBLAS_CHECK (p, bad_index ());
+ return *p;
+ }
+
+ public:
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
+ for (;;) {
+ array_size_type address1 (layout_type::index_M (i, j));
+ array_size_type address2 (layout_type::index_m (i, j));
+ vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
+ if (filled1_ <= address1 + 1)
+ return const_iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
+
+ const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ if (rank == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*it);
+ } else {
+ if (i >= size1_)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == index2_data_.begin () + zero_based (*itv))
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*(it - 1));
+ } else {
+ if (i == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
+ for (;;) {
+ array_size_type address1 (layout_type::index_M (i, j));
+ array_size_type address2 (layout_type::index_m (i, j));
+ vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
+ if (filled1_ <= address1 + 1)
+ return iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
+
+ subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ if (rank == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*it);
+ } else {
+ if (i >= size1_)
+ return iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == index2_data_.begin () + zero_based (*itv))
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*(it - 1));
+ } else {
+ if (i == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
+ for (;;) {
+ array_size_type address1 (layout_type::index_M (i, j));
+ array_size_type address2 (layout_type::index_m (i, j));
+ vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
+ if (filled1_ <= address1 + 1)
+ return const_iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
+
+ const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ if (rank == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*it);
+ } else {
+ if (j >= size2_)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == index2_data_.begin () + zero_based (*itv))
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*(it - 1));
+ } else {
+ if (j == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
+ for (;;) {
+ array_size_type address1 (layout_type::index_M (i, j));
+ array_size_type address2 (layout_type::index_m (i, j));
+ vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
+ if (filled1_ <= address1 + 1)
+ return iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
+
+ subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
+ subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
+
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ if (rank == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*it);
+ } else {
+ if (j >= size2_)
+ return iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == index2_data_.begin () + zero_based (*itv))
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*(it - 1));
+ } else {
+ if (j == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+
+
+ class const_iterator1:
+ public container_const_reference<compressed_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename compressed_matrix::value_type value_type;
+ typedef typename compressed_matrix::difference_type difference_type;
+ typedef typename compressed_matrix::const_reference reference;
+ typedef const typename compressed_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ i_ = index1 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ --i_;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+ class iterator1:
+ public container_reference<compressed_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename compressed_matrix::value_type value_type;
+ typedef typename compressed_matrix::difference_type difference_type;
+ typedef typename compressed_matrix::true_reference reference;
+ typedef typename compressed_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ i_ = index1 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ --i_;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+ class const_iterator2:
+ public container_const_reference<compressed_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename compressed_matrix::value_type value_type;
+ typedef typename compressed_matrix::difference_type difference_type;
+ typedef typename compressed_matrix::const_reference reference;
+ typedef const typename compressed_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ j_ = index2 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ --j_;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ class iterator2:
+ public container_reference<compressed_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename compressed_matrix::value_type value_type;
+ typedef typename compressed_matrix::difference_type difference_type;
+ typedef typename compressed_matrix::true_reference reference;
+ typedef typename compressed_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ j_ = index2 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ --j_;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+ ar & serialization::make_nvp("size1",s1);
+ ar & serialization::make_nvp("size2",s2);
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("capacity", capacity_);
+ ar & serialization::make_nvp("filled1", filled1_);
+ ar & serialization::make_nvp("filled2", filled2_);
+ ar & serialization::make_nvp("index1_data", index1_data_);
+ ar & serialization::make_nvp("index2_data", index2_data_);
+ ar & serialization::make_nvp("value_data", value_data_);
+ storage_invariants();
+ }
+
+ private:
+ void storage_invariants () const {
+ BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == index1_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (filled1_ > 0 && filled1_ <= layout_type::size_M (size1_, size2_) + 1, internal_logic ());
+ BOOST_UBLAS_CHECK (filled2_ <= capacity_, internal_logic ());
+ BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ());
+ }
+
+ size_type size1_;
+ size_type size2_;
+ array_size_type capacity_;
+ array_size_type filled1_;
+ array_size_type filled2_;
+ index_array_type index1_data_;
+ index_array_type index2_data_;
+ value_array_type value_data_;
+ static const value_type zero_;
+
+ BOOST_UBLAS_INLINE
+ static size_type zero_based (size_type k_based_index) {
+ return k_based_index - IB;
+ }
+ BOOST_UBLAS_INLINE
+ static size_type k_based (size_type zero_based_index) {
+ return zero_based_index + IB;
+ }
+
+ friend class iterator1;
+ friend class iterator2;
+ friend class const_iterator1;
+ friend class const_iterator2;
+ };
+
+ template<class T, class L, std::size_t IB, class IA, class TA>
+ const typename compressed_matrix<T, L, IB, IA, TA>::value_type compressed_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
+
+
+ // Coordinate array based sparse matrix class
+ // Thanks to Kresimir Fresl for extending this to cover different index bases.
+ template<class T, class L, std::size_t IB, class IA, class TA>
+ class coordinate_matrix:
+ public matrix_container<coordinate_matrix<T, L, IB, IA, TA> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef L layout_type;
+ typedef coordinate_matrix<T, L, IB, IA, TA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ // ISSUE require type consistency check, is_convertable (IA::size_type, TA::size_type)
+ typedef typename IA::value_type size_type;
+ // ISSUE difference_type cannot be deduced for sparse indices, we only know the value_type
+ typedef std::ptrdiff_t difference_type;
+ // size_type for the data arrays.
+ typedef typename IA::size_type array_size_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ typedef T &reference;
+#else
+ typedef sparse_matrix_element<self_type> reference;
+#endif
+ typedef IA index_array_type;
+ typedef TA value_array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef coordinate_vector<T, IB, IA, TA> vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ coordinate_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ coordinate_matrix (size_type size1, size_type size2, array_size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ coordinate_matrix (const coordinate_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
+ filled_ (m.filled_), sorted_filled_ (m.sorted_filled_), sorted_ (m.sorted_),
+ index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
+ storage_invariants ();
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix (const matrix_expression<AE> &ae, array_size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return capacity_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return filled_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ static size_type index_base () {
+ return IB;
+ }
+ BOOST_UBLAS_INLINE
+ array_size_type filled () const {
+ return filled_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index1_data () const {
+ return index1_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index2_data () const {
+ return index2_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const value_array_type &value_data () const {
+ return value_data_;
+ }
+ BOOST_UBLAS_INLINE
+ void set_filled (const array_size_type &filled) {
+ // Make sure that storage_invariants() succeeds
+ if (sorted_ && filled < filled_)
+ sorted_filled_ = filled;
+ else
+ sorted_ = (sorted_filled_ == filled);
+ filled_ = filled;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index1_data () {
+ return index1_data_;
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index2_data () {
+ return index2_data_;
+ }
+ BOOST_UBLAS_INLINE
+ value_array_type &value_data () {
+ return value_data_;
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ array_size_type restrict_capacity (array_size_type non_zeros) const {
+ // minimum non_zeros
+ non_zeros = (std::max) (non_zeros, array_size_type((std::min) (size1_, size2_)));
+ // ISSUE no maximum as coordinate may contain inserted duplicates
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ // FIXME preserve unimplemented
+ BOOST_UBLAS_CHECK (!preserve, internal_logic ());
+ size1_ = size1;
+ size2_ = size2;
+ capacity_ = restrict_capacity (capacity_);
+ index1_data_.resize (capacity_);
+ index2_data_.resize (capacity_);
+ value_data_.resize (capacity_);
+ filled_ = 0;
+ sorted_filled_ = filled_;
+ sorted_ = true;
+ storage_invariants ();
+ }
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (array_size_type non_zeros, bool preserve = true) {
+ sort (); // remove duplicate elements
+ capacity_ = restrict_capacity (non_zeros);
+ if (preserve) {
+ index1_data_.resize (capacity_, size_type ());
+ index2_data_.resize (capacity_, size_type ());
+ value_data_.resize (capacity_, value_type ());
+ filled_ = (std::min) (capacity_, filled_);
+ }
+ else {
+ index1_data_.resize (capacity_);
+ index2_data_.resize (capacity_);
+ value_data_.resize (capacity_);
+ filled_ = 0;
+ }
+ sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i, size_type j) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i, size_type j) const {
+ sort ();
+ size_type element1 (layout_type::index_M (i, j));
+ size_type element2 (layout_type::index_m (i, j));
+ vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
+ vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
+ if (itv_begin == itv_end)
+ return 0;
+ const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
+ if (it == it_end || *it != k_based (element2))
+ return 0;
+ return &value_data_ [it - index2_data_.begin ()];
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ const_pointer p = find_element (i, j);
+ if (p)
+ return *p;
+ else
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ pointer p = find_element (i, j);
+ if (p)
+ return *p;
+ else
+ return insert_element (i, j, value_type/*zero*/());
+#else
+ return reference (*this, i, j);
+#endif
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ void append_element (size_type i, size_type j, const_reference t) {
+ if (filled_ >= capacity_)
+ reserve (2 * filled_, true);
+ BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ index1_data_ [filled_] = k_based (element1);
+ index2_data_ [filled_] = k_based (element2);
+ value_data_ [filled_] = t;
+ ++ filled_;
+ sorted_ = false;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
+ append_element (i, j, t);
+ return value_data_ [filled_ - 1];
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ sort ();
+ vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
+ vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
+ subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
+ if (it != it_end && *it == k_based (element2)) {
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
+ vector_subiterator_type itv (index1_data_.begin () + n);
+ std::copy (itv + 1, index1_data_.begin () + filled_, itv);
+ std::copy (it + 1, index2_data_.begin () + filled_, it);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy (itt + 1, value_data_.begin () + filled_, itt);
+ -- filled_;
+ sorted_filled_ = filled_;
+ }
+ storage_invariants ();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ filled_ = 0;
+ sorted_filled_ = filled_;
+ sorted_ = true;
+ storage_invariants ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &operator = (const coordinate_matrix &m) {
+ if (this != &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ capacity_ = m.capacity_;
+ filled_ = m.filled_;
+ sorted_filled_ = m.sorted_filled_;
+ sorted_ = m.sorted_;
+ index1_data_ = m.index1_data_;
+ index2_data_ = m.index2_data_;
+ value_data_ = m.value_data_;
+ BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
+ }
+ storage_invariants ();
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &operator = (const matrix_container<C> &m) {
+ resize (m ().size1 (), m ().size2 (), false);
+ assign (m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &assign_temporary (coordinate_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &operator += (const matrix_container<C> &m) {
+ plus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &operator -= (const matrix_container<C> &m) {
+ minus_assign (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ coordinate_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (coordinate_matrix &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ std::swap (capacity_, m.capacity_);
+ std::swap (filled_, m.filled_);
+ std::swap (sorted_filled_, m.sorted_filled_);
+ std::swap (sorted_, m.sorted_);
+ index1_data_.swap (m.index1_data_);
+ index2_data_.swap (m.index2_data_);
+ value_data_.swap (m.value_data_);
+ }
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Sorting and summation of duplicates
+ BOOST_UBLAS_INLINE
+ void sort () const {
+ if (! sorted_ && filled_ > 0) {
+ typedef index_triple_array<index_array_type, index_array_type, value_array_type> array_triple;
+ array_triple ita (filled_, index1_data_, index2_data_, value_data_);
+ const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_;
+ // sort new elements and merge
+ std::sort (iunsorted, ita.end ());
+ std::inplace_merge (ita.begin (), iunsorted, ita.end ());
+
+ // sum duplicates with += and remove
+ array_size_type filled = 0;
+ for (array_size_type i = 1; i < filled_; ++ i) {
+ if (index1_data_ [filled] != index1_data_ [i] ||
+ index2_data_ [filled] != index2_data_ [i]) {
+ ++ filled;
+ if (filled != i) {
+ index1_data_ [filled] = index1_data_ [i];
+ index2_data_ [filled] = index2_data_ [i];
+ value_data_ [filled] = value_data_ [i];
+ }
+ } else {
+ value_data_ [filled] += value_data_ [i];
+ }
+ }
+ filled_ = filled + 1;
+ sorted_filled_ = filled_;
+ sorted_ = true;
+ storage_invariants ();
+ }
+ }
+
+ // Back element insertion and erasure
+ BOOST_UBLAS_INLINE
+ void push_back (size_type i, size_type j, const_reference t) {
+ size_type element1 = layout_type::index_M (i, j);
+ size_type element2 = layout_type::index_m (i, j);
+ // must maintain sort order
+ BOOST_UBLAS_CHECK (sorted_ &&
+ (filled_ == 0 ||
+ index1_data_ [filled_ - 1] < k_based (element1) ||
+ (index1_data_ [filled_ - 1] == k_based (element1) && index2_data_ [filled_ - 1] < k_based (element2)))
+ , external_logic ());
+ if (filled_ >= capacity_)
+ reserve (2 * filled_, true);
+ BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
+ index1_data_ [filled_] = k_based (element1);
+ index2_data_ [filled_] = k_based (element2);
+ value_data_ [filled_] = t;
+ ++ filled_;
+ sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ void pop_back () {
+ // ISSUE invariants could be simpilfied if sorted required as precondition
+ BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
+ -- filled_;
+ sorted_filled_ = (std::min) (sorted_filled_, filled_);
+ sorted_ = sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+
+ // Iterator types
+ private:
+ // Use index array iterator
+ typedef typename IA::const_iterator vector_const_subiterator_type;
+ typedef typename IA::iterator vector_subiterator_type;
+ typedef typename IA::const_iterator const_subiterator_type;
+ typedef typename IA::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ pointer p = find_element (i, j);
+ BOOST_UBLAS_CHECK (p, bad_index ());
+ return *p;
+ }
+
+ public:
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
+ sort ();
+ for (;;) {
+ size_type address1 (layout_type::index_M (i, j));
+ size_type address2 (layout_type::index_m (i, j));
+ vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+ vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+
+ const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
+ if (rank == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*it);
+ } else {
+ if (i >= size1_)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*(it - 1));
+ } else {
+ if (i == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
+ sort ();
+ for (;;) {
+ size_type address1 (layout_type::index_M (i, j));
+ size_type address2 (layout_type::index_m (i, j));
+ vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+ vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+
+ subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
+ if (rank == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*it);
+ } else {
+ if (i >= size1_)
+ return iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = zero_based (*(it - 1));
+ } else {
+ if (i == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
+ sort ();
+ for (;;) {
+ size_type address1 (layout_type::index_M (i, j));
+ size_type address2 (layout_type::index_m (i, j));
+ vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+ vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+
+ const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+
+ const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
+ if (rank == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*it);
+ } else {
+ if (j >= size2_)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*(it - 1));
+ } else {
+ if (j == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
+ sort ();
+ for (;;) {
+ size_type address1 (layout_type::index_M (i, j));
+ size_type address2 (layout_type::index_m (i, j));
+ vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+ vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
+
+ subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
+ subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
+
+ subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
+ vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
+ if (rank == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && zero_based (*it) == address2)
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*it);
+ } else {
+ if (j >= size2_)
+ return iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = zero_based (*(it - 1));
+ } else {
+ if (j == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+
+
+ class const_iterator1:
+ public container_const_reference<coordinate_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename coordinate_matrix::value_type value_type;
+ typedef typename coordinate_matrix::difference_type difference_type;
+ typedef typename coordinate_matrix::const_reference reference;
+ typedef const typename coordinate_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ i_ = index1 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ i_ = index1 () - 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+ class iterator1:
+ public container_reference<coordinate_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename coordinate_matrix::value_type value_type;
+ typedef typename coordinate_matrix::difference_type difference_type;
+ typedef typename coordinate_matrix::true_reference reference;
+ typedef typename coordinate_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ i_ = index1 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ i_ = index1 () - 1;
+ if (rank_ == 1)
+ *this = (*this) ().find1 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+ class const_iterator2:
+ public container_const_reference<coordinate_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename coordinate_matrix::value_type value_type;
+ typedef typename coordinate_matrix::difference_type difference_type;
+ typedef typename coordinate_matrix::const_reference reference;
+ typedef const typename coordinate_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ j_ = index2 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ j_ = index2 () - 1;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_const_subiterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ class iterator2:
+ public container_reference<coordinate_matrix>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename coordinate_matrix::value_type value_type;
+ typedef typename coordinate_matrix::difference_type difference_type;
+ typedef typename coordinate_matrix::true_reference reference;
+ typedef typename coordinate_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ j_ = index2 () + 1;
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, 1);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ j_ = index2 ();
+ if (rank_ == 1)
+ *this = (*this) ().find2 (rank_, i_, j_, -1);
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vector_subiterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+ ar & serialization::make_nvp("size1",s1);
+ ar & serialization::make_nvp("size2",s2);
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+ ar & serialization::make_nvp("capacity", capacity_);
+ ar & serialization::make_nvp("filled", filled_);
+ ar & serialization::make_nvp("sorted_filled", sorted_filled_);
+ ar & serialization::make_nvp("sorted", sorted_);
+ ar & serialization::make_nvp("index1_data", index1_data_);
+ ar & serialization::make_nvp("index2_data", index2_data_);
+ ar & serialization::make_nvp("value_data", value_data_);
+ storage_invariants();
+ }
+
+ private:
+ void storage_invariants () const
+ {
+ BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
+ BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
+ BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
+ }
+
+ size_type size1_;
+ size_type size2_;
+ array_size_type capacity_;
+ mutable array_size_type filled_;
+ mutable array_size_type sorted_filled_;
+ mutable bool sorted_;
+ mutable index_array_type index1_data_;
+ mutable index_array_type index2_data_;
+ mutable value_array_type value_data_;
+ static const value_type zero_;
+
+ BOOST_UBLAS_INLINE
+ static size_type zero_based (size_type k_based_index) {
+ return k_based_index - IB;
+ }
+ BOOST_UBLAS_INLINE
+ static size_type k_based (size_type zero_based_index) {
+ return zero_based_index + IB;
+ }
+
+ friend class iterator1;
+ friend class iterator2;
+ friend class const_iterator1;
+ friend class const_iterator2;
+ };
+
+ template<class T, class L, std::size_t IB, class IA, class TA>
+ const typename coordinate_matrix<T, L, IB, IA, TA>::value_type coordinate_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_OPERATION_
+#define _BOOST_UBLAS_OPERATION_
+
+#include <boost/numeric/ublas/matrix_proxy.hpp>
+
+/** \file operation.hpp
+ * \brief This file contains some specialized products.
+ */
+
+// axpy-based products
+// Alexei Novakov had a lot of ideas to improve these. Thanks.
+// Hendrik Kueck proposed some new kernel. Thanks again.
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class V, class T1, class L1, class IA1, class TA1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const compressed_matrix<T1, L1, 0, IA1, TA1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, row_major_tag) {
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+
+ for (size_type i = 0; i < e1.filled1 () -1; ++ i) {
+ size_type begin = e1.index1_data () [i];
+ size_type end = e1.index1_data () [i + 1];
+ value_type t (v (i));
+ for (size_type j = begin; j < end; ++ j)
+ t += e1.value_data () [j] * e2 () (e1.index2_data () [j]);
+ v (i) = t;
+ }
+ return v;
+ }
+
+ template<class V, class T1, class L1, class IA1, class TA1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const compressed_matrix<T1, L1, 0, IA1, TA1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, column_major_tag) {
+ typedef typename V::size_type size_type;
+
+ for (size_type j = 0; j < e1.filled1 () -1; ++ j) {
+ size_type begin = e1.index1_data () [j];
+ size_type end = e1.index1_data () [j + 1];
+ for (size_type i = begin; i < end; ++ i)
+ v (e1.index2_data () [i]) += e1.value_data () [i] * e2 () (j);
+ }
+ return v;
+ }
+
+ // Dispatcher
+ template<class V, class T1, class L1, class IA1, class TA1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const compressed_matrix<T1, L1, 0, IA1, TA1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, bool init = true) {
+ typedef typename V::value_type value_type;
+ typedef typename L1::orientation_category orientation_category;
+
+ if (init)
+ v.assign (zero_vector<value_type> (e1.size1 ()));
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_plus_assign> (cv, prod (e1, e2));
+#endif
+ axpy_prod (e1, e2, v, orientation_category ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+ template<class V, class T1, class L1, class IA1, class TA1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ axpy_prod (const compressed_matrix<T1, L1, 0, IA1, TA1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef V vector_type;
+
+ vector_type v (e1.size1 ());
+ return axpy_prod (e1, e2, v, true);
+ }
+
+ template<class V, class T1, class L1, class IA1, class TA1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const coordinate_matrix<T1, L1, 0, IA1, TA1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, bool init = true) {
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ typedef L1 layout_type;
+
+ size_type size1 = e1.size1();
+ size_type size2 = e1.size2();
+
+ if (init) {
+ noalias(v) = zero_vector<value_type>(size1);
+ }
+
+ for (size_type i = 0; i < e1.nnz(); ++i) {
+ size_type row_index = layout_type::index_M( e1.index1_data () [i], e1.index2_data () [i] );
+ size_type col_index = layout_type::index_m( e1.index1_data () [i], e1.index2_data () [i] );
+ v( row_index ) += e1.value_data () [i] * e2 () (col_index);
+ }
+ return v;
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag, row_major_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression1_type::const_iterator1 it1 (e1 ().begin1 ());
+ typename expression1_type::const_iterator1 it1_end (e1 ().end1 ());
+ while (it1 != it1_end) {
+ size_type index1 (it1.index1 ());
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression1_type::const_iterator2 it2 (it1.begin ());
+ typename expression1_type::const_iterator2 it2_end (it1.end ());
+#else
+ typename expression1_type::const_iterator2 it2 (boost::numeric::ublas::begin (it1, iterator1_tag ()));
+ typename expression1_type::const_iterator2 it2_end (boost::numeric::ublas::end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) {
+ v (index1) += *it2 * e2 () (it2.index2 ());
+ ++ it2;
+ }
+ ++ it1;
+ }
+ return v;
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag, column_major_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression1_type::const_iterator2 it2 (e1 ().begin2 ());
+ typename expression1_type::const_iterator2 it2_end (e1 ().end2 ());
+ while (it2 != it2_end) {
+ size_type index2 (it2.index2 ());
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression1_type::const_iterator1 it1 (it2.begin ());
+ typename expression1_type::const_iterator1 it1_end (it2.end ());
+#else
+ typename expression1_type::const_iterator1 it1 (boost::numeric::ublas::begin (it2, iterator2_tag ()));
+ typename expression1_type::const_iterator1 it1_end (boost::numeric::ublas::end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) {
+ v (it1.index1 ()) += *it1 * e2 () (index2);
+ ++ it1;
+ }
+ ++ it2;
+ }
+ return v;
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, sparse_bidirectional_iterator_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression2_type::const_iterator it (e2 ().begin ());
+ typename expression2_type::const_iterator it_end (e2 ().end ());
+ while (it != it_end) {
+ v.plus_assign (column (e1 (), it.index ()) * *it);
+ ++ it;
+ }
+ return v;
+ }
+
+ // Dispatcher
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag) {
+ typedef typename E1::orientation_category orientation_category;
+ return axpy_prod (e1, e2, v, packed_random_access_iterator_tag (), orientation_category ());
+ }
+
+
+ /** \brief computes <tt>v += A x</tt> or <tt>v = A x</tt> in an
+ optimized fashion.
+
+ \param e1 the matrix expression \c A
+ \param e2 the vector expression \c x
+ \param v the result vector \c v
+ \param init a boolean parameter
+
+ <tt>axpy_prod(A, x, v, init)</tt> implements the well known
+ axpy-product. Setting \a init to \c true is equivalent to call
+ <tt>v.clear()</tt> before <tt>axpy_prod</tt>. Currently \a init
+ defaults to \c true, but this may change in the future.
+
+ Up to now there are some specialisation for compressed
+ matrices that give a large speed up compared to prod.
+
+ \ingroup blas2
+
+ \internal
+
+ template parameters:
+ \param V type of the result vector \c v
+ \param E1 type of a matrix expression \c A
+ \param E2 type of a vector expression \c x
+ */
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ V &v, bool init = true) {
+ typedef typename V::value_type value_type;
+ typedef typename E2::const_iterator::iterator_category iterator_category;
+
+ if (init)
+ v.assign (zero_vector<value_type> (e1 ().size1 ()));
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_plus_assign> (cv, prod (e1, e2));
+#endif
+ axpy_prod (e1, e2, v, iterator_category ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ axpy_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef V vector_type;
+
+ vector_type v (e1 ().size1 ());
+ return axpy_prod (e1, e2, v, true);
+ }
+
+ template<class V, class E1, class T2, class IA2, class TA2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const compressed_matrix<T2, column_major, 0, IA2, TA2> &e2,
+ V &v, column_major_tag) {
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+
+ for (size_type j = 0; j < e2.filled1 () -1; ++ j) {
+ size_type begin = e2.index1_data () [j];
+ size_type end = e2.index1_data () [j + 1];
+ value_type t (v (j));
+ for (size_type i = begin; i < end; ++ i)
+ t += e2.value_data () [i] * e1 () (e2.index2_data () [i]);
+ v (j) = t;
+ }
+ return v;
+ }
+
+ template<class V, class E1, class T2, class IA2, class TA2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const compressed_matrix<T2, row_major, 0, IA2, TA2> &e2,
+ V &v, row_major_tag) {
+ typedef typename V::size_type size_type;
+
+ for (size_type i = 0; i < e2.filled1 () -1; ++ i) {
+ size_type begin = e2.index1_data () [i];
+ size_type end = e2.index1_data () [i + 1];
+ for (size_type j = begin; j < end; ++ j)
+ v (e2.index2_data () [j]) += e2.value_data () [j] * e1 () (i);
+ }
+ return v;
+ }
+
+ // Dispatcher
+ template<class V, class E1, class T2, class L2, class IA2, class TA2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const compressed_matrix<T2, L2, 0, IA2, TA2> &e2,
+ V &v, bool init = true) {
+ typedef typename V::value_type value_type;
+ typedef typename L2::orientation_category orientation_category;
+
+ if (init)
+ v.assign (zero_vector<value_type> (e2.size2 ()));
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_plus_assign> (cv, prod (e1, e2));
+#endif
+ axpy_prod (e1, e2, v, orientation_category ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+ template<class V, class E1, class T2, class L2, class IA2, class TA2>
+ BOOST_UBLAS_INLINE
+ V
+ axpy_prod (const vector_expression<E1> &e1,
+ const compressed_matrix<T2, L2, 0, IA2, TA2> &e2) {
+ typedef V vector_type;
+
+ vector_type v (e2.size2 ());
+ return axpy_prod (e1, e2, v, true);
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag, column_major_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression2_type::const_iterator2 it2 (e2 ().begin2 ());
+ typename expression2_type::const_iterator2 it2_end (e2 ().end2 ());
+ while (it2 != it2_end) {
+ size_type index2 (it2.index2 ());
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression2_type::const_iterator1 it1 (it2.begin ());
+ typename expression2_type::const_iterator1 it1_end (it2.end ());
+#else
+ typename expression2_type::const_iterator1 it1 (boost::numeric::ublas::begin (it2, iterator2_tag ()));
+ typename expression2_type::const_iterator1 it1_end (boost::numeric::ublas::end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) {
+ v (index2) += *it1 * e1 () (it1.index1 ());
+ ++ it1;
+ }
+ ++ it2;
+ }
+ return v;
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag, row_major_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression2_type::const_iterator1 it1 (e2 ().begin1 ());
+ typename expression2_type::const_iterator1 it1_end (e2 ().end1 ());
+ while (it1 != it1_end) {
+ size_type index1 (it1.index1 ());
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression2_type::const_iterator2 it2 (it1.begin ());
+ typename expression2_type::const_iterator2 it2_end (it1.end ());
+#else
+ typename expression2_type::const_iterator2 it2 (boost::numeric::ublas::begin (it1, iterator1_tag ()));
+ typename expression2_type::const_iterator2 it2_end (boost::numeric::ublas::end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) {
+ v (it2.index2 ()) += *it2 * e1 () (index1);
+ ++ it2;
+ }
+ ++ it1;
+ }
+ return v;
+ }
+
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v, sparse_bidirectional_iterator_tag) {
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+
+ typename expression1_type::const_iterator it (e1 ().begin ());
+ typename expression1_type::const_iterator it_end (e1 ().end ());
+ while (it != it_end) {
+ v.plus_assign (*it * row (e2 (), it.index ()));
+ ++ it;
+ }
+ return v;
+ }
+
+ // Dispatcher
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v, packed_random_access_iterator_tag) {
+ typedef typename E2::orientation_category orientation_category;
+ return axpy_prod (e1, e2, v, packed_random_access_iterator_tag (), orientation_category ());
+ }
+
+
+ /** \brief computes <tt>v += A<sup>T</sup> x</tt> or <tt>v = A<sup>T</sup> x</tt> in an
+ optimized fashion.
+
+ \param e1 the vector expression \c x
+ \param e2 the matrix expression \c A
+ \param v the result vector \c v
+ \param init a boolean parameter
+
+ <tt>axpy_prod(x, A, v, init)</tt> implements the well known
+ axpy-product. Setting \a init to \c true is equivalent to call
+ <tt>v.clear()</tt> before <tt>axpy_prod</tt>. Currently \a init
+ defaults to \c true, but this may change in the future.
+
+ Up to now there are some specialisation for compressed
+ matrices that give a large speed up compared to prod.
+
+ \ingroup blas2
+
+ \internal
+
+ template parameters:
+ \param V type of the result vector \c v
+ \param E1 type of a vector expression \c x
+ \param E2 type of a matrix expression \c A
+ */
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V &
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ V &v, bool init = true) {
+ typedef typename V::value_type value_type;
+ typedef typename E1::const_iterator::iterator_category iterator_category;
+
+ if (init)
+ v.assign (zero_vector<value_type> (e2 ().size2 ()));
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_plus_assign> (cv, prod (e1, e2));
+#endif
+ axpy_prod (e1, e2, v, iterator_category ());
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+ template<class V, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ axpy_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef V vector_type;
+
+ vector_type v (e2 ().size2 ());
+ return axpy_prod (e1, e2, v, true);
+ }
+
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ dense_proxy_tag, row_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), row_major_tag ());
+#endif
+ size_type size1 (e1 ().size1 ());
+ size_type size2 (e1 ().size2 ());
+ for (size_type i = 0; i < size1; ++ i)
+ for (size_type j = 0; j < size2; ++ j)
+ row (m, i).plus_assign (e1 () (i, j) * row (e2 (), j));
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ sparse_proxy_tag, row_major_tag) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), row_major_tag ());
+#endif
+ typename expression1_type::const_iterator1 it1 (e1 ().begin1 ());
+ typename expression1_type::const_iterator1 it1_end (e1 ().end1 ());
+ while (it1 != it1_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression1_type::const_iterator2 it2 (it1.begin ());
+ typename expression1_type::const_iterator2 it2_end (it1.end ());
+#else
+ typename expression1_type::const_iterator2 it2 (boost::numeric::ublas::begin (it1, iterator1_tag ()));
+ typename expression1_type::const_iterator2 it2_end (boost::numeric::ublas::end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) {
+ // row (m, it1.index1 ()).plus_assign (*it2 * row (e2 (), it2.index2 ()));
+ matrix_row<expression2_type> mr (e2 (), it2.index2 ());
+ typename matrix_row<expression2_type>::const_iterator itr (mr.begin ());
+ typename matrix_row<expression2_type>::const_iterator itr_end (mr.end ());
+ while (itr != itr_end) {
+ if (triangular_restriction::other (it1.index1 (), itr.index ()))
+ m (it1.index1 (), itr.index ()) += *it2 * *itr;
+ ++ itr;
+ }
+ ++ it2;
+ }
+ ++ it1;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ dense_proxy_tag, column_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), column_major_tag ());
+#endif
+ size_type size1 (e2 ().size1 ());
+ size_type size2 (e2 ().size2 ());
+ for (size_type j = 0; j < size2; ++ j)
+ for (size_type i = 0; i < size1; ++ i)
+ column (m, j).plus_assign (e2 () (i, j) * column (e1 (), i));
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ sparse_proxy_tag, column_major_tag) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), column_major_tag ());
+#endif
+ typename expression2_type::const_iterator2 it2 (e2 ().begin2 ());
+ typename expression2_type::const_iterator2 it2_end (e2 ().end2 ());
+ while (it2 != it2_end) {
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression2_type::const_iterator1 it1 (it2.begin ());
+ typename expression2_type::const_iterator1 it1_end (it2.end ());
+#else
+ typename expression2_type::const_iterator1 it1 (boost::numeric::ublas::begin (it2, iterator2_tag ()));
+ typename expression2_type::const_iterator1 it1_end (boost::numeric::ublas::end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) {
+ // column (m, it2.index2 ()).plus_assign (*it1 * column (e1 (), it1.index1 ()));
+ matrix_column<expression1_type> mc (e1 (), it1.index1 ());
+ typename matrix_column<expression1_type>::const_iterator itc (mc.begin ());
+ typename matrix_column<expression1_type>::const_iterator itc_end (mc.end ());
+ while (itc != itc_end) {
+ if(triangular_restriction::other (itc.index (), it2.index2 ()))
+ m (itc.index (), it2.index2 ()) += *it1 * *itc;
+ ++ itc;
+ }
+ ++ it1;
+ }
+ ++ it2;
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ // Dispatcher
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI, bool init = true) {
+ typedef typename M::value_type value_type;
+ typedef typename M::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+ typedef TRI triangular_restriction;
+
+ if (init)
+ m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
+ return axpy_prod (e1, e2, m, triangular_restriction (), storage_category (), orientation_category ());
+ }
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ TRI) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+
+ matrix_type m (e1 ().size1 (), e2 ().size2 ());
+ return axpy_prod (e1, e2, m, triangular_restriction (), true);
+ }
+
+ /** \brief computes <tt>M += A X</tt> or <tt>M = A X</tt> in an
+ optimized fashion.
+
+ \param e1 the matrix expression \c A
+ \param e2 the matrix expression \c X
+ \param m the result matrix \c M
+ \param init a boolean parameter
+
+ <tt>axpy_prod(A, X, M, init)</tt> implements the well known
+ axpy-product. Setting \a init to \c true is equivalent to call
+ <tt>M.clear()</tt> before <tt>axpy_prod</tt>. Currently \a init
+ defaults to \c true, but this may change in the future.
+
+ Up to now there are no specialisations.
+
+ \ingroup blas3
+
+ \internal
+
+ template parameters:
+ \param M type of the result matrix \c M
+ \param E1 type of a matrix expression \c A
+ \param E2 type of a matrix expression \c X
+ */
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, bool init = true) {
+ typedef typename M::value_type value_type;
+ typedef typename M::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ if (init)
+ m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
+ return axpy_prod (e1, e2, m, full (), storage_category (), orientation_category ());
+ }
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ axpy_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef M matrix_type;
+
+ matrix_type m (e1 ().size1 (), e2 ().size2 ());
+ return axpy_prod (e1, e2, m, full (), true);
+ }
+
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ opb_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m,
+ dense_proxy_tag, row_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), row_major_tag ());
+#endif
+ size_type size (BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ()));
+ for (size_type k = 0; k < size; ++ k) {
+ vector<value_type> ce1 (column (e1 (), k));
+ vector<value_type> re2 (row (e2 (), k));
+ m.plus_assign (outer_prod (ce1, re2));
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ opb_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m,
+ dense_proxy_tag, column_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m);
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_plus_assign> (cm, prod (e1, e2), column_major_tag ());
+#endif
+ size_type size (BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ()));
+ for (size_type k = 0; k < size; ++ k) {
+ vector<value_type> ce1 (column (e1 (), k));
+ vector<value_type> re2 (row (e2 (), k));
+ m.plus_assign (outer_prod (ce1, re2));
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ // Dispatcher
+
+ /** \brief computes <tt>M += A X</tt> or <tt>M = A X</tt> in an
+ optimized fashion.
+
+ \param e1 the matrix expression \c A
+ \param e2 the matrix expression \c X
+ \param m the result matrix \c M
+ \param init a boolean parameter
+
+ <tt>opb_prod(A, X, M, init)</tt> implements the well known
+ axpy-product. Setting \a init to \c true is equivalent to call
+ <tt>M.clear()</tt> before <tt>opb_prod</tt>. Currently \a init
+ defaults to \c true, but this may change in the future.
+
+ This function may give a speedup if \c A has less columns than
+ rows, because the product is computed as a sum of outer
+ products.
+
+ \ingroup blas3
+
+ \internal
+
+ template parameters:
+ \param M type of the result matrix \c M
+ \param E1 type of a matrix expression \c A
+ \param E2 type of a matrix expression \c X
+ */
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ opb_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, bool init = true) {
+ typedef typename M::value_type value_type;
+ typedef typename M::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ if (init)
+ m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
+ return opb_prod (e1, e2, m, storage_category (), orientation_category ());
+ }
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ opb_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef M matrix_type;
+
+ matrix_type m (e1 ().size1 (), e2 ().size2 ());
+ return opb_prod (e1, e2, m, true);
+ }
+
+}}}
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file begin.hpp
+ *
+ * \brief The \c begin operation.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_BEGIN_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_BEGIN_HPP
+
+
+#include <boost/numeric/ublas/expression_types.hpp>
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/traits/const_iterator_type.hpp>
+#include <boost/numeric/ublas/traits/iterator_type.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+ /**
+ * \brief Auxiliary class for implementing the \c begin operation.
+ * \tparam CategoryT The expression category type (e.g., vector_tag).
+ * \tparam TagT The dimension type tag (e.g., tag::major).
+ * \tparam OrientationT The orientation category type (e.g., row_major_tag).
+ */
+ template <typename CategoryT, typename TagT=void, typename OrientationT=void>
+ struct begin_impl;
+
+
+ /// \brief Specialization of \c begin_impl for iterating vector expressions.
+ template <>
+ struct begin_impl<vector_tag,void,void>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator over the given vector expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator apply(ExprT& e)
+ {
+ return e.begin();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the first element of the given vector
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator apply(ExprT const& e)
+ {
+ return e.begin();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a row-major orientation over the major dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::major,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given row-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.begin1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * row-major matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.begin1();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a column-major orientation over the major dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::major,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given column-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.begin2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * column-major matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.begin2();
+ }
+ };
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a row-major orientation over the minor dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::minor,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given row-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.begin2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * row-major matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.begin2();
+ }
+ };
+
+
+
+ /// \brief Specialization of \c begin_impl for iterating matrix expressions with
+ /// a column-major orientation over the minor dimension.
+ template <>
+ struct begin_impl<matrix_tag,tag::minor,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the first element of the given column-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.begin1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the first element of the given
+ * column-major matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.begin1();
+ }
+ };
+
+ } // Namespace detail
+
+
+ /**
+ * \brief An iterator to the first element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator to the first element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::iterator begin(vector_expression<ExprT>& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the first element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the first element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::const_iterator begin(vector_expression<ExprT> const& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the first element of the given matrix expression
+ * according to its orientation.
+ * \tparam DimTagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator to the first element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT>& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the first element of the given matrix expression
+ * according to its orientation.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator to the first element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename const_iterator_type<ExprT,TagT>::type begin(matrix_expression<ExprT> const& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the first element over the dual dimension of the given
+ * iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return An iterator to the first element over the dual dimension of the given
+ * iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type begin(IteratorT& it)
+ {
+ return it.begin();
+ }
+
+
+ /**
+ * \brief A const iterator to the first element over the dual dimension of the
+ * given iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return A const iterator to the first element over the dual dimension of the
+ * given iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type begin(IteratorT const& it)
+ {
+ return it.begin();
+ }
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_OPERATION_BEGIN_HPP
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file c_array.hpp
+ *
+ * \brief provides specializations of matrix and vector operations for c arrays and c matrices.
+ *
+ * Copyright (c) 2009, Gunter Winkler
+ *
+ * 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)
+ *
+ * \author Gunter Winkler (guwi17 at gmx dot de)
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_C_ARRAY_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_C_ARRAY_HPP
+
+#include <boost/numeric/ublas/traits/c_array.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+
+
+ } // namespace boost::numeric::ublas::detail
+
+
+ template <typename T>
+ BOOST_UBLAS_INLINE
+ typename ExprT::const_iterator begin(vector_expression<ExprT> const& e)
+ {
+ return detail::begin_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+}}} // Namespace boost::numeric::ublas
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file end.hpp
+ *
+ * \brief The \c end operation.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_END_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_END_HPP
+
+
+#include <boost/numeric/ublas/expression_types.hpp>
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/traits/const_iterator_type.hpp>
+#include <boost/numeric/ublas/traits/iterator_type.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+ /**
+ * \brief Auxiliary class for implementing the \c end operation.
+ * \tparam CategoryT The expression category type (e.g., vector_tag).
+ * \tparam TagT The dimension type tag (e.g., tag::major).
+ * \tparam OrientationT The orientation category type (e.g., row_major_tag).
+ */
+ template <typename CategoryT, typename TagT=void, typename OrientationT=void>
+ struct end_impl;
+
+
+ /// \brief Specialization of \c end_impl for iterating vector expressions.
+ template <>
+ struct end_impl<vector_tag,void,void>
+ {
+ /**
+ * \brief Return an iterator to the last element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator over the given vector expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator apply(ExprT& e)
+ {
+ return e.end();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the last element of the given vector
+ * expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the first element of the given vector
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator apply(ExprT const& e)
+ {
+ return e.end();
+ }
+ };
+
+
+ /// \brief Specialization of \c end_impl for iterating matrix expressions with a
+ /// row-major orientation over the major dimension.
+ template <>
+ struct end_impl<matrix_tag,tag::major,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the last element of the given row-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.end1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the last element of the given row-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.end1();
+ }
+ };
+
+
+ /// \brief Specialization of \c end_impl for iterating matrix expressions with a
+ /// column-major orientation over the major dimension.
+ template <>
+ struct end_impl<matrix_tag,tag::major,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the last element of the given column-major
+ * matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.end2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the last element of the given
+ * column-major matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the major dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.end2();
+ }
+ };
+
+
+ /// \brief Specialization of \c end_impl for iterating matrix expressions with a
+ /// row-major orientation over the minor dimension.
+ template <>
+ struct end_impl<matrix_tag,tag::minor,row_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the last element of the given row-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator2 apply(ExprT& e)
+ {
+ return e.end2();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the last element of the given
+ * row-minor matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator2 apply(ExprT const& e)
+ {
+ return e.end2();
+ }
+ };
+
+
+ /// \brief Specialization of \c end_impl for iterating matrix expressions with a
+ /// column-major orientation over the minor dimension.
+ template <>
+ struct end_impl<matrix_tag,tag::minor,column_major_tag>
+ {
+ /**
+ * \brief Return an iterator to the last element of the given column-major
+ * matrix expression over the minor dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::iterator1 apply(ExprT& e)
+ {
+ return e.end1();
+ }
+
+
+ /**
+ * \brief Return a const iterator to the last element of the given
+ * column-minor matrix expression over the major dimension.
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator over the minor dimension of the given matrix
+ * expression.
+ */
+ template <typename ExprT>
+ static typename ExprT::const_iterator1 apply(ExprT const& e)
+ {
+ return e.end1();
+ }
+ };
+
+ } // Namespace detail
+
+
+ /**
+ * \brief An iterator to the last element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return An iterator to the last element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::iterator end(vector_expression<ExprT>& e)
+ {
+ return detail::end_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the last element of the given vector expression.
+ * \tparam ExprT A model of VectorExpression type.
+ * \param e A vector expression.
+ * \return A const iterator to the last element of the given vector expression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename ExprT::const_iterator end(vector_expression<ExprT> const& e)
+ {
+ return detail::end_impl<typename ExprT::type_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the last element of the given matrix expression
+ * according to its orientation.
+ * \tparam DimTagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return An iterator to the last element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename iterator_type<ExprT,TagT>::type end(matrix_expression<ExprT>& e)
+ {
+ return detail::end_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief A const iterator to the last element of the given matrix expression
+ * according to its orientation.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ * \tparam ExprT A model of MatrixExpression type.
+ * \param e A matrix expression.
+ * \return A const iterator to the last element of the given matrix expression
+ * according to its orientation.
+ */
+ template <typename TagT, typename ExprT>
+ BOOST_UBLAS_INLINE
+ typename const_iterator_type<ExprT,TagT>::type end(matrix_expression<ExprT> const& e)
+ {
+ return detail::end_impl<typename ExprT::type_category, TagT, typename ExprT::orientation_category>::apply(e());
+ }
+
+
+ /**
+ * \brief An iterator to the last element over the dual dimension of the given
+ * iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return An iterator to the last element over the dual dimension of the given
+ * iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type end(IteratorT& it)
+ {
+ return it.end();
+ }
+
+
+ /**
+ * \brief A const iterator to the last element over the dual dimension of the
+ * given iterator.
+ * \tparam IteratorT A model of Iterator type.
+ * \param it An iterator.
+ * \return A const iterator to the last element over the dual dimension of the
+ * given iterator.
+ */
+ template <typename IteratorT>
+ BOOST_UBLAS_INLINE
+ typename IteratorT::dual_iterator_type end(IteratorT const& it)
+ {
+ return it.end();
+ }
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_OPERATION_END_HPP
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file num_columns.hpp
+ *
+ * \brief The \c num_columns operation.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_NUM_COLUMNS_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_NUM_COLUMNS_HPP
+
+
+#include <boost/numeric/ublas/detail/config.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /**
+ * \brief Return the number of columns.
+ * \tparam MatrixExprT A type which models the matrix expression concept.
+ * \param m A matrix expression.
+ * \return The number of columns.
+ */
+ template <typename MatrixExprT>
+ BOOST_UBLAS_INLINE
+ typename MatrixExprT::size_type num_columns(MatrixExprT const& m)
+ {
+ return m.size2();
+ }
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_OPERATION_NUM_COLUMNS_HPP
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file num_rows.hpp
+ *
+ * \brief The \c num_rows operation.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_NUM_ROWS_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_NUM_ROWS_HPP
+
+
+#include <boost/numeric/ublas/detail/config.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /**
+ * \brief Return the number of rows.
+ * \tparam MatrixExprT A type which models the matrix expression concept.
+ * \param m A matrix expression.
+ * \return The number of rows.
+ */
+ template <typename MatrixExprT>
+ BOOST_UBLAS_INLINE
+ typename MatrixExprT::size_type num_rows(MatrixExprT const& m)
+ {
+ return m.size1();
+ }
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_OPERATION_NUM_ROWS_HPP
--- /dev/null
+/**
+ * \file size.hpp
+ *
+ * \brief The family of \c size operations.
+ *
+ * Copyright (c) 2009-2010, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
+
+
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/ublas/detail/config.hpp>
+#include <boost/numeric/ublas/expression_types.hpp>
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/tags.hpp>
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <cstddef>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+namespace detail { namespace /*<unnamed>*/ {
+
+/// Define a \c has_size_type trait class.
+BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
+
+
+/**
+ * \brief Wrapper type-traits used in \c boost::lazy_enabled_if for getting the
+ * size type (see below).
+ * \tparam VectorT A vector type.
+ */
+template <typename VectorT>
+struct vector_size_type
+{
+ /// The size type.
+ typedef typename vector_traits<VectorT>::size_type type;
+};
+
+/**
+ * \brief Wrapper type-traits used in \c boost::lazy_enabled_if for getting the
+ * size type (see below).
+ * \tparam MatrixT A matrix type.
+ */
+template <typename MatrixT>
+struct matrix_size_type
+{
+ /// The size type.
+ typedef typename matrix_traits<MatrixT>::size_type type;
+};
+
+
+/**
+ * \brief Auxiliary class for computing the size of the given dimension for
+ * a container of the given category.
+ * \tparam Dim The dimension number (starting from 1).
+ * \tparam CategoryT The category type (e.g., vector_tag).
+ */
+template <std::size_t Dim, typename CategoryT>
+struct size_by_dim_impl;
+
+
+/**
+ * \brief Auxiliary class for computing the size of the given dimension for
+ * a container of the given category and with the given orientation.
+ * \tparam Dim The dimension number (starting from 1).
+ * \tparam CategoryT The category type (e.g., vector_tag).
+ * \tparam OrientationT The orientation category type (e.g., row_major_tag).
+ */
+template <typename TagT, typename CategoryT, typename OrientationT>
+struct size_by_tag_impl;
+
+
+/**
+ * \brief Specialization of \c size_by_dim_impl for computing the size of a
+ * vector.
+ */
+template <>
+struct size_by_dim_impl<1, vector_tag>
+{
+ /**
+ * \brief Compute the size of the given vector.
+ * \tparam ExprT A vector expression type.
+ * \pre ExprT must be a model of VectorExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename vector_traits<ExprT>::size_type apply(vector_expression<ExprT> const& ve)
+ {
+ return ve().size();
+ }
+};
+
+
+/**
+ * \brief Specialization of \c size_by_dim_impl for computing the number of
+ * rows of a matrix
+ */
+template <>
+struct size_by_dim_impl<1, matrix_tag>
+{
+ /**
+ * \brief Compute the number of rows of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size1();
+ }
+};
+
+
+/**
+ * \brief Specialization of \c size_by_dim_impl for computing the number of
+ * columns of a matrix
+ */
+template <>
+struct size_by_dim_impl<2, matrix_tag>
+{
+ /**
+ * \brief Compute the number of columns of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size2();
+ }
+};
+
+
+/**
+ * \brief Specialization of \c size_by_tag_impl for computing the size of the
+ * major dimension of a row-major oriented matrix.
+ */
+template <>
+struct size_by_tag_impl<tag::major, matrix_tag, row_major_tag>
+{
+ /**
+ * \brief Compute the number of rows of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size1();
+ }
+};
+
+
+/**
+ * \brief Specialization of \c size_by_tag_impl for computing the size of the
+ * minor dimension of a row-major oriented matrix.
+ */
+template <>
+struct size_by_tag_impl<tag::minor, matrix_tag, row_major_tag>
+{
+ /**
+ * \brief Compute the number of columns of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size2();
+ }
+};
+
+
+/**
+ * \brief Specialization of \c size_by_tag_impl for computing the size of the
+ * leading dimension of a row-major oriented matrix.
+ */
+template <>
+struct size_by_tag_impl<tag::leading, matrix_tag, row_major_tag>
+{
+ /**
+ * \brief Compute the number of columns of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size2();
+ }
+};
+
+
+/// \brief Specialization of \c size_by_tag_impl for computing the size of the
+/// major dimension of a column-major oriented matrix.
+template <>
+struct size_by_tag_impl<tag::major, matrix_tag, column_major_tag>
+{
+ /**
+ * \brief Compute the number of columns of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size2();
+ }
+};
+
+
+/// \brief Specialization of \c size_by_tag_impl for computing the size of the
+/// minor dimension of a column-major oriented matrix.
+template <>
+struct size_by_tag_impl<tag::minor, matrix_tag, column_major_tag>
+{
+ /**
+ * \brief Compute the number of rows of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size1();
+ }
+};
+
+
+/// \brief Specialization of \c size_by_tag_impl for computing the size of the
+/// leading dimension of a column-major oriented matrix.
+template <>
+struct size_by_tag_impl<tag::leading, matrix_tag, column_major_tag>
+{
+ /**
+ * \brief Compute the number of rows of the given matrix.
+ * \tparam ExprT A matrix expression type.
+ * \pre ExprT must be a model of MatrixExpression.
+ */
+ template <typename ExprT>
+ BOOST_UBLAS_INLINE
+ static typename matrix_traits<ExprT>::size_type apply(matrix_expression<ExprT> const& me)
+ {
+ return me().size1();
+ }
+};
+
+
+/// \brief Specialization of \c size_by_tag_impl for computing the size of the
+/// given dimension of a unknown oriented expression.
+template <typename TagT, typename CategoryT>
+struct size_by_tag_impl<TagT, CategoryT, unknown_orientation_tag>: size_by_tag_impl<TagT, CategoryT, row_major_tag>
+{
+ // Empty
+};
+
+}} // Namespace detail::<unnamed>
+
+
+/**
+ * \brief Return the number of columns.
+ * \tparam VectorExprT A type which models the vector expression concept.
+ * \param ve A vector expression.
+ * \return The length of the input vector expression.
+ */
+template <typename VectorExprT>
+BOOST_UBLAS_INLINE
+typename ::boost::lazy_enable_if_c<
+ detail::has_size_type<VectorExprT>::value,
+ detail::vector_size_type<VectorExprT>
+>::type size(vector_expression<VectorExprT> const& ve)
+{
+ return ve().size();
+}
+
+
+/**
+ * \brief Return the size of the given dimension for the given vector
+ * expression.
+ * \tparam Dim The dimension number (starting from 1).
+ * \tparam VectorExprT A vector expression type.
+ * \param ve A vector expression.
+ * \return The length of the input vector expression.
+ */
+template <std::size_t Dim, typename VectorExprT>
+BOOST_UBLAS_INLINE
+typename vector_traits<VectorExprT>::size_type size(vector_expression<VectorExprT> const& ve)
+{
+ return detail::size_by_dim_impl<Dim, vector_tag>::template apply(ve);
+}
+
+
+/**
+ * \brief Return the size of the given dimension for the given matrix
+ * expression.
+ * \tparam Dim The dimension number (starting from 1).
+ * \tparam MatrixExprT A matrix expression type.
+ * \param e A matrix expression.
+ * \return The size of the input matrix expression associated to the dimension
+ * \a Dim.
+ */
+template <std::size_t Dim, typename MatrixExprT>
+BOOST_UBLAS_INLINE
+typename matrix_traits<MatrixExprT>::size_type size(matrix_expression<MatrixExprT> const& me)
+{
+ return detail::size_by_dim_impl<Dim, matrix_tag>::template apply(me);
+}
+
+
+/**
+ * \brief Return the size of the given dimension tag for the given matrix
+ * expression.
+ * \tparam TagT The dimension tag type (e.g., tag::major).
+ * \tparam MatrixExprT A matrix expression type.
+ * \param e A matrix expression.
+ * \return The size of the input matrix expression associated to the dimension
+ * tag \a TagT.
+ */
+template <typename TagT, typename MatrixExprT>
+BOOST_UBLAS_INLINE
+typename ::boost::lazy_enable_if_c<
+ detail::has_size_type<MatrixExprT>::value,
+ detail::matrix_size_type<MatrixExprT>
+>::type size(matrix_expression<MatrixExprT> const& me)
+{
+ return detail::size_by_tag_impl<TagT, matrix_tag, typename matrix_traits<MatrixExprT>::orientation_category>::template apply(me);
+}
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP
--- /dev/null
+//
+// 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_OPERATION_BLOCKED_
+#define _BOOST_UBLAS_OPERATION_BLOCKED_
+
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/numeric/ublas/detail/vector_assign.hpp> // indexing_vector_assign
+#include <boost/numeric/ublas/detail/matrix_assign.hpp> // indexing_matrix_assign
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class V, typename V::size_type BS, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ block_prod (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef V vector_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ const size_type block_size = BS;
+
+ V v (e1 ().size1 ());
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v.size ());
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_assign> (cv, prod (e1, e2));
+#endif
+ size_type i_size = e1 ().size1 ();
+ size_type j_size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size ());
+ for (size_type i_begin = 0; i_begin < i_size; i_begin += block_size) {
+ size_type i_end = i_begin + (std::min) (i_size - i_begin, block_size);
+ // FIX: never ignore Martin Weiser's advice ;-(
+#ifdef BOOST_UBLAS_NO_CACHE
+ vector_range<vector_type> v_range (v, range (i_begin, i_end));
+#else
+ // vector<value_type, bounded_array<value_type, block_size> > v_range (i_end - i_begin);
+ vector<value_type> v_range (i_end - i_begin);
+#endif
+ v_range.assign (zero_vector<value_type> (i_end - i_begin));
+ for (size_type j_begin = 0; j_begin < j_size; j_begin += block_size) {
+ size_type j_end = j_begin + (std::min) (j_size - j_begin, block_size);
+#ifdef BOOST_UBLAS_NO_CACHE
+ const matrix_range<expression1_type> e1_range (e1 (), range (i_begin, i_end), range (j_begin, j_end));
+ const vector_range<expression2_type> e2_range (e2 (), range (j_begin, j_end));
+ v_range.plus_assign (prod (e1_range, e2_range));
+#else
+ // const matrix<value_type, row_major, bounded_array<value_type, block_size * block_size> > e1_range (project (e1 (), range (i_begin, i_end), range (j_begin, j_end)));
+ // const vector<value_type, bounded_array<value_type, block_size> > e2_range (project (e2 (), range (j_begin, j_end)));
+ const matrix<value_type, row_major> e1_range (project (e1 (), range (i_begin, i_end), range (j_begin, j_end)));
+ const vector<value_type> e2_range (project (e2 (), range (j_begin, j_end)));
+ v_range.plus_assign (prod (e1_range, e2_range));
+#endif
+ }
+#ifndef BOOST_UBLAS_NO_CACHE
+ project (v, range (i_begin, i_end)).assign (v_range);
+#endif
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+
+ template<class V, typename V::size_type BS, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ V
+ block_prod (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef V vector_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ const size_type block_size = BS;
+
+ V v (e2 ().size2 ());
+#if BOOST_UBLAS_TYPE_CHECK
+ vector<value_type> cv (v.size ());
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type verrorbound (norm_1 (v) + norm_1 (e1) * norm_1 (e2));
+ indexing_vector_assign<scalar_assign> (cv, prod (e1, e2));
+#endif
+ size_type i_size = BOOST_UBLAS_SAME (e1 ().size (), e2 ().size1 ());
+ size_type j_size = e2 ().size2 ();
+ for (size_type j_begin = 0; j_begin < j_size; j_begin += block_size) {
+ size_type j_end = j_begin + (std::min) (j_size - j_begin, block_size);
+ // FIX: never ignore Martin Weiser's advice ;-(
+#ifdef BOOST_UBLAS_NO_CACHE
+ vector_range<vector_type> v_range (v, range (j_begin, j_end));
+#else
+ // vector<value_type, bounded_array<value_type, block_size> > v_range (j_end - j_begin);
+ vector<value_type> v_range (j_end - j_begin);
+#endif
+ v_range.assign (zero_vector<value_type> (j_end - j_begin));
+ for (size_type i_begin = 0; i_begin < i_size; i_begin += block_size) {
+ size_type i_end = i_begin + (std::min) (i_size - i_begin, block_size);
+#ifdef BOOST_UBLAS_NO_CACHE
+ const vector_range<expression1_type> e1_range (e1 (), range (i_begin, i_end));
+ const matrix_range<expression2_type> e2_range (e2 (), range (i_begin, i_end), range (j_begin, j_end));
+#else
+ // const vector<value_type, bounded_array<value_type, block_size> > e1_range (project (e1 (), range (i_begin, i_end)));
+ // const matrix<value_type, column_major, bounded_array<value_type, block_size * block_size> > e2_range (project (e2 (), range (i_begin, i_end), range (j_begin, j_end)));
+ const vector<value_type> e1_range (project (e1 (), range (i_begin, i_end)));
+ const matrix<value_type, column_major> e2_range (project (e2 (), range (i_begin, i_end), range (j_begin, j_end)));
+#endif
+ v_range.plus_assign (prod (e1_range, e2_range));
+ }
+#ifndef BOOST_UBLAS_NO_CACHE
+ project (v, range (j_begin, j_end)).assign (v_range);
+#endif
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ BOOST_UBLAS_CHECK (norm_1 (v - cv) <= 2 * std::numeric_limits<real_type>::epsilon () * verrorbound, internal_logic ());
+#endif
+ return v;
+ }
+
+ template<class M, typename M::size_type BS, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ block_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ row_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ const size_type block_size = BS;
+
+ M m (e1 ().size1 (), e2 ().size2 ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_assign> (cm, prod (e1, e2), row_major_tag ());
+ disable_type_check<bool>::value = true;
+#endif
+ size_type i_size = e1 ().size1 ();
+ size_type j_size = e2 ().size2 ();
+ size_type k_size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ());
+ for (size_type i_begin = 0; i_begin < i_size; i_begin += block_size) {
+ size_type i_end = i_begin + (std::min) (i_size - i_begin, block_size);
+ for (size_type j_begin = 0; j_begin < j_size; j_begin += block_size) {
+ size_type j_end = j_begin + (std::min) (j_size - j_begin, block_size);
+ // FIX: never ignore Martin Weiser's advice ;-(
+#ifdef BOOST_UBLAS_NO_CACHE
+ matrix_range<matrix_type> m_range (m, range (i_begin, i_end), range (j_begin, j_end));
+#else
+ // matrix<value_type, row_major, bounded_array<value_type, block_size * block_size> > m_range (i_end - i_begin, j_end - j_begin);
+ matrix<value_type, row_major> m_range (i_end - i_begin, j_end - j_begin);
+#endif
+ m_range.assign (zero_matrix<value_type> (i_end - i_begin, j_end - j_begin));
+ for (size_type k_begin = 0; k_begin < k_size; k_begin += block_size) {
+ size_type k_end = k_begin + (std::min) (k_size - k_begin, block_size);
+#ifdef BOOST_UBLAS_NO_CACHE
+ const matrix_range<expression1_type> e1_range (e1 (), range (i_begin, i_end), range (k_begin, k_end));
+ const matrix_range<expression2_type> e2_range (e2 (), range (k_begin, k_end), range (j_begin, j_end));
+#else
+ // const matrix<value_type, row_major, bounded_array<value_type, block_size * block_size> > e1_range (project (e1 (), range (i_begin, i_end), range (k_begin, k_end)));
+ // const matrix<value_type, column_major, bounded_array<value_type, block_size * block_size> > e2_range (project (e2 (), range (k_begin, k_end), range (j_begin, j_end)));
+ const matrix<value_type, row_major> e1_range (project (e1 (), range (i_begin, i_end), range (k_begin, k_end)));
+ const matrix<value_type, column_major> e2_range (project (e2 (), range (k_begin, k_end), range (j_begin, j_end)));
+#endif
+ m_range.plus_assign (prod (e1_range, e2_range));
+ }
+#ifndef BOOST_UBLAS_NO_CACHE
+ project (m, range (i_begin, i_end), range (j_begin, j_end)).assign (m_range);
+#endif
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ disable_type_check<bool>::value = false;
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ template<class M, typename M::size_type BS, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ block_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ column_major_tag) {
+ typedef M matrix_type;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+ const size_type block_size = BS;
+
+ M m (e1 ().size1 (), e2 ().size2 ());
+#if BOOST_UBLAS_TYPE_CHECK
+ matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
+ typedef typename type_traits<value_type>::real_type real_type;
+ real_type merrorbound (norm_1 (m) + norm_1 (e1) * norm_1 (e2));
+ indexing_matrix_assign<scalar_assign> (cm, prod (e1, e2), column_major_tag ());
+ disable_type_check<bool>::value = true;
+#endif
+ size_type i_size = e1 ().size1 ();
+ size_type j_size = e2 ().size2 ();
+ size_type k_size = BOOST_UBLAS_SAME (e1 ().size2 (), e2 ().size1 ());
+ for (size_type j_begin = 0; j_begin < j_size; j_begin += block_size) {
+ size_type j_end = j_begin + (std::min) (j_size - j_begin, block_size);
+ for (size_type i_begin = 0; i_begin < i_size; i_begin += block_size) {
+ size_type i_end = i_begin + (std::min) (i_size - i_begin, block_size);
+ // FIX: never ignore Martin Weiser's advice ;-(
+#ifdef BOOST_UBLAS_NO_CACHE
+ matrix_range<matrix_type> m_range (m, range (i_begin, i_end), range (j_begin, j_end));
+#else
+ // matrix<value_type, column_major, bounded_array<value_type, block_size * block_size> > m_range (i_end - i_begin, j_end - j_begin);
+ matrix<value_type, column_major> m_range (i_end - i_begin, j_end - j_begin);
+#endif
+ m_range.assign (zero_matrix<value_type> (i_end - i_begin, j_end - j_begin));
+ for (size_type k_begin = 0; k_begin < k_size; k_begin += block_size) {
+ size_type k_end = k_begin + (std::min) (k_size - k_begin, block_size);
+#ifdef BOOST_UBLAS_NO_CACHE
+ const matrix_range<expression1_type> e1_range (e1 (), range (i_begin, i_end), range (k_begin, k_end));
+ const matrix_range<expression2_type> e2_range (e2 (), range (k_begin, k_end), range (j_begin, j_end));
+#else
+ // const matrix<value_type, row_major, bounded_array<value_type, block_size * block_size> > e1_range (project (e1 (), range (i_begin, i_end), range (k_begin, k_end)));
+ // const matrix<value_type, column_major, bounded_array<value_type, block_size * block_size> > e2_range (project (e2 (), range (k_begin, k_end), range (j_begin, j_end)));
+ const matrix<value_type, row_major> e1_range (project (e1 (), range (i_begin, i_end), range (k_begin, k_end)));
+ const matrix<value_type, column_major> e2_range (project (e2 (), range (k_begin, k_end), range (j_begin, j_end)));
+#endif
+ m_range.plus_assign (prod (e1_range, e2_range));
+ }
+#ifndef BOOST_UBLAS_NO_CACHE
+ project (m, range (i_begin, i_end), range (j_begin, j_end)).assign (m_range);
+#endif
+ }
+ }
+#if BOOST_UBLAS_TYPE_CHECK
+ disable_type_check<bool>::value = false;
+ BOOST_UBLAS_CHECK (norm_1 (m - cm) <= 2 * std::numeric_limits<real_type>::epsilon () * merrorbound, internal_logic ());
+#endif
+ return m;
+ }
+
+ // Dispatcher
+ template<class M, typename M::size_type BS, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ block_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef typename M::orientation_category orientation_category;
+ return block_prod<M, BS> (e1, e2, orientation_category ());
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_OPERATION_SPARSE_
+#define _BOOST_UBLAS_OPERATION_SPARSE_
+
+#include <boost/numeric/ublas/traits.hpp>
+
+// These scaled additions were borrowed from MTL unashamedly.
+// But Alexei Novakov had a lot of ideas to improve these. Thanks.
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ row_major_tag) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+ // ISSUE why is there a dense vector here?
+ vector<value_type> temporary (e2 ().size2 ());
+ temporary.clear ();
+ typename expression1_type::const_iterator1 it1 (e1 ().begin1 ());
+ typename expression1_type::const_iterator1 it1_end (e1 ().end1 ());
+ while (it1 != it1_end) {
+ size_type jb (temporary.size ());
+ size_type je (0);
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression1_type::const_iterator2 it2 (it1.begin ());
+ typename expression1_type::const_iterator2 it2_end (it1.end ());
+#else
+ typename expression1_type::const_iterator2 it2 (boost::numeric::ublas::begin (it1, iterator1_tag ()));
+ typename expression1_type::const_iterator2 it2_end (boost::numeric::ublas::end (it1, iterator1_tag ()));
+#endif
+ while (it2 != it2_end) {
+ // temporary.plus_assign (*it2 * row (e2 (), it2.index2 ()));
+ matrix_row<expression2_type> mr (e2 (), it2.index2 ());
+ typename matrix_row<expression2_type>::const_iterator itr (mr.begin ());
+ typename matrix_row<expression2_type>::const_iterator itr_end (mr.end ());
+ while (itr != itr_end) {
+ size_type j (itr.index ());
+ temporary (j) += *it2 * *itr;
+ jb = (std::min) (jb, j);
+ je = (std::max) (je, j);
+ ++ itr;
+ }
+ ++ it2;
+ }
+ for (size_type j = jb; j < je + 1; ++ j) {
+ if (temporary (j) != value_type/*zero*/()) {
+ // FIXME we'll need to extend the container interface!
+ // m.push_back (it1.index1 (), j, temporary (j));
+ // FIXME What to do with adaptors?
+ // m.insert (it1.index1 (), j, temporary (j));
+ if (triangular_restriction::other (it1.index1 (), j))
+ m (it1.index1 (), j) = temporary (j);
+ temporary (j) = value_type/*zero*/();
+ }
+ }
+ ++ it1;
+ }
+ return m;
+ }
+
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI,
+ column_major_tag) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+ typedef const E1 expression1_type;
+ typedef const E2 expression2_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::value_type value_type;
+
+ // ISSUE why is there a dense vector here?
+ vector<value_type> temporary (e1 ().size1 ());
+ temporary.clear ();
+ typename expression2_type::const_iterator2 it2 (e2 ().begin2 ());
+ typename expression2_type::const_iterator2 it2_end (e2 ().end2 ());
+ while (it2 != it2_end) {
+ size_type ib (temporary.size ());
+ size_type ie (0);
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ typename expression2_type::const_iterator1 it1 (it2.begin ());
+ typename expression2_type::const_iterator1 it1_end (it2.end ());
+#else
+ typename expression2_type::const_iterator1 it1 (boost::numeric::ublas::begin (it2, iterator2_tag ()));
+ typename expression2_type::const_iterator1 it1_end (boost::numeric::ublas::end (it2, iterator2_tag ()));
+#endif
+ while (it1 != it1_end) {
+ // column (m, it2.index2 ()).plus_assign (*it1 * column (e1 (), it1.index1 ()));
+ matrix_column<expression1_type> mc (e1 (), it1.index1 ());
+ typename matrix_column<expression1_type>::const_iterator itc (mc.begin ());
+ typename matrix_column<expression1_type>::const_iterator itc_end (mc.end ());
+ while (itc != itc_end) {
+ size_type i (itc.index ());
+ temporary (i) += *it1 * *itc;
+ ib = (std::min) (ib, i);
+ ie = (std::max) (ie, i);
+ ++ itc;
+ }
+ ++ it1;
+ }
+ for (size_type i = ib; i < ie + 1; ++ i) {
+ if (temporary (i) != value_type/*zero*/()) {
+ // FIXME we'll need to extend the container interface!
+ // m.push_back (i, it2.index2 (), temporary (i));
+ // FIXME What to do with adaptors?
+ // m.insert (i, it2.index2 (), temporary (i));
+ if (triangular_restriction::other (i, it2.index2 ()))
+ m (i, it2.index2 ()) = temporary (i);
+ temporary (i) = value_type/*zero*/();
+ }
+ }
+ ++ it2;
+ }
+ return m;
+ }
+
+ // Dispatcher
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M &
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, TRI, bool init = true) {
+ typedef typename M::value_type value_type;
+ typedef TRI triangular_restriction;
+ typedef typename M::orientation_category orientation_category;
+
+ if (init)
+ m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
+ return sparse_prod (e1, e2, m, triangular_restriction (), orientation_category ());
+ }
+ template<class M, class E1, class E2, class TRI>
+ BOOST_UBLAS_INLINE
+ M
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ TRI) {
+ typedef M matrix_type;
+ typedef TRI triangular_restriction;
+
+ matrix_type m (e1 ().size1 (), e2 ().size2 ());
+ // FIXME needed for c_matrix?!
+ // return sparse_prod (e1, e2, m, triangular_restriction (), false);
+ return sparse_prod (e1, e2, m, triangular_restriction (), true);
+ }
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M &
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ M &m, bool init = true) {
+ typedef typename M::value_type value_type;
+ typedef typename M::orientation_category orientation_category;
+
+ if (init)
+ m.assign (zero_matrix<value_type> (e1 ().size1 (), e2 ().size2 ()));
+ return sparse_prod (e1, e2, m, full (), orientation_category ());
+ }
+ template<class M, class E1, class E2>
+ BOOST_UBLAS_INLINE
+ M
+ sparse_prod (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2) {
+ typedef M matrix_type;
+
+ matrix_type m (e1 ().size1 (), e2 ().size2 ());
+ // FIXME needed for c_matrix?!
+ // return sparse_prod (e1, e2, m, full (), false);
+ return sparse_prod (e1, e2, m, full (), true);
+ }
+
+}}}
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file operations.hpp
+ *
+ * \brief This header includes several headers from the operation directory.
+ *
+ * Copyright (c) 2009, Gunter Winkler
+ *
+ * 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)
+ *
+ * \author Gunter Winkler (guwi17 at gmx dot de)
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_OPERATIONS_HPP
+#define BOOST_NUMERIC_UBLAS_OPERATIONS_HPP
+
+#include <boost/numeric/ublas/operation/begin.hpp>
+#include <boost/numeric/ublas/operation/end.hpp>
+#include <boost/numeric/ublas/operation/num_columns.hpp>
+#include <boost/numeric/ublas/operation/num_rows.hpp>
+#include <boost/numeric/ublas/operation/size.hpp>
+
+#endif
--- /dev/null
+//
+// 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_STORAGE_H
+#define BOOST_UBLAS_STORAGE_H
+
+#include <algorithm>
+#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
+#include <boost/shared_array.hpp>
+#endif
+
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/nvp.hpp>
+
+#include <boost/numeric/ublas/exception.hpp>
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/numeric/ublas/detail/iterator.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+
+ // Base class for Storage Arrays - see the Barton Nackman trick
+ template<class E>
+ class storage_array:
+ private nonassignable {
+ };
+
+
+ // Unbounded array - with allocator
+ template<class T, class ALLOC>
+ class unbounded_array:
+ public storage_array<unbounded_array<T, ALLOC> > {
+
+ typedef unbounded_array<T, ALLOC> self_type;
+ public:
+ typedef ALLOC allocator_type;
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef T *pointer;
+ typedef const_pointer const_iterator;
+ typedef pointer iterator;
+
+ // Construction and destruction
+ explicit BOOST_UBLAS_INLINE
+ unbounded_array (const ALLOC &a = ALLOC()):
+ alloc_ (a), size_ (0) {
+ data_ = 0;
+ }
+ explicit BOOST_UBLAS_INLINE
+ unbounded_array (size_type size, const ALLOC &a = ALLOC()):
+ alloc_(a), size_ (size) {
+ if (size_) {
+ data_ = alloc_.allocate (size_);
+ if (! detail::has_trivial_constructor<T>::value) {
+ for (pointer d = data_; d != data_ + size_; ++d)
+ alloc_.construct(d, value_type());
+ }
+ }
+ else
+ data_ = 0;
+ }
+ // No value initialised, but still be default constructed
+ BOOST_UBLAS_INLINE
+ unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()):
+ alloc_ (a), size_ (size) {
+ if (size_) {
+ data_ = alloc_.allocate (size_);
+ std::uninitialized_fill (begin(), end(), init);
+ }
+ else
+ data_ = 0;
+ }
+ BOOST_UBLAS_INLINE
+ unbounded_array (const unbounded_array &c):
+ storage_array<unbounded_array<T, ALLOC> >(),
+ alloc_ (c.alloc_), size_ (c.size_) {
+ if (size_) {
+ data_ = alloc_.allocate (size_);
+ std::uninitialized_copy (c.begin(), c.end(), begin());
+ }
+ else
+ data_ = 0;
+ }
+ BOOST_UBLAS_INLINE
+ ~unbounded_array () {
+ if (size_) {
+ if (! detail::has_trivial_destructor<T>::value) {
+ // std::_Destroy (begin(), end(), alloc_);
+ const iterator i_end = end();
+ for (iterator i = begin (); i != i_end; ++i) {
+ iterator_destroy (i);
+ }
+ }
+ alloc_.deallocate (data_, size_);
+ }
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ void resize_internal (const size_type size, const value_type init, const bool preserve) {
+ if (size != size_) {
+ pointer p_data = data_;
+ if (size) {
+ data_ = alloc_.allocate (size);
+ if (preserve) {
+ pointer si = p_data;
+ pointer di = data_;
+ if (size < size_) {
+ for (; di != data_ + size; ++di) {
+ alloc_.construct (di, *si);
+ ++si;
+ }
+ }
+ else {
+ for (pointer si = p_data; si != p_data + size_; ++si) {
+ alloc_.construct (di, *si);
+ ++di;
+ }
+ for (; di != data_ + size; ++di) {
+ alloc_.construct (di, init);
+ }
+ }
+ }
+ else {
+ if (! detail::has_trivial_constructor<T>::value) {
+ for (pointer di = data_; di != data_ + size; ++di)
+ alloc_.construct (di, value_type());
+ }
+ }
+ }
+
+ if (size_) {
+ if (! detail::has_trivial_destructor<T>::value) {
+ for (pointer si = p_data; si != p_data + size_; ++si)
+ alloc_.destroy (si);
+ }
+ alloc_.deallocate (p_data, size_);
+ }
+
+ if (!size)
+ data_ = 0;
+ size_ = size;
+ }
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size) {
+ resize_internal (size, value_type (), false);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, value_type init) {
+ resize_internal (size, init, true);
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return ALLOC ().max_size();
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return size_ == 0;
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ unbounded_array &operator = (const unbounded_array &a) {
+ if (this != &a) {
+ resize (a.size_);
+ std::copy (a.data_, a.data_ + a.size_, data_);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ unbounded_array &assign_temporary (unbounded_array &a) {
+ swap (a);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (unbounded_array &a) {
+ if (this != &a) {
+ std::swap (size_, a.size_);
+ std::swap (data_, a.data_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (unbounded_array &a1, unbounded_array &a2) {
+ a1.swap (a2);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_ + size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_ + size_;
+ }
+
+ // Reverse iterators
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Allocator
+ allocator_type get_allocator () {
+ return alloc_;
+ }
+
+ private:
+ friend class boost::serialization::access;
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ serialization::collection_size_type s(size_);
+ ar & serialization::make_nvp("size",s);
+ if ( Archive::is_loading::value ) {
+ resize(s);
+ }
+ ar & serialization::make_array(data_, s);
+ }
+
+ private:
+ // Handle explict destroy on a (possibly indexed) iterator
+ BOOST_UBLAS_INLINE
+ static void iterator_destroy (iterator &i) {
+ (&(*i)) -> ~value_type ();
+ }
+ ALLOC alloc_;
+ size_type size_;
+ pointer data_;
+ };
+
+ // Bounded array - with allocator for size_type and difference_type
+ template<class T, std::size_t N, class ALLOC>
+ class bounded_array:
+ public storage_array<bounded_array<T, N, ALLOC> > {
+
+ typedef bounded_array<T, N, ALLOC> self_type;
+ public:
+ // No allocator_type as ALLOC is not used for allocation
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef T *pointer;
+ typedef const_pointer const_iterator;
+ typedef pointer iterator;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ bounded_array ():
+ size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N
+ }
+ explicit BOOST_UBLAS_INLINE
+ bounded_array (size_type size):
+ size_ (size) /*, data_ ()*/ {
+ BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
+ // data_ (an array) elements are already default constructed
+ }
+ BOOST_UBLAS_INLINE
+ bounded_array (size_type size, const value_type &init):
+ size_ (size) /*, data_ ()*/ {
+ BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
+ // ISSUE elements should be value constructed here, but we must fill instead as already default constructed
+ std::fill (begin(), end(), init) ;
+ }
+ BOOST_UBLAS_INLINE
+ bounded_array (const bounded_array &c):
+ size_ (c.size_) {
+ // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed
+ std::copy (c.begin(), c.end(), begin());
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size) {
+ BOOST_UBLAS_CHECK (size <= N, bad_size ());
+ size_ = size;
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, value_type init) {
+ BOOST_UBLAS_CHECK (size <= N, bad_size ());
+ if (size > size_)
+ std::fill (data_ + size_, data_ + size, init);
+ size_ = size;
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return ALLOC ().max_size();
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return size_ == 0;
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ bounded_array &operator = (const bounded_array &a) {
+ if (this != &a) {
+ resize (a.size_);
+ std::copy (a.data_, a.data_ + a.size_, data_);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ bounded_array &assign_temporary (bounded_array &a) {
+ *this = a;
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (bounded_array &a) {
+ if (this != &a) {
+ std::swap (size_, a.size_);
+ std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (bounded_array &a1, bounded_array &a2) {
+ a1.swap (a2);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_ + size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_ + size_;
+ }
+
+ // Reverse iterators
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ // Serialization
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ serialization::collection_size_type s(size_);
+ ar & serialization::make_nvp("size", s);
+ if ( Archive::is_loading::value ) {
+ if (s > N) bad_size("too large size in bounded_array::load()\n").raise();
+ resize(s);
+ }
+ ar & serialization::make_array(data_, s);
+ }
+
+ private:
+ size_type size_;
+ BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N];
+ };
+
+
+ // Array adaptor with normal deep copy semantics of elements
+ template<class T>
+ class array_adaptor:
+ public storage_array<array_adaptor<T> > {
+
+ typedef array_adaptor<T> self_type;
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef T *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ array_adaptor ():
+ size_ (0), own_ (true), data_ (new value_type [0]) {
+ }
+ explicit BOOST_UBLAS_INLINE
+ array_adaptor (size_type size):
+ size_ (size), own_ (true), data_ (new value_type [size]) {
+ }
+ BOOST_UBLAS_INLINE
+ array_adaptor (size_type size, const value_type &init):
+ size_ (size), own_ (true), data_ (new value_type [size]) {
+ std::fill (data_, data_ + size_, init);
+ }
+ BOOST_UBLAS_INLINE
+ array_adaptor (size_type size, pointer data):
+ size_ (size), own_ (false), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ array_adaptor (const array_adaptor &a):
+ storage_array<self_type> (),
+ size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) {
+ *this = a;
+ }
+ BOOST_UBLAS_INLINE
+ ~array_adaptor () {
+ if (own_) {
+ delete [] data_;
+ }
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ void resize_internal (size_type size, value_type init, bool preserve = true) {
+ if (size != size_) {
+ pointer data = new value_type [size];
+ if (preserve) {
+ std::copy (data_, data_ + (std::min) (size, size_), data);
+ std::fill (data + (std::min) (size, size_), data + size, init);
+ }
+ if (own_)
+ delete [] data_;
+ size_ = size;
+ own_ = true;
+ data_ = data;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
+ if (data != data_) {
+ if (preserve) {
+ std::copy (data_, data_ + (std::min) (size, size_), data);
+ std::fill (data + (std::min) (size, size_), data + size, init);
+ }
+ if (own_)
+ delete [] data_;
+ own_ = false;
+ data_ = data;
+ }
+ else {
+ std::fill (data + (std::min) (size, size_), data + size, init);
+ }
+ size_ = size;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size) {
+ resize_internal (size, value_type (), false);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, value_type init) {
+ resize_internal (size, init, true);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, pointer data) {
+ resize_internal (size, data, value_type (), false);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, pointer data, value_type init) {
+ resize_internal (size, data, init, true);
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ array_adaptor &operator = (const array_adaptor &a) {
+ if (this != &a) {
+ resize (a.size_);
+ std::copy (a.data_, a.data_ + a.size_, data_);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ array_adaptor &assign_temporary (array_adaptor &a) {
+ if (own_ && a.own_)
+ swap (a);
+ else
+ *this = a;
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (array_adaptor &a) {
+ if (this != &a) {
+ std::swap (size_, a.size_);
+ std::swap (own_, a.own_);
+ std::swap (data_, a.data_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (array_adaptor &a1, array_adaptor &a2) {
+ a1.swap (a2);
+ }
+
+ // Iterators simply are pointers.
+
+ typedef const_pointer const_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_ + size_;
+ }
+
+ typedef pointer iterator;
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_ + size_;
+ }
+
+ // Reverse iterators
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ size_type size_;
+ bool own_;
+ pointer data_;
+ };
+
+#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
+ // Array adaptor with shallow (reference) copy semantics of elements.
+ // shared_array is used to maintain reference counts.
+ // This class breaks the normal copy semantics for a storage container and is very dangerous!
+ template<class T>
+ class shallow_array_adaptor:
+ public storage_array<shallow_array_adaptor<T> > {
+
+ typedef shallow_array_adaptor<T> self_type;
+
+ template<class TT>
+ struct leaker {
+ typedef void result_type;
+ typedef TT *argument_type;
+
+ BOOST_UBLAS_INLINE
+ result_type operator () (argument_type x) {}
+ };
+
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef T *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor ():
+ size_ (0), own_ (true), data_ (new value_type [0]) {
+ }
+ explicit BOOST_UBLAS_INLINE
+ shallow_array_adaptor (size_type size):
+ size_ (size), own_ (true), data_ (new value_type [size]) {
+ }
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor (size_type size, const value_type &init):
+ size_ (size), own_ (true), data_ (new value_type [size]) {
+ std::fill (data_.get (), data_.get () + size_, init);
+ }
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor (size_type size, pointer data):
+ size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {}
+
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor (const shallow_array_adaptor &a):
+ storage_array<self_type> (),
+ size_ (a.size_), own_ (a.own_), data_ (a.data_) {}
+
+ BOOST_UBLAS_INLINE
+ ~shallow_array_adaptor () {
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ void resize_internal (size_type size, value_type init, bool preserve = true) {
+ if (size != size_) {
+ shared_array<value_type> data (new value_type [size]);
+ if (preserve) {
+ std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ());
+ std::fill (data.get () + (std::min) (size, size_), data.get () + size, init);
+ }
+ size_ = size;
+ data_ = data;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
+ if (preserve) {
+ std::copy (data_.get (), data_.get () + (std::min) (size, size_), data);
+ std::fill (data + (std::min) (size, size_), data + size, init);
+ }
+ size_ = size;
+ data_ = data;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size) {
+ resize_internal (size, value_type (), false);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, value_type init) {
+ resize_internal (size, init, true);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, pointer data) {
+ resize_internal (size, data, value_type (), false);
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, pointer data, value_type init) {
+ resize_internal (size, data, init, true);
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor &operator = (const shallow_array_adaptor &a) {
+ if (this != &a) {
+ resize (a.size_);
+ std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ());
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) {
+ if (own_ && a.own_)
+ swap (a);
+ else
+ *this = a;
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (shallow_array_adaptor &a) {
+ if (this != &a) {
+ std::swap (size_, a.size_);
+ std::swap (own_, a.own_);
+ std::swap (data_, a.data_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) {
+ a1.swap (a2);
+ }
+
+ // Iterators simply are pointers.
+
+ typedef const_pointer const_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_.get ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_.get () + size_;
+ }
+
+ typedef pointer iterator;
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_.get ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_.get () + size_;
+ }
+
+ // Reverse iterators
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ size_type size_;
+ bool own_;
+ shared_array<value_type> data_;
+ };
+
+#endif
+
+
+ // Range class
+ template <class Z, class D>
+ class basic_range {
+ typedef basic_range<Z, D> self_type;
+ public:
+ typedef Z size_type;
+ typedef D difference_type;
+ typedef size_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const value_type *const_pointer;
+ typedef value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ basic_range ():
+ start_ (0), size_ (0) {}
+ BOOST_UBLAS_INLINE
+ basic_range (size_type start, size_type stop):
+ start_ (start), size_ (stop - start) {
+ BOOST_UBLAS_CHECK (start_ <= stop, bad_index ());
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type start () const {
+ return start_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return size_ == 0;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return start_ + i;
+ }
+
+ // Composition
+ BOOST_UBLAS_INLINE
+ basic_range compose (const basic_range &r) const {
+ return basic_range (start_ + r.start_, start_ + r.start_ + r.size_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const basic_range &r) const {
+ return start_ == r.start_ && size_ == r.size_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator != (const basic_range &r) const {
+ return ! (*this == r);
+ }
+
+ // Iterator types
+ private:
+ // Use and index
+ typedef size_type const_subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
+#else
+ class const_iterator:
+ public container_const_reference<basic_range>,
+ public random_access_iterator_base<std::random_access_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename basic_range::value_type value_type;
+ typedef typename basic_range::difference_type difference_type;
+ typedef typename basic_range::const_reference reference;
+ typedef typename basic_range::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<basic_range> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const basic_range &r, const const_subiterator_type &it):
+ container_const_reference<basic_range> (r), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
+ BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
+ return it_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
+ BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
+ return it_ - (*this) ().start ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ // Comeau recommends...
+ this->assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
+ return it_ == it.it_;
+ }
+ 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_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this, start_);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this, start_ + size_);
+ }
+
+ // Reverse iterator
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ BOOST_UBLAS_INLINE
+ basic_range preprocess (size_type size) const {
+ if (this != &all_)
+ return *this;
+ return basic_range (0, size);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ const basic_range &all () {
+ return all_;
+ }
+
+ private:
+ size_type start_;
+ size_type size_;
+ static const basic_range all_;
+ };
+
+ template <class Z, class D>
+ const basic_range<Z,D> basic_range<Z,D>::all_ (0, size_type (-1));
+
+
+ // Slice class
+ template <class Z, class D>
+ class basic_slice {
+ typedef basic_slice<Z, D> self_type;
+ public:
+ typedef Z size_type;
+ typedef D difference_type;
+ typedef size_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const value_type *const_pointer;
+ typedef value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ basic_slice ():
+ start_ (0), stride_ (0), size_ (0) {}
+ BOOST_UBLAS_INLINE
+ basic_slice (size_type start, difference_type stride, size_type size):
+ start_ (start), stride_ (stride), size_ (size) {}
+
+ BOOST_UBLAS_INLINE
+ size_type start () const {
+ return start_;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride () const {
+ return stride_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return size_ == 0;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ());
+ return start_ + i * stride_;
+ }
+
+ // Composition
+ BOOST_UBLAS_INLINE
+ basic_slice compose (const basic_range<size_type, difference_type> &r) const {
+ BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ());
+ return basic_slice (start_ + stride_ * r.start (), stride_, r.size ());
+ }
+ BOOST_UBLAS_INLINE
+ basic_slice compose (const basic_slice &s) const {
+ BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ());
+ return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const basic_slice &s) const {
+ return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator != (const basic_slice &s) const {
+ return ! (*this == s);
+ }
+
+ // Iterator types
+ private:
+ // Use and index
+ typedef size_type const_subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
+#else
+ class const_iterator:
+ public container_const_reference<basic_slice>,
+ public random_access_iterator_base<std::random_access_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename basic_slice::value_type value_type;
+ typedef typename basic_slice::difference_type difference_type;
+ typedef typename basic_slice::const_reference reference;
+ typedef typename basic_slice::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<basic_slice> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const basic_slice &s, const const_subiterator_type &it):
+ container_const_reference<basic_slice> (s), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
+ --it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
+ return (*this) ().start () + it_* (*this) ().stride ();
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ // Comeau recommends...
+ this->assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
+ return it_ == it.it_;
+ }
+ 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_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this, size_);
+ }
+
+ // Reverse iterator
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ BOOST_UBLAS_INLINE
+ basic_slice preprocess (size_type size) const {
+ if (this != &all_)
+ return *this;
+ return basic_slice (0, 1, size);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ const basic_slice &all () {
+ return all_;
+ }
+
+ private:
+ size_type start_;
+ difference_type stride_;
+ size_type size_;
+ static const basic_slice all_;
+ };
+
+ template <class Z, class D>
+ const basic_slice<Z,D> basic_slice<Z,D>::all_ (0, 1, size_type (-1));
+
+
+ // Indirect array class
+ template<class A>
+ class indirect_array {
+ typedef indirect_array<A> self_type;
+ public:
+ typedef A array_type;
+ typedef const A const_array_type;
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef typename A::value_type value_type;
+ typedef typename A::const_reference const_reference;
+ typedef typename A::reference reference;
+ typedef typename A::const_pointer const_pointer;
+ typedef typename A::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ indirect_array ():
+ size_ (), data_ () {}
+ explicit BOOST_UBLAS_INLINE
+ indirect_array (size_type size):
+ size_ (size), data_ (size) {}
+ BOOST_UBLAS_INLINE
+ indirect_array (size_type size, const array_type &data):
+ size_ (size), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ indirect_array (pointer start, pointer stop):
+ size_ (stop - start), data_ (stop - start) {
+ std::copy (start, stop, data_.begin ());
+ }
+
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ const_array_type data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type data () {
+ return data_;
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return data_.size () == 0;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+
+ // Composition
+ BOOST_UBLAS_INLINE
+ indirect_array compose (const basic_range<size_type, difference_type> &r) const {
+ BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ());
+ array_type data (r.size ());
+ for (size_type i = 0; i < r.size (); ++ i)
+ data [i] = data_ [r.start () + i];
+ return indirect_array (r.size (), data);
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array compose (const basic_slice<size_type, difference_type> &s) const {
+ BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ());
+ array_type data (s.size ());
+ for (size_type i = 0; i < s.size (); ++ i)
+ data [i] = data_ [s.start () + s.stride () * i];
+ return indirect_array (s.size (), data);
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array compose (const indirect_array &ia) const {
+ array_type data (ia.size_);
+ for (size_type i = 0; i < ia.size_; ++ i) {
+ BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ());
+ data [i] = data_ [ia.data_ [i]];
+ }
+ return indirect_array (ia.size_, data);
+ }
+
+ // Comparison
+ template<class OA>
+ BOOST_UBLAS_INLINE
+ bool operator == (const indirect_array<OA> &ia) const {
+ if (size_ != ia.size_)
+ return false;
+ for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i)
+ if (data_ [i] != ia.data_ [i])
+ return false;
+ return true;
+ }
+ template<class OA>
+ BOOST_UBLAS_INLINE
+ bool operator != (const indirect_array<OA> &ia) const {
+ return ! (*this == ia);
+ }
+
+ // Iterator types
+ private:
+ // Use a index difference
+ typedef difference_type const_subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator;
+#else
+ class const_iterator:
+ public container_const_reference<indirect_array>,
+ public random_access_iterator_base<std::random_access_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename indirect_array::value_type value_type;
+ typedef typename indirect_array::difference_type difference_type;
+ typedef typename indirect_array::const_reference reference;
+ typedef typename indirect_array::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<indirect_array> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const indirect_array &ia, const const_subiterator_type &it):
+ container_const_reference<indirect_array> (ia), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it_);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ // Comeau recommends...
+ this->assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
+ return it_ == it.it_;
+ }
+ 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_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this, size_);
+ }
+
+ // Reverse iterator
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ BOOST_UBLAS_INLINE
+ indirect_array preprocess (size_type size) const {
+ if (this != &all_)
+ return *this;
+ indirect_array ia (size);
+ for (size_type i = 0; i < size; ++ i)
+ ia (i) = i;
+ return ia;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ const indirect_array &all () {
+ return all_;
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ static const indirect_array all_;
+ };
+
+ template<class A>
+ const indirect_array<A> indirect_array<A>::all_;
+
+
+
+ // Gunter Winkler contributed the classes index_pair, index_pair_array,
+ // index_triple and index_triple_array to enable inplace sort of parallel arrays.
+
+ template <class V>
+ class index_pair :
+ private boost::noncopyable,
+ public container_reference<V> {
+
+ typedef index_pair<V> self_type;
+ public:
+ typedef typename V::size_type size_type;
+
+ BOOST_UBLAS_INLINE
+ index_pair(V& v, size_type i) :
+ container_reference<V>(v), i_(i),
+ v1_(v.data1_[i]), v2_(v.data2_[i]),
+ dirty_(false), is_copy_(false) {}
+ BOOST_UBLAS_INLINE
+ index_pair(const self_type& rhs) :
+ container_reference<V>(rhs()), i_(0),
+ v1_(rhs.v1_), v2_(rhs.v2_),
+ dirty_(false), is_copy_(true) {}
+ BOOST_UBLAS_INLINE
+ ~index_pair() {
+ if (dirty_ && (!is_copy_) ) {
+ (*this)().data1_[i_] = v1_;
+ (*this)().data2_[i_] = v2_;
+ }
+ }
+
+ BOOST_UBLAS_INLINE
+ self_type& operator=(const self_type& rhs) {
+ v1_ = rhs.v1_;
+ v2_ = rhs.v2_;
+ dirty_ = true;
+ return *this;
+ }
+
+ BOOST_UBLAS_INLINE
+ void swap(self_type& rhs) {
+ self_type tmp(rhs);
+ rhs = *this;
+ *this = tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap(self_type& lhs, self_type& rhs) {
+ lhs.swap(rhs);
+ }
+
+ BOOST_UBLAS_INLINE
+ bool equal(const self_type& rhs) const {
+ return (v1_ == rhs.v1_);
+ }
+ BOOST_UBLAS_INLINE
+ bool less(const self_type& rhs) const {
+ return (v1_ < rhs.v1_);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator == (const self_type& lhs, const self_type& rhs) {
+ return lhs.equal(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator != (const self_type& lhs, const self_type& rhs) {
+ return !lhs.equal(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator < (const self_type& lhs, const self_type& rhs) {
+ return lhs.less(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator >= (const self_type& lhs, const self_type& rhs) {
+ return !lhs.less(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator > (const self_type& lhs, const self_type& rhs) {
+ return rhs.less(lhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator <= (const self_type& lhs, const self_type& rhs) {
+ return !rhs.less(lhs);
+ }
+
+ private:
+ size_type i_;
+ typename V::value1_type v1_;
+ typename V::value2_type v2_;
+ bool dirty_;
+ bool is_copy_;
+ };
+
+ template <class V1, class V2>
+ class index_pair_array:
+ private boost::noncopyable {
+
+ typedef index_pair_array<V1, V2> self_type;
+ public:
+ typedef typename V1::value_type value1_type;
+ typedef typename V2::value_type value2_type;
+
+ typedef typename V1::size_type size_type;
+ typedef typename V1::difference_type difference_type;
+ typedef index_pair<self_type> value_type;
+ // There is nothing that can be referenced directly. Always return a copy of the index_pair
+ typedef value_type reference;
+ typedef const value_type const_reference;
+
+ BOOST_UBLAS_INLINE
+ index_pair_array(size_type size, V1& data1, V2& data2) :
+ size_(size),data1_(data1),data2_(data2) {}
+
+ BOOST_UBLAS_INLINE
+ size_type size() const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return value_type((*this), i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return value_type((*this), i);
+ }
+
+ typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
+ typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
+
+ BOOST_UBLAS_INLINE
+ iterator begin() {
+ return iterator( (*this), 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end() {
+ return iterator( (*this), size());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin() const {
+ return const_iterator( (*this), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end() const {
+ return const_iterator( (*this), size());
+ }
+
+ // unnecessary function:
+ BOOST_UBLAS_INLINE
+ bool equal(size_type i1, size_type i2) const {
+ return data1_[i1] == data1_[i2];
+ }
+ BOOST_UBLAS_INLINE
+ bool less(size_type i1, size_type i2) const {
+ return data1_[i1] < data1_[i2];
+ }
+
+ // gives a large speedup
+ BOOST_UBLAS_INLINE
+ friend void iter_swap(const iterator& lhs, const iterator& rhs) {
+ const size_type i1 = lhs.index();
+ const size_type i2 = rhs.index();
+ std::swap(lhs().data1_[i1], rhs().data1_[i2]);
+ std::swap(lhs().data2_[i1], rhs().data2_[i2]);
+ }
+
+ private:
+ size_type size_;
+ V1& data1_;
+ V2& data2_;
+
+ // friend class value_type;
+ friend class index_pair<self_type>;
+ };
+
+ template <class M>
+ class index_triple :
+ private boost::noncopyable,
+ public container_reference<M> {
+
+ typedef index_triple<M> self_type;
+ public:
+ typedef typename M::size_type size_type;
+
+ BOOST_UBLAS_INLINE
+ index_triple(M& m, size_type i) :
+ container_reference<M>(m), i_(i),
+ v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]),
+ dirty_(false), is_copy_(false) {}
+ BOOST_UBLAS_INLINE
+ index_triple(const self_type& rhs) :
+ container_reference<M>(rhs()), i_(0),
+ v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_),
+ dirty_(false), is_copy_(true) {}
+ BOOST_UBLAS_INLINE
+ ~index_triple() {
+ if (dirty_ && (!is_copy_) ) {
+ (*this)().data1_[i_] = v1_;
+ (*this)().data2_[i_] = v2_;
+ (*this)().data3_[i_] = v3_;
+ }
+ }
+
+ BOOST_UBLAS_INLINE
+ self_type& operator=(const self_type& rhs) {
+ v1_ = rhs.v1_;
+ v2_ = rhs.v2_;
+ v3_ = rhs.v3_;
+ dirty_ = true;
+ return *this;
+ }
+
+ BOOST_UBLAS_INLINE
+ void swap(self_type& rhs) {
+ self_type tmp(rhs);
+ rhs = *this;
+ *this = tmp;
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap(self_type& lhs, self_type& rhs) {
+ lhs.swap(rhs);
+ }
+
+ BOOST_UBLAS_INLINE
+ bool equal(const self_type& rhs) const {
+ return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_));
+ }
+ BOOST_UBLAS_INLINE
+ bool less(const self_type& rhs) const {
+ return ((v1_ < rhs.v1_) ||
+ (v1_ == rhs.v1_ && v2_ < rhs.v2_));
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator == (const self_type& lhs, const self_type& rhs) {
+ return lhs.equal(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator != (const self_type& lhs, const self_type& rhs) {
+ return !lhs.equal(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator < (const self_type& lhs, const self_type& rhs) {
+ return lhs.less(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator >= (const self_type& lhs, const self_type& rhs) {
+ return !lhs.less(rhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator > (const self_type& lhs, const self_type& rhs) {
+ return rhs.less(lhs);
+ }
+ BOOST_UBLAS_INLINE
+ friend bool operator <= (const self_type& lhs, const self_type& rhs) {
+ return !rhs.less(lhs);
+ }
+
+ private:
+ size_type i_;
+ typename M::value1_type v1_;
+ typename M::value2_type v2_;
+ typename M::value3_type v3_;
+ bool dirty_;
+ bool is_copy_;
+ };
+
+ template <class V1, class V2, class V3>
+ class index_triple_array:
+ private boost::noncopyable {
+
+ typedef index_triple_array<V1, V2, V3> self_type;
+ public:
+ typedef typename V1::value_type value1_type;
+ typedef typename V2::value_type value2_type;
+ typedef typename V3::value_type value3_type;
+
+ typedef typename V1::size_type size_type;
+ typedef typename V1::difference_type difference_type;
+ typedef index_triple<self_type> value_type;
+ // There is nothing that can be referenced directly. Always return a copy of the index_triple
+ typedef value_type reference;
+ typedef const value_type const_reference;
+
+ BOOST_UBLAS_INLINE
+ index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) :
+ size_(size),data1_(data1),data2_(data2),data3_(data3) {}
+
+ BOOST_UBLAS_INLINE
+ size_type size() const {
+ return size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return value_type((*this), i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return value_type((*this), i);
+ }
+
+ typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
+ typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
+
+ BOOST_UBLAS_INLINE
+ iterator begin() {
+ return iterator( (*this), 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end() {
+ return iterator( (*this), size());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin() const {
+ return const_iterator( (*this), 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end() const {
+ return const_iterator( (*this), size());
+ }
+
+ // unnecessary function:
+ BOOST_UBLAS_INLINE
+ bool equal(size_type i1, size_type i2) const {
+ return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2]));
+ }
+ BOOST_UBLAS_INLINE
+ bool less(size_type i1, size_type i2) const {
+ return ((data1_[i1] < data1_[i2]) ||
+ (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2]));
+ }
+
+ // gives a large speedup
+ BOOST_UBLAS_INLINE
+ friend void iter_swap(const iterator& lhs, const iterator& rhs) {
+ const size_type i1 = lhs.index();
+ const size_type i2 = rhs.index();
+ std::swap(lhs().data1_[i1], rhs().data1_[i2]);
+ std::swap(lhs().data2_[i1], rhs().data2_[i2]);
+ std::swap(lhs().data3_[i1], rhs().data3_[i2]);
+ }
+
+ private:
+ size_type size_;
+ V1& data1_;
+ V2& data2_;
+ V3& data3_;
+
+ // friend class value_type;
+ friend class index_triple<self_type>;
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_STORAGE_SPARSE_
+#define _BOOST_UBLAS_STORAGE_SPARSE_
+
+#include <map>
+#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/map.hpp>
+#include <boost/serialization/base_object.hpp>
+
+#include <boost/numeric/ublas/storage.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+ template<class I, class T, class C>
+ BOOST_UBLAS_INLINE
+ I lower_bound (const I &begin, const I &end, const T &t, C compare) {
+ // t <= *begin <=> ! (*begin < t)
+ if (begin == end || ! compare (*begin, t))
+ return begin;
+ if (compare (*(end - 1), t))
+ return end;
+ return std::lower_bound (begin, end, t, compare);
+ }
+ template<class I, class T, class C>
+ BOOST_UBLAS_INLINE
+ I upper_bound (const I &begin, const I &end, const T &t, C compare) {
+ if (begin == end || compare (t, *begin))
+ return begin;
+ // (*end - 1) <= t <=> ! (t < *end)
+ if (! compare (t, *(end - 1)))
+ return end;
+ return std::upper_bound (begin, end, t, compare);
+ }
+
+ template<class P>
+ struct less_pair {
+ BOOST_UBLAS_INLINE
+ bool operator () (const P &p1, const P &p2) {
+ return p1.first < p2.first;
+ }
+ };
+ template<class T>
+ struct less_triple {
+ BOOST_UBLAS_INLINE
+ bool operator () (const T &t1, const T &t2) {
+ return t1.first.first < t2.first.first ||
+ (t1.first.first == t2.first.first && t1.first.second < t2.first.second);
+ }
+ };
+
+ }
+
+#ifdef BOOST_UBLAS_STRICT_MAP_ARRAY
+ template<class A>
+ class sparse_storage_element:
+ public container_reference<A> {
+ public:
+ typedef A array_type;
+ typedef typename A::key_type index_type;
+ typedef typename A::mapped_type data_value_type;
+ // typedef const data_value_type &data_const_reference;
+ typedef typename type_traits<data_value_type>::const_reference data_const_reference;
+ typedef data_value_type &data_reference;
+ typedef typename A::value_type value_type;
+ typedef value_type *pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ sparse_storage_element (array_type &a, pointer it):
+ container_reference<array_type> (a), it_ (it), i_ (it->first), d_ (it->second), dirty_ (false) {}
+ BOOST_UBLAS_INLINE
+ sparse_storage_element (array_type &a, index_type i):
+ container_reference<array_type> (a), it_ (), i_ (i), d_ (), dirty_ (false) {
+ pointer it = (*this) ().find (i_);
+ if (it == (*this) ().end ())
+ it = (*this) ().insert ((*this) ().end (), value_type (i_, d_));
+ d_ = it->second;
+ }
+ BOOST_UBLAS_INLINE
+ ~sparse_storage_element () {
+ if (dirty_) {
+ if (! it_)
+ it_ = (*this) ().find (i_);
+ BOOST_UBLAS_CHECK (it_ != (*this) ().end (), internal_logic ());
+ it_->second = d_;
+ }
+ }
+
+ // Element access - only if data_const_reference is defined
+ BOOST_UBLAS_INLINE
+ typename data_value_type::data_const_reference
+ operator [] (index_type i) const {
+ return d_ [i];
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator = (const sparse_storage_element &p) {
+ // Overide the implict copy assignment
+ d_ = p.d_;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator = (const D &d) {
+ d_ = d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator += (const D &d) {
+ d_ += d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator -= (const D &d) {
+ d_ -= d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator *= (const D &d) {
+ d_ *= d;
+ dirty_ = true;
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_storage_element &operator /= (const D &d) {
+ d_ /= d;
+ dirty_ = true;
+ return *this;
+ }
+
+ // Comparison
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator == (const D &d) const {
+ return d_ == d;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator != (const D &d) const {
+ return d_ != d;
+ }
+
+ // Conversion
+ BOOST_UBLAS_INLINE
+ operator data_const_reference () const {
+ return d_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (sparse_storage_element p) {
+ if (this != &p) {
+ dirty_ = true;
+ p.dirty_ = true;
+ std::swap (d_, p.d_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (sparse_storage_element p1, sparse_storage_element p2) {
+ p1.swap (p2);
+ }
+
+ private:
+ pointer it_;
+ index_type i_;
+ data_value_type d_;
+ bool dirty_;
+ };
+#endif
+
+
+ // Default map type is simply forwarded to std::map
+ // FIXME should use ALLOC for map but std::allocator of std::pair<const I, T> and std::pair<I,T> fail to compile
+ template<class I, class T, class ALLOC>
+ class map_std : public std::map<I, T /*, ALLOC */> {
+ public:
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ ar & serialization::make_nvp("base", boost::serialization::base_object< std::map<I, T /*, ALLOC */> >(*this));
+ }
+ };
+
+
+
+
+ // Map array
+ // Implementation requires pair<I, T> allocator definition (without const)
+ template<class I, class T, class ALLOC>
+ class map_array {
+ public:
+ typedef ALLOC allocator_type;
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef std::pair<I,T> value_type;
+ typedef I key_type;
+ typedef T mapped_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef const value_type *const_pointer;
+ typedef value_type *pointer;
+ // Iterators simply are pointers.
+ typedef const_pointer const_iterator;
+ typedef pointer iterator;
+
+ typedef const T &data_const_reference;
+#ifndef BOOST_UBLAS_STRICT_MAP_ARRAY
+ typedef T &data_reference;
+#else
+ typedef sparse_storage_element<map_array> data_reference;
+#endif
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ map_array (const ALLOC &a = ALLOC()):
+ alloc_(a), capacity_ (0), size_ (0) {
+ data_ = 0;
+ }
+ BOOST_UBLAS_INLINE
+ map_array (const map_array &c):
+ alloc_ (c.alloc_), capacity_ (c.size_), size_ (c.size_) {
+ if (capacity_) {
+ data_ = alloc_.allocate (capacity_);
+ std::uninitialized_copy (data_, data_ + capacity_, c.data_);
+ // capacity != size_ requires uninitialized_fill (size_ to capacity_)
+ }
+ else
+ data_ = 0;
+ }
+ BOOST_UBLAS_INLINE
+ ~map_array () {
+ if (capacity_) {
+ std::for_each (data_, data_ + capacity_, static_destroy);
+ alloc_.deallocate (data_, capacity_);
+ }
+ }
+
+ private:
+ // Resizing - implicitly exposses uninitialized (but default constructed) mapped_type
+ BOOST_UBLAS_INLINE
+ void resize (size_type size) {
+ BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
+ if (size > capacity_) {
+ const size_type capacity = size << 1;
+ BOOST_UBLAS_CHECK (capacity, internal_logic ());
+ pointer data = alloc_.allocate (capacity);
+ std::uninitialized_copy (data_, data_ + (std::min) (size, size_), data);
+ std::uninitialized_fill (data + (std::min) (size, size_), data + capacity, value_type ());
+
+ if (capacity_) {
+ std::for_each (data_, data_ + capacity_, static_destroy);
+ alloc_.deallocate (data_, capacity_);
+ }
+ capacity_ = capacity;
+ data_ = data;
+ }
+ size_ = size;
+ BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
+ }
+ public:
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type capacity) {
+ BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
+ // Reduce capacity_ if size_ allows
+ BOOST_UBLAS_CHECK (capacity >= size_, bad_size ());
+ pointer data;
+ if (capacity) {
+ data = alloc_.allocate (capacity);
+ std::uninitialized_copy (data_, data_ + size_, data);
+ std::uninitialized_fill (data + size_, data + capacity, value_type ());
+ }
+ else
+ data = 0;
+
+ if (capacity_) {
+ std::for_each (data_, data_ + capacity_, static_destroy);
+ alloc_.deallocate (data_, capacity_);
+ }
+ capacity_ = capacity;
+ data_ = data;
+ BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
+ }
+
+ // Random Access Container
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type capacity () const {
+ return capacity_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type max_size () const {
+ return 0; //TODO
+ }
+
+ BOOST_UBLAS_INLINE
+ bool empty () const {
+ return size_ == 0;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ data_reference operator [] (key_type i) {
+#ifndef BOOST_UBLAS_STRICT_MAP_ARRAY
+ pointer it = find (i);
+ if (it == end ())
+ it = insert (end (), value_type (i, mapped_type (0)));
+ BOOST_UBLAS_CHECK (it != end (), internal_logic ());
+ return it->second;
+#else
+ return data_reference (*this, i);
+#endif
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ map_array &operator = (const map_array &a) {
+ if (this != &a) {
+ resize (a.size_);
+ std::copy (a.data_, a.data_ + a.size_, data_);
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ map_array &assign_temporary (map_array &a) {
+ swap (a);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (map_array &a) {
+ if (this != &a) {
+ std::swap (capacity_, a.capacity_);
+ std::swap (data_, a.data_);
+ std::swap (size_, a.size_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (map_array &a1, map_array &a2) {
+ a1.swap (a2);
+ }
+
+ // Element insertion and deletion
+
+ // From Back Insertion Sequence concept
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator push_back (iterator it, const value_type &p) {
+ if (size () == 0 || (it = end () - 1)->first < p.first) {
+ resize (size () + 1);
+ *(it = end () - 1) = p;
+ return it;
+ }
+ external_logic ().raise ();
+ return it;
+ }
+ // Form Unique Associative Container concept
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ std::pair<iterator,bool> insert (const value_type &p) {
+ iterator it = detail::lower_bound (begin (), end (), p, detail::less_pair<value_type> ());
+ if (it != end () && it->first == p.first)
+ return std::make_pair (it, false);
+ difference_type n = it - begin ();
+ resize (size () + 1);
+ it = begin () + n; // allow for invalidation
+ std::copy_backward (it, end () - 1, end ());
+ *it = p;
+ return std::make_pair (it, true);
+ }
+ // Form Sorted Associative Container concept
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator insert (iterator hint, const value_type &p) {
+ return insert (p).first;
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void erase (iterator it) {
+ BOOST_UBLAS_CHECK (begin () <= it && it < end (), bad_index ());
+ std::copy (it + 1, end (), it);
+ resize (size () - 1);
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void erase (iterator it1, iterator it2) {
+ if (it1 == it2) return /* nothing to erase */;
+ BOOST_UBLAS_CHECK (begin () <= it1 && it1 < it2 && it2 <= end (), bad_index ());
+ std::copy (it2, end (), it1);
+ resize (size () - (it2 - it1));
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ void clear () {
+ resize (0);
+ }
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator find (key_type i) const {
+ const_iterator it (detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ()));
+ if (it == end () || it->first != i)
+ it = end ();
+ return it;
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator find (key_type i) {
+ iterator it (detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ()));
+ if (it == end () || it->first != i)
+ it = end ();
+ return it;
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator lower_bound (key_type i) const {
+ return detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ());
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator lower_bound (key_type i) {
+ return detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return data_ + size_;
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return data_ + size_;
+ }
+
+ // Reverse iterators
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Allocator
+ allocator_type get_allocator () {
+ return alloc_;
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ resize(s);
+ }
+ ar & serialization::make_array(data_, s);
+ }
+
+ private:
+ // Provide destroy as a non member function
+ BOOST_UBLAS_INLINE
+ static void static_destroy (reference p) {
+ (&p) -> ~value_type ();
+ }
+ ALLOC alloc_;
+ size_type capacity_;
+ pointer data_;
+ size_type size_;
+ };
+
+
+ namespace detail {
+ template<class A, class T>
+ struct map_traits {
+ typedef typename A::mapped_type &reference;
+ };
+ template<class I, class T, class ALLOC>
+ struct map_traits<map_array<I, T, ALLOC>, T > {
+ typedef typename map_array<I, T, ALLOC>::data_reference reference;
+ };
+
+ // reserve helpers for map_array and generic maps
+ // ISSUE should be in map_traits but want to use on all compilers
+
+ template<class M>
+ BOOST_UBLAS_INLINE
+ void map_reserve (M &/* m */, typename M::size_type /* capacity */) {
+ }
+ template<class I, class T, class ALLOC>
+ BOOST_UBLAS_INLINE
+ void map_reserve (map_array<I, T, ALLOC> &m, typename map_array<I, T, ALLOC>::size_type capacity) {
+ m.reserve (capacity);
+ }
+
+ template<class M>
+ struct map_capacity_traits {
+ typedef typename M::size_type type ;
+ type operator() ( M const& m ) const {
+ return m.size ();
+ }
+ } ;
+
+ template<class I, class T, class ALLOC>
+ struct map_capacity_traits< map_array<I, T, ALLOC> > {
+ typedef typename map_array<I, T, ALLOC>::size_type type ;
+ type operator() ( map_array<I, T, ALLOC> const& m ) const {
+ return m.capacity ();
+ }
+ } ;
+
+ template<class M>
+ BOOST_UBLAS_INLINE
+ typename map_capacity_traits<M>::type map_capacity (M const& m) {
+ return map_capacity_traits<M>() ( m );
+ }
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_SYMMETRIC_
+#define _BOOST_UBLAS_SYMMETRIC_
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/triangular.hpp>
+#include <boost/numeric/ublas/detail/temporary.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+// Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this.
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class M>
+ bool is_symmetric (const M &m) {
+ typedef typename M::size_type size_type;
+
+ if (m.size1 () != m.size2 ())
+ return false;
+ size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
+ for (size_type i = 0; i < size; ++ i) {
+ for (size_type j = i; j < size; ++ j) {
+ if (m (i, j) != m (j, i))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Array based symmetric matrix class
+ template<class T, class TRI, class L, class A>
+ class symmetric_matrix:
+ public matrix_container<symmetric_matrix<T, TRI, L, A> > {
+
+ typedef T *pointer;
+ typedef TRI triangular_type;
+ typedef L layout_type;
+ typedef symmetric_matrix<T, TRI, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef A array_type;
+
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, A> vector_temporary_type;
+ typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
+ typedef packed_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ symmetric_matrix ():
+ matrix_container<self_type> (),
+ size_ (0), data_ (0) {}
+ BOOST_UBLAS_INLINE
+ symmetric_matrix (size_type size):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
+ }
+ BOOST_UBLAS_INLINE
+ symmetric_matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
+ }
+ BOOST_UBLAS_INLINE
+ symmetric_matrix (size_type size, const array_type &data):
+ matrix_container<self_type> (),
+ size_ (size), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ symmetric_matrix (const symmetric_matrix &m):
+ matrix_container<self_type> (),
+ size_ (m.size_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix (const matrix_expression<AE> &ae):
+ matrix_container<self_type> (),
+ size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
+ data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ if (preserve) {
+ self_type temporary (size, size);
+ detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
+ }
+ else {
+ data ().resize (triangular_type::packed_size (layout_type (), size, size));
+ size_ = size;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ resize (BOOST_UBLAS_SAME (size1, size2), preserve);
+ }
+ BOOST_UBLAS_INLINE
+ void resize_packed_preserve (size_type size) {
+ size_ = BOOST_UBLAS_SAME (size, size);
+ data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ if (triangular_type::other (i, j))
+ return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
+ else
+ return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size_, bad_index ());
+ if (triangular_type::other (i, j))
+ return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
+ else
+ return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (operator () (i, j) = t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ operator () (i, j) = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ // data ().clear ();
+ std::fill (data ().begin (), data ().end (), value_type/*zero*/());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &operator = (const symmetric_matrix &m) {
+ size_ = m.size_;
+ data () = m.data ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &assign_temporary (symmetric_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ symmetric_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (symmetric_matrix &m) {
+ if (this != &m) {
+ std::swap (size_, m.size_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
+ return const_iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
+ if (rank == 0)
+ i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
+ return iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
+ return const_iterator2 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
+ if (rank == 0)
+ j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
+ return iterator2 (*this, i, j);
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<symmetric_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename symmetric_matrix::value_type value_type;
+ typedef typename symmetric_matrix::difference_type difference_type;
+ typedef typename symmetric_matrix::const_reference reference;
+ typedef const typename symmetric_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<symmetric_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename symmetric_matrix::value_type value_type;
+ typedef typename symmetric_matrix::difference_type difference_type;
+ typedef typename symmetric_matrix::reference reference;
+ typedef typename symmetric_matrix::pointer pointer;
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<symmetric_matrix>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename symmetric_matrix::value_type value_type;
+ typedef typename symmetric_matrix::difference_type difference_type;
+ typedef typename symmetric_matrix::const_reference reference;
+ typedef const typename symmetric_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<symmetric_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename symmetric_matrix::value_type value_type;
+ typedef typename symmetric_matrix::difference_type difference_type;
+ typedef typename symmetric_matrix::reference reference;
+ typedef typename symmetric_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ };
+
+
+ // Symmetric matrix adaptor class
+ template<class M, class TRI>
+ class symmetric_adaptor:
+ public matrix_expression<symmetric_adaptor<M, TRI> > {
+
+ typedef symmetric_adaptor<M, TRI> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef const M const_matrix_type;
+ typedef M matrix_type;
+ typedef TRI triangular_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ // Replaced by _temporary_traits to avoid type requirements on M
+ //typedef typename M::vector_temporary_type vector_temporary_type;
+ //typedef typename M::matrix_temporary_type matrix_temporary_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ packed_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor (matrix_type &data):
+ matrix_expression<self_type> (),
+ data_ (data) {
+ BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
+ }
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor (const symmetric_adaptor &m):
+ matrix_expression<self_type> (),
+ data_ (m.data_) {
+ BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return data_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return data_.size2 ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else
+ return data () (j, i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else
+ return data () (j, i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else
+ return data () (j, i);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &operator = (const symmetric_adaptor &m) {
+ matrix_assign<scalar_assign, triangular_type> (*this, m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
+ *this = m;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ symmetric_adaptor& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const symmetric_adaptor &sa) const {
+ return (*this).data ().same_closure (sa.data ());
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (symmetric_adaptor &m) {
+ if (this != &m)
+ matrix_swap<scalar_swap, triangular_type> (*this, m);
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ // Use matrix iterator
+ typedef typename M::const_iterator1 const_subiterator1_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator1_type;
+ typedef typename M::const_iterator2 const_subiterator2_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (triangular_type::other (i, j)) {
+ if (triangular_type::other (size1 (), j)) {
+ return const_iterator1 (*this, 0, 0,
+ data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
+ data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
+ } else {
+ return const_iterator1 (*this, 0, 1,
+ data ().find1 (rank, i, j), data ().find1 (rank, j, j),
+ data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
+ }
+ } else {
+ if (triangular_type::other (size1 (), j)) {
+ return const_iterator1 (*this, 1, 0,
+ data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
+ data ().find2 (rank, j, i), data ().find2 (rank, j, j));
+ } else {
+ return const_iterator1 (*this, 1, 1,
+ data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
+ data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
+ }
+ }
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
+ return iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (triangular_type::other (i, j)) {
+ if (triangular_type::other (i, size2 ())) {
+ return const_iterator2 (*this, 1, 1,
+ data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
+ data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
+ } else {
+ return const_iterator2 (*this, 1, 0,
+ data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
+ data ().find2 (rank, i, j), data ().find2 (rank, i, i));
+ }
+ } else {
+ if (triangular_type::other (i, size2 ())) {
+ return const_iterator2 (*this, 0, 1,
+ data ().find1 (rank, j, i), data ().find1 (rank, i, i),
+ data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
+ } else {
+ return const_iterator2 (*this, 0, 0,
+ data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
+ data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
+ }
+ }
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
+ return iterator2 (*this, data ().find2 (rank, i, j));
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<symmetric_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
+ const_iterator1, value_type> {
+ public:
+ typedef typename const_subiterator1_type::value_type value_type;
+ typedef typename const_subiterator1_type::difference_type difference_type;
+ typedef typename const_subiterator1_type::reference reference;
+ typedef typename const_subiterator1_type::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (),
+ begin_ (-1), end_ (-1), current_ (-1),
+ it1_begin_ (), it1_end_ (), it1_ (),
+ it2_begin_ (), it2_end_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int begin, int end,
+ const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
+ const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
+ container_const_reference<self_type> (m),
+ begin_ (begin), end_ (end), current_ (begin),
+ it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
+ it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
+ if (current_ == 0 && it1_ == it1_end_)
+ current_ = 1;
+ if (current_ == 1 && it2_ == it2_end_)
+ current_ = 0;
+ if ((current_ == 0 && it1_ == it1_end_) ||
+ (current_ == 1 && it2_ == it2_end_))
+ current_ = end_;
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+ // FIXME cannot compile
+ // iterator1 does not have these members!
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()),
+ begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
+ it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
+ it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ ++ it1_;
+ if (it1_ == it1_end_ && end_ == 1) {
+ it2_ = it2_begin_;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ ++ it2_;
+ if (it2_ == it2_end_ && end_ == 0) {
+ it1_ = it1_begin_;
+ current_ = 0;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ if (it1_ == it1_begin_ && begin_ == 1) {
+ it2_ = it2_end_;
+ BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
+ -- it2_;
+ current_ = 1;
+ } else {
+ -- it1_;
+ }
+ } else /* if (current_ == 1) */ {
+ if (it2_ == it2_begin_ && begin_ == 0) {
+ it1_ = it1_end_;
+ BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
+ -- it1_;
+ current_ = 0;
+ } else {
+ -- it2_;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_end_ - it1_);
+ it1_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_begin_ + d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_end_ - it2_);
+ it2_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_begin_ + d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_ - it1_begin_);
+ it1_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_end_ - d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_ - it2_begin_);
+ it2_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_end_ - d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ if (current_ == 0 && it.current_ == 0) {
+ return it1_ - it.it1_;
+ } else if (current_ == 0 && it.current_ == 1) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
+ }
+
+ } else if (current_ == 1 && it.current_ == 0) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
+ }
+ }
+ /* current_ == 1 && it.current_ == 1 */ {
+ return it2_ - it.it2_;
+ }
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return *it1_;
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return *it2_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index1 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index2 ();
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index2 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index1 ();
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ begin_ = it.begin_;
+ end_ = it.end_;
+ current_ = it.current_;
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+ it1_ = it.it1_;
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
+ (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it - *this > 0;
+ }
+
+ private:
+ int begin_;
+ int end_;
+ int current_;
+ const_subiterator1_type it1_begin_;
+ const_subiterator1_type it1_end_;
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_begin_;
+ const_subiterator2_type it2_end_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<symmetric_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator1, value_type> {
+ public:
+ typedef typename subiterator1_type::value_type value_type;
+ typedef typename subiterator1_type::difference_type difference_type;
+ typedef typename subiterator1_type::reference reference;
+ typedef typename subiterator1_type::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator1_type &it1):
+ container_reference<self_type> (m), it1_ (it1) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it1_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<symmetric_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
+ const_iterator2, value_type> {
+ public:
+ typedef typename const_subiterator2_type::value_type value_type;
+ typedef typename const_subiterator2_type::difference_type difference_type;
+ typedef typename const_subiterator2_type::reference reference;
+ typedef typename const_subiterator2_type::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (),
+ begin_ (-1), end_ (-1), current_ (-1),
+ it1_begin_ (), it1_end_ (), it1_ (),
+ it2_begin_ (), it2_end_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int begin, int end,
+ const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
+ const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
+ container_const_reference<self_type> (m),
+ begin_ (begin), end_ (end), current_ (begin),
+ it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
+ it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
+ if (current_ == 0 && it1_ == it1_end_)
+ current_ = 1;
+ if (current_ == 1 && it2_ == it2_end_)
+ current_ = 0;
+ if ((current_ == 0 && it1_ == it1_end_) ||
+ (current_ == 1 && it2_ == it2_end_))
+ current_ = end_;
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+ // FIXME cannot compiler
+ // iterator2 does not have these members!
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()),
+ begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
+ it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
+ it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
+ BOOST_UBLAS_CHECK (current_ == end_ ||
+ (current_ == 0 && it1_ != it1_end_) ||
+ (current_ == 1 && it2_ != it2_end_), internal_logic ());
+ }
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ ++ it1_;
+ if (it1_ == it1_end_ && end_ == 1) {
+ it2_ = it2_begin_;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ ++ it2_;
+ if (it2_ == it2_end_ && end_ == 0) {
+ it1_ = it1_begin_;
+ current_ = 0;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ if (it1_ == it1_begin_ && begin_ == 1) {
+ it2_ = it2_end_;
+ BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
+ -- it2_;
+ current_ = 1;
+ } else {
+ -- it1_;
+ }
+ } else /* if (current_ == 1) */ {
+ if (it2_ == it2_begin_ && begin_ == 0) {
+ it1_ = it1_end_;
+ BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
+ -- it1_;
+ current_ = 0;
+ } else {
+ -- it2_;
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_end_ - it1_);
+ it1_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_begin_ + d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_end_ - it2_);
+ it2_ += d;
+ n -= d;
+ if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_begin_ + d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ size_type d = (std::min) (n, it1_ - it1_begin_);
+ it1_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
+ d = (std::min) (n, it2_end_ - it2_begin_);
+ it2_ = it2_end_ - d;
+ n -= d;
+ current_ = 1;
+ }
+ } else /* if (current_ == 1) */ {
+ size_type d = (std::min) (n, it2_ - it2_begin_);
+ it2_ -= d;
+ n -= d;
+ if (n > 0) {
+ BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
+ d = (std::min) (n, it1_end_ - it1_begin_);
+ it1_ = it1_end_ - d;
+ n -= d;
+ current_ = 0;
+ }
+ }
+ BOOST_UBLAS_CHECK (n == 0, external_logic ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ if (current_ == 0 && it.current_ == 0) {
+ return it1_ - it.it1_;
+ } else if (current_ == 0 && it.current_ == 1) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
+ }
+
+ } else if (current_ == 1 && it.current_ == 0) {
+ if (end_ == 1 && it.end_ == 1) {
+ return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
+ } else /* if (end_ == 0 && it.end_ == 0) */ {
+ return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
+ }
+ }
+ /* current_ == 1 && it.current_ == 1 */ {
+ return it2_ - it.it2_;
+ }
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return *it1_;
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return *it2_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index2 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index1 ();
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ if (current_ == 0) {
+ BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
+ return it1_.index1 ();
+ } else /* if (current_ == 1) */ {
+ BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
+ return it2_.index2 ();
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ begin_ = it.begin_;
+ end_ = it.end_;
+ current_ = it.current_;
+ it1_begin_ = it.it1_begin_;
+ it1_end_ = it.it1_end_;
+ it1_ = it.it1_;
+ it2_begin_ = it.it2_begin_;
+ it2_end_ = it.it2_end_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
+ BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
+ return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
+ (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it - *this > 0;
+ }
+
+ private:
+ int begin_;
+ int end_;
+ int current_;
+ const_subiterator1_type it1_begin_;
+ const_subiterator1_type it1_end_;
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_begin_;
+ const_subiterator2_type it2_end_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<symmetric_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator2, value_type> {
+ public:
+ typedef typename subiterator2_type::value_type value_type;
+ typedef typename subiterator2_type::difference_type difference_type;
+ typedef typename subiterator2_type::reference reference;
+ typedef typename subiterator2_type::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator2_type &it2):
+ container_reference<self_type> (m), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return *it2_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ };
+
+ // Specialization for temporary_traits
+ template <class M, class TRI>
+ struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
+ : vector_temporary_traits< M > {} ;
+ template <class M, class TRI>
+ struct vector_temporary_traits< const symmetric_adaptor<M, TRI> >
+ : vector_temporary_traits< M > {} ;
+
+ template <class M, class TRI>
+ struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
+ : matrix_temporary_traits< M > {} ;
+ template <class M, class TRI>
+ struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> >
+ : matrix_temporary_traits< M > {} ;
+
+}}}
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file tags.hpp
+ *
+ * \brief Tags.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_TAG_HPP
+#define BOOST_NUMERIC_UBLAS_TAG_HPP
+
+
+namespace boost { namespace numeric { namespace ublas { namespace tag {
+
+/// \brief Tag for the major dimension.
+struct major {};
+
+
+/// \brief Tag for the minor dimension.
+struct minor {};
+
+
+/// \brief Tag for the leading dimension.
+struct leading {};
+
+}}}} // Namespace boost::numeric::ublas::tag
+
+
+#endif // BOOST_NUMERIC_UBLAS_TAG_HPP
--- /dev/null
+//
+// 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_TRAITS_
+#define _BOOST_UBLAS_TRAITS_
+
+#include <iterator>
+#include <complex>
+#include <boost/config/no_tr1/cmath.hpp>
+
+#include <boost/numeric/ublas/detail/config.hpp>
+#include <boost/numeric/ublas/detail/iterator.hpp>
+#include <boost/numeric/ublas/detail/returntype_deduction.hpp>
+
+#include <boost/type_traits.hpp>
+#include <complex>
+#include <boost/typeof/typeof.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_float.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/mpl/and.hpp>
+
+// anonymous namespace to avoid ADL issues
+namespace {
+ template<class T> T boost_numeric_ublas_sqrt (const T& t) {
+ using namespace std;
+ // 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;
+ // we'll find either std::abs or else another version via ADL:
+ return abs (t);
+ }
+}
+
+namespace boost { namespace numeric { namespace ublas {
+
+ // Use Joel de Guzman's return type deduction
+ // uBLAS assumes a common return type for all binary arithmetic operators
+ template<class X, class Y>
+ struct promote_traits {
+ typedef type_deduction_detail::base_result_of<X, Y> base_type;
+ static typename base_type::x_type x;
+ static typename base_type::y_type y;
+ static const std::size_t size = sizeof (
+ type_deduction_detail::test<
+ typename base_type::x_type
+ , typename base_type::y_type
+ >(x + y) // Use x+y to stand of all the arithmetic actions
+ );
+
+ static const std::size_t index = (size / sizeof (char)) - 1;
+ typedef typename mpl::at_c<
+ typename base_type::types, index>::type id;
+ 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
+ template<class T>
+ struct type_traits;
+
+ // Define properties for a generic scalar type
+ template<class T>
+ struct scalar_traits {
+ typedef scalar_traits<T> self_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+
+ typedef T real_type;
+ typedef real_type precision_type; // we do not know what type has more precision then the real_type
+
+ static const unsigned plus_complexity = 1;
+ static const unsigned multiplies_complexity = 1;
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type real (const_reference t) {
+ return t;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type imag (const_reference /*t*/) {
+ return 0;
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type conj (const_reference t) {
+ return t;
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type type_abs (const_reference t) {
+ return boost_numeric_ublas_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type type_sqrt (const_reference t) {
+ // force a type conversion back to value_type for intgral types
+ return value_type (boost_numeric_ublas_sqrt (t));
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_1 (const_reference t) {
+ return self_type::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_2 (const_reference t) {
+ return self_type::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_inf (const_reference t) {
+ return self_type::type_abs (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool equals (const_reference t1, const_reference t2) {
+ return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
+ (std::max) ((std::max) (self_type::norm_inf (t1),
+ self_type::norm_inf (t2)),
+ BOOST_UBLAS_TYPE_CHECK_MIN);
+ }
+ };
+
+ // Define default type traits, assume T is a scalar type
+ template<class T>
+ struct type_traits : scalar_traits <T> {
+ typedef type_traits<T> self_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+
+ typedef T real_type;
+ typedef real_type precision_type;
+ static const unsigned multiplies_complexity = 1;
+
+ };
+
+ // Define real type traits
+ template<>
+ struct type_traits<float> : scalar_traits<float> {
+ typedef type_traits<float> self_type;
+ typedef float value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef double precision_type;
+ };
+ template<>
+ struct type_traits<double> : scalar_traits<double> {
+ typedef type_traits<double> self_type;
+ typedef double value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef long double precision_type;
+ };
+ template<>
+ struct type_traits<long double> : scalar_traits<long double> {
+ typedef type_traits<long double> self_type;
+ typedef long double value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef value_type precision_type;
+ };
+
+ // Define properties for a generic complex type
+ template<class T>
+ struct complex_traits {
+ typedef complex_traits<T> self_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+
+ typedef typename T::value_type real_type;
+ typedef real_type precision_type; // we do not know what type has more precision then the real_type
+
+ static const unsigned plus_complexity = 2;
+ static const unsigned multiplies_complexity = 6;
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type real (const_reference t) {
+ return std::real (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type imag (const_reference t) {
+ return std::imag (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type conj (const_reference t) {
+ return std::conj (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type type_abs (const_reference t) {
+ return abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type type_sqrt (const_reference t) {
+ return sqrt (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_1 (const_reference t) {
+ return self_type::type_abs (t);
+ // original computation has been replaced because a complex number should behave like a scalar type
+ // return type_traits<real_type>::type_abs (self_type::real (t)) +
+ // type_traits<real_type>::type_abs (self_type::imag (t));
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_2 (const_reference t) {
+ return self_type::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_inf (const_reference t) {
+ return self_type::type_abs (t);
+ // original computation has been replaced because a complex number should behave like a scalar type
+ // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
+ // type_traits<real_type>::type_abs (self_type::imag (t)));
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool equals (const_reference t1, const_reference t2) {
+ return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
+ (std::max) ((std::max) (self_type::norm_inf (t1),
+ self_type::norm_inf (t2)),
+ BOOST_UBLAS_TYPE_CHECK_MIN);
+ }
+ };
+
+ // Define complex type traits
+ template<>
+ struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
+ typedef type_traits<std::complex<float> > self_type;
+ typedef std::complex<float> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef float real_type;
+ typedef std::complex<double> precision_type;
+
+ };
+ template<>
+ struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
+ typedef type_traits<std::complex<double> > self_type;
+ typedef std::complex<double> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef double real_type;
+ typedef std::complex<long double> precision_type;
+ };
+ template<>
+ struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
+ typedef type_traits<std::complex<long double> > self_type;
+ typedef std::complex<long double> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef long double real_type;
+ typedef value_type precision_type;
+ };
+
+#ifdef BOOST_UBLAS_USE_INTERVAL
+ // Define scalar interval type traits
+ template<>
+ struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
+ typedef type_traits<boost::numeric::interval<float> > self_type;
+ typedef boost::numeric::interval<float> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef boost::numeric::interval<double> precision_type;
+
+ };
+ template<>
+ struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
+ typedef type_traits<boost::numeric::interval<double> > self_type;
+ typedef boost::numeric::interval<double> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef boost::numeric::interval<long double> precision_type;
+ };
+ template<>
+ struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
+ typedef type_traits<boost::numeric::interval<long double> > self_type;
+ typedef boost::numeric::interval<long double> value_type;
+ typedef const value_type &const_reference;
+ typedef value_type &reference;
+ typedef value_type real_type;
+ typedef value_type precision_type;
+ };
+#endif
+
+
+ // Storage tags -- hierarchical definition of storage characteristics
+
+ struct unknown_storage_tag {};
+ struct sparse_proxy_tag: public unknown_storage_tag {};
+ struct sparse_tag: public sparse_proxy_tag {};
+ struct packed_proxy_tag: public sparse_proxy_tag {};
+ struct packed_tag: public packed_proxy_tag {};
+ struct dense_proxy_tag: public packed_proxy_tag {};
+ struct dense_tag: public dense_proxy_tag {};
+
+ template<class S1, class S2>
+ struct storage_restrict_traits {
+ typedef S1 storage_category;
+ };
+
+ template<>
+ struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
+ typedef dense_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+ template<>
+ struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
+ typedef packed_proxy_tag storage_category;
+ };
+ template<>
+ struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
+ typedef sparse_proxy_tag storage_category;
+ };
+
+
+ // Iterator tags -- hierarchical definition of storage characteristics
+
+ struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
+ struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
+ struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
+
+ // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
+ template<class IC>
+ struct iterator_base_traits {};
+
+ template<>
+ struct iterator_base_traits<std::forward_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
+ };
+ };
+
+ template<>
+ struct iterator_base_traits<std::bidirectional_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
+ };
+ };
+ template<>
+ struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
+ };
+ };
+
+ template<>
+ struct iterator_base_traits<std::random_access_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
+ };
+ };
+ template<>
+ struct iterator_base_traits<packed_random_access_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
+ };
+ };
+ template<>
+ struct iterator_base_traits<dense_random_access_iterator_tag> {
+ template<class I, class T>
+ struct iterator_base {
+ typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
+ };
+ };
+
+ template<class I1, class I2>
+ struct iterator_restrict_traits {
+ typedef I1 iterator_category;
+ };
+
+ template<>
+ struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_bidirectional_iterator_tag iterator_category;
+ };
+ template<>
+ struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
+ typedef sparse_bidirectional_iterator_tag iterator_category;
+ };
+
+ template<>
+ struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
+ typedef sparse_bidirectional_iterator_tag iterator_category;
+ };
+ template<>
+ struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
+ typedef sparse_bidirectional_iterator_tag iterator_category;
+ };
+
+ template<>
+ struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
+ typedef packed_random_access_iterator_tag iterator_category;
+ };
+ template<>
+ struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
+ typedef packed_random_access_iterator_tag iterator_category;
+ };
+
+ template<class I>
+ BOOST_UBLAS_INLINE
+ void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
+ it += (std::min) (compare, it_end - it);
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
+ ++ it;
+ }
+ template<class I>
+ BOOST_UBLAS_INLINE
+ void increment (I &it, const I &it_end, typename I::difference_type compare) {
+ increment (it, it_end, compare, typename I::iterator_category ());
+ }
+
+ template<class I>
+ BOOST_UBLAS_INLINE
+ void increment (I &it, const I &it_end) {
+#if BOOST_UBLAS_TYPE_CHECK
+ I cit (it);
+ while (cit != it_end) {
+ BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
+ ++ cit;
+ }
+#endif
+ it = it_end;
+ }
+
+ namespace detail {
+
+ // specialisation which define whether a type has a trivial constructor
+ // or not. This is used by array types.
+ template<typename T>
+ struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
+
+ template<typename T>
+ struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
+
+ template<typename FLT>
+ struct has_trivial_constructor<std::complex<FLT> > : public boost::true_type {};
+
+ template<typename FLT>
+ struct has_trivial_destructor<std::complex<FLT> > : public boost::true_type {};
+
+ }
+
+
+ /** \brief Traits class to extract type information from a constant matrix or vector CONTAINER.
+ *
+ */
+ template < class E >
+ struct container_view_traits {
+ /// type of indices
+ typedef typename E::size_type size_type;
+ /// type of differences of indices
+ typedef typename E::difference_type difference_type;
+
+ /// storage category: \c unknown_storage_tag, \c dense_tag, \c packed_tag, ...
+ typedef typename E::storage_category storage_category;
+
+ /// type of elements
+ typedef typename E::value_type value_type;
+ /// const reference to an element
+ typedef typename E::const_reference const_reference;
+
+ /// type used in expressions to mark a reference to this class (usually a const container_reference<const E> or the class itself)
+ typedef typename E::const_closure_type const_closure_type;
+ };
+
+ /** \brief Traits class to extract additional type information from a mutable matrix or vector CONTAINER.
+ *
+ */
+ template < class E >
+ struct mutable_container_traits {
+ /// reference to an element
+ typedef typename E::reference reference;
+
+ /// type used in expressions to mark a reference to this class (usually a container_reference<E> or the class itself)
+ typedef typename E::closure_type closure_type;
+ };
+
+ /** \brief Traits class to extract type information from a matrix or vector CONTAINER.
+ *
+ */
+ template < class E >
+ struct container_traits
+ : container_view_traits<E>, mutable_container_traits<E> {
+
+ };
+
+
+ /** \brief Traits class to extract type information from a constant MATRIX.
+ *
+ */
+ template < class MATRIX >
+ struct matrix_view_traits : container_view_traits <MATRIX> {
+
+ /// orientation of the matrix, either \c row_major_tag, \c column_major_tag or \c unknown_orientation_tag
+ typedef typename MATRIX::orientation_category orientation_category;
+
+ /// row iterator for the matrix
+ typedef typename MATRIX::const_iterator1 const_iterator1;
+
+ /// column iterator for the matrix
+ typedef typename MATRIX::const_iterator2 const_iterator2;
+ };
+
+ /** \brief Traits class to extract additional type information from a mutable MATRIX.
+ *
+ */
+ template < class MATRIX >
+ struct mutable_matrix_traits
+ : mutable_container_traits <MATRIX> {
+
+ /// row iterator for the matrix
+ typedef typename MATRIX::iterator1 iterator1;
+
+ /// column iterator for the matrix
+ typedef typename MATRIX::iterator2 iterator2;
+ };
+
+
+ /** \brief Traits class to extract type information from a MATRIX.
+ *
+ */
+ template < class MATRIX >
+ struct matrix_traits
+ : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
+ };
+
+ /** \brief Traits class to extract type information from a VECTOR.
+ *
+ */
+ template < class VECTOR >
+ struct vector_view_traits : container_view_traits <VECTOR> {
+
+ /// iterator for the VECTOR
+ typedef typename VECTOR::const_iterator const_iterator;
+
+ /// iterator pointing to the first element
+ static
+ const_iterator begin(const VECTOR & v) {
+ return v.begin();
+ }
+ /// iterator pointing behind the last element
+ static
+ const_iterator end(const VECTOR & v) {
+ return v.end();
+ }
+
+ };
+
+ /** \brief Traits class to extract type information from a VECTOR.
+ *
+ */
+ template < class VECTOR >
+ struct mutable_vector_traits : mutable_container_traits <VECTOR> {
+ /// iterator for the VECTOR
+ typedef typename VECTOR::iterator iterator;
+
+ /// iterator pointing to the first element
+ static
+ iterator begin(VECTOR & v) {
+ return v.begin();
+ }
+
+ /// iterator pointing behind the last element
+ static
+ iterator end(VECTOR & v) {
+ return v.end();
+ }
+ };
+
+ /** \brief Traits class to extract type information from a VECTOR.
+ *
+ */
+ template < class VECTOR >
+ struct vector_traits
+ : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
+ };
+
+
+ // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp
+
+}}}
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file c_array.hpp
+ *
+ * \brief provides specializations of matrix and vector traits for c arrays and c matrices.
+ *
+ * Copyright (c) 2009, Gunter Winkler
+ *
+ * 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)
+ *
+ * \author Gunter Winkler (guwi17 at gmx dot de)
+ */
+
+#ifndef BOOST_NUMERIC_UBLAS_TRAITS_C_ARRAY_HPP
+#define BOOST_NUMERIC_UBLAS_TRAITS_C_ARRAY_HPP
+
+
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/numeric/ublas/traits/const_iterator_type.hpp>
+#include <boost/numeric/ublas/traits/iterator_type.hpp>
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+
+
+ }
+
+
+ template < class T, int M, int N >
+ struct matrix_view_traits < T[M][N] > {
+ typedef T matrix_type[M][N];
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef row_major_tag orientation_category;
+ typedef dense_tag storage_category;
+
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef const T *const_pointer;
+
+ typedef const matrix_reference<const matrix_type> const_closure_type;
+
+ typedef T row_type[N];
+
+ typedef const row_type *const_iterator1;
+ typedef const_pointer const_iterator2;
+
+ };
+
+ template < class T, int M, int N >
+ struct mutable_matrix_traits < T[M][N] > {
+ typedef T matrix_type[M][N];
+
+ typedef T *reference;
+
+ typedef matrix_reference<matrix_type> closure_type;
+
+ };
+
+ template < class T, int N >
+ struct vector_view_traits < T[N] > {
+ typedef T vector_type[N];
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef dense_tag storage_category;
+
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef const T *const_pointer;
+
+ typedef const vector_reference<const vector_type> const_closure_type;
+
+ typedef const_pointer const_iterator;
+
+ /// iterator pointing to the first element
+ static
+ const_iterator begin(const vector_type & v) {
+ return & (v[0]);
+ }
+ /// iterator pointing behind the last element
+ static
+ const_iterator end(const vector_type & v) {
+ return & (v[N]);
+ }
+ };
+
+ template < class T, int N >
+ struct mutable_vector_traits < T[N] > {
+
+ typedef T &reference;
+ typedef T *pointer;
+ typedef vector_reference< T[N] > closure_type;
+
+ };
+
+
+
+
+}}} // Namespace boost::numeric::ublas
+
+#endif
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file const_iterator_type.hpp
+ *
+ * \brief Const iterator to a given container type.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+
+#ifndef BOOST_NUMERIC_UBLAS_TRAITS_CONST_ITERATOR_TYPE_HPP
+#define BOOST_NUMERIC_UBLAS_TRAITS_CONST_ITERATOR_TYPE_HPP
+
+
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/tags.hpp>
+#include <boost/numeric/ublas/traits.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+ /**
+ * \brief Auxiliary class for retrieving the const iterator to the given
+ * matrix expression according its orientation and to the given dimension tag.
+ * \tparam MatrixT A model of MatrixExpression.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ * \tparam OrientationT An orientation category type (e.g., row_major_tag).
+ */
+ template <typename MatrixT, typename TagT, typename OrientationT>
+ struct const_iterator_type_impl;
+
+
+ /// \brief Specialization of \c const_iterator_type_impl for row-major oriented
+ /// matrices and over the major dimension.
+ template <typename MatrixT>
+ struct const_iterator_type_impl<MatrixT,tag::major,row_major_tag>
+ {
+ typedef typename matrix_view_traits<MatrixT>::const_iterator1 type;
+ };
+
+
+ /// \brief Specialization of \c const_iterator_type_impl for column-major
+ /// oriented matrices and over the major dimension.
+ template <typename MatrixT>
+ struct const_iterator_type_impl<MatrixT,tag::major,column_major_tag>
+ {
+ typedef typename matrix_view_traits<MatrixT>::const_iterator2 type;
+ };
+
+
+ /// \brief Specialization of \c const_iterator_type_impl for row-major oriented
+ /// matrices and over the minor dimension.
+ template <typename MatrixT>
+ struct const_iterator_type_impl<MatrixT,tag::minor,row_major_tag>
+ {
+ typedef typename matrix_view_traits<MatrixT>::const_iterator2 type;
+ };
+
+
+ /// \brief Specialization of \c const_iterator_type_impl for column-major
+ /// oriented matrices and over the minor dimension.
+ template <typename MatrixT>
+ struct const_iterator_type_impl<MatrixT,tag::minor,column_major_tag>
+ {
+ typedef typename matrix_view_traits<MatrixT>::const_iterator1 type;
+ };
+
+ } // Namespace detail
+
+
+ /**
+ * \brief A const iterator for the given container type over the given
+ * dimension.
+ * \tparam ContainerT A container expression type.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ */
+ template <typename ContainerT, typename TagT=void>
+ struct const_iterator_type;
+
+
+ /**
+ * \brief Specialization of \c const_iterator_type for vector expressions.
+ * \tparam VectorT A model of VectorExpression type.
+ */
+ template <typename VectorT>
+ struct const_iterator_type<VectorT, void>
+ {
+ typedef typename vector_view_traits<VectorT>::const_iterator type;
+ };
+
+
+ /**
+ * \brief Specialization of \c const_iterator_type for matrix expressions and
+ * over the major dimension.
+ * \tparam MatrixT A model of MatrixExpression type.
+ */
+ template <typename MatrixT>
+ struct const_iterator_type<MatrixT,tag::major>
+ {
+ typedef typename detail::const_iterator_type_impl<MatrixT,tag::minor,typename matrix_view_traits<MatrixT>::orientation_category>::type type;
+ };
+
+
+ /**
+ * \brief Specialization of \c const_iterator_type for matrix expressions and
+ * over the minor dimension.
+ * \tparam MatrixT A model of MatrixExpression type.
+ */
+ template <typename MatrixT>
+ struct const_iterator_type<MatrixT,tag::minor>
+ {
+ typedef typename detail::const_iterator_type_impl<MatrixT,tag::minor,typename matrix_view_traits<MatrixT>::orientation_category>::type type;
+ };
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_TRAITS_CONST_ITERATOR_TYPE_HPP
--- /dev/null
+/**
+ * -*- c++ -*-
+ *
+ * \file iterator_type.hpp
+ *
+ * \brief Iterator to a given container type.
+ *
+ * Copyright (c) 2009, Marco Guazzone
+ *
+ * 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)
+ *
+ * \author Marco Guazzone, marco.guazzone@gmail.com
+ */
+
+
+#ifndef BOOST_NUMERIC_UBLAS_TRAITS_ITERATOR_TYPE_HPP
+#define BOOST_NUMERIC_UBLAS_TRAITS_ITERATOR_TYPE_HPP
+
+
+#include <boost/numeric/ublas/fwd.hpp>
+#include <boost/numeric/ublas/traits.hpp>
+#include <boost/numeric/ublas/tags.hpp>
+
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+
+ /**
+ * \brief Auxiliary class for retrieving the iterator to the given
+ * matrix expression according its orientation and to the given dimension tag.
+ * \tparam MatrixT A model of MatrixExpression.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ * \tparam OrientationT An orientation category type (e.g., row_major_tag).
+ */
+ template <typename MatrixT, typename TagT, typename OrientationT>
+ struct iterator_type_impl;
+
+
+ /// \brief Specialization of \c iterator_type_impl for row-major oriented
+ /// matrices and over the major dimension.
+ template <typename MatrixT>
+ struct iterator_type_impl<MatrixT,tag::major,row_major_tag>
+ {
+ typedef typename matrix_traits<MatrixT>::iterator1 type;
+ };
+
+
+ /// \brief Specialization of \c iterator_type_impl for column-major oriented
+ /// matrices and over the major dimension.
+ template <typename MatrixT>
+ struct iterator_type_impl<MatrixT,tag::major,column_major_tag>
+ {
+ typedef typename matrix_traits<MatrixT>::iterator2 type;
+ };
+
+
+ /// \brief Specialization of \c iterator_type_impl for row-major oriented
+ /// matrices and over the minor dimension.
+ template <typename MatrixT>
+ struct iterator_type_impl<MatrixT,tag::minor,row_major_tag>
+ {
+ typedef typename matrix_traits<MatrixT>::iterator2 type;
+ };
+
+
+ /// \brief Specialization of \c iterator_type_impl for column-major oriented
+ /// matrices and over the minor dimension.
+ template <typename MatrixT>
+ struct iterator_type_impl<MatrixT,tag::minor,column_major_tag>
+ {
+ typedef typename matrix_traits<MatrixT>::iterator1 type;
+ };
+
+ } // Namespace detail
+
+
+ /**
+ * \brief A iterator for the given container type over the given dimension.
+ * \tparam ContainerT A container expression type.
+ * \tparam TagT A dimension tag type (e.g., tag::major).
+ */
+ template <typename ContainerT, typename TagT=void>
+ struct iterator_type;
+
+
+ /**
+ * \brief Specialization of \c iterator_type for vector expressions.
+ * \tparam VectorT A model of VectorExpression type.
+ */
+ template <typename VectorT>
+ struct iterator_type<VectorT, void>
+ {
+ typedef typename vector_traits<VectorT>::iterator type;
+ };
+
+
+ /**
+ * \brief Specialization of \c iterator_type for matrix expressions and
+ * over the major dimension.
+ * \tparam MatrixT A model of MatrixExpression type.
+ */
+ template <typename MatrixT>
+ struct iterator_type<MatrixT,tag::major>
+ {
+ typedef typename detail::iterator_type_impl<MatrixT,tag::major,typename matrix_traits<MatrixT>::orientation_category>::type type;
+ };
+
+
+ /**
+ * \brief Specialization of \c iterator_type for matrix expressions and
+ * over the minor dimension.
+ * \tparam MatrixT A model of MatrixExpression type.
+ */
+ template <typename MatrixT>
+ struct iterator_type<MatrixT,tag::minor>
+ {
+ typedef typename detail::iterator_type_impl<MatrixT,tag::minor,typename matrix_traits<MatrixT>::orientation_category>::type type;
+ };
+
+}}} // Namespace boost::numeric::ublas
+
+
+#endif // BOOST_NUMERIC_UBLAS_TRAITS_ITERATOR_TYPE_HPP
--- /dev/null
+//
+// 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_TRIANGULAR_
+#define _BOOST_UBLAS_TRIANGULAR_
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/detail/temporary.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ namespace detail {
+ using namespace boost::numeric::ublas;
+
+ // Matrix resizing algorithm
+ template <class L, class T, class M>
+ BOOST_UBLAS_INLINE
+ void matrix_resize_preserve (M& m, M& temporary) {
+ typedef L layout_type;
+ typedef T triangular_type;
+ typedef typename M::size_type size_type;
+ const size_type msize1 (m.size1 ()); // original size
+ const size_type msize2 (m.size2 ());
+ const size_type size1 (temporary.size1 ()); // new size is specified by temporary
+ const size_type size2 (temporary.size2 ());
+ // Common elements to preserve
+ const size_type size1_min = (std::min) (size1, msize1);
+ const size_type size2_min = (std::min) (size2, msize2);
+ // Order for major and minor sizes
+ const size_type major_size = layout_type::size_M (size1_min, size2_min);
+ const size_type minor_size = layout_type::size_m (size1_min, size2_min);
+ // Indexing copy over major
+ for (size_type major = 0; major != major_size; ++major) {
+ for (size_type minor = 0; minor != minor_size; ++minor) {
+ // find indexes - use invertability of element_ functions
+ const size_type i1 = layout_type::index_M(major, minor);
+ const size_type i2 = layout_type::index_m(major, minor);
+ if ( triangular_type::other(i1,i2) ) {
+ temporary.data () [triangular_type::element (layout_type (), i1, size1, i2, size2)] =
+ m.data() [triangular_type::element (layout_type (), i1, msize1, i2, msize2)];
+ }
+ }
+ }
+ m.assign_temporary (temporary);
+ }
+ }
+
+ /** \brief A triangular matrix of values of type \c T.
+ *
+ * For a \f$(n \times n )\f$-dimensional lower triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i>j\f$ holds,
+ * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit lower triangular.
+ *
+ * For a \f$(n \times n )\f$-dimensional upper triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i<j\f$ holds,
+ * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit upper triangular.
+ *
+ * The default storage for triangular matrices is packed. Orientation and storage can also be specified.
+ * Default is \c row_major and and unbounded_array. It is \b not required by the storage to initialize
+ * elements of the matrix.
+ *
+ * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
+ * \tparam TRI the type of the triangular matrix. It can either be \c lower or \c upper. Default is \c lower
+ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
+ * \tparam A the type of Storage array. Default is \c unbounded_array
+ */
+ template<class T, class TRI, class L, class A>
+ class triangular_matrix:
+ public matrix_container<triangular_matrix<T, TRI, L, A> > {
+
+ typedef T *pointer;
+ typedef TRI triangular_type;
+ typedef L layout_type;
+ typedef triangular_matrix<T, TRI, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef A array_type;
+
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef vector<T, A> vector_temporary_type;
+ typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
+ typedef packed_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ triangular_matrix ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ (0) {}
+ BOOST_UBLAS_INLINE
+ triangular_matrix (size_type size1, size_type size2):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
+ }
+ BOOST_UBLAS_INLINE
+ triangular_matrix (size_type size1, size_type size2, const array_type &data):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (data) {}
+ BOOST_UBLAS_INLINE
+ triangular_matrix (const triangular_matrix &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix (const matrix_expression<AE> &ae):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
+ data_ (triangular_type::packed_size (layout_type (), size1_, size2_)) {
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ if (preserve) {
+ self_type temporary (size1, size2);
+ detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
+ }
+ else {
+ data ().resize (triangular_type::packed_size (layout_type (), size1, size2));
+ size1_ = size1;
+ size2_ = size2;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void resize_packed_preserve (size_type size1, size_type size2) {
+ size1_ = size1;
+ size2_ = size2;
+ data ().resize (triangular_type::packed_size (layout_type (), size1_, size2_), value_type ());
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+ if (triangular_type::other (i, j))
+ return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
+ else if (triangular_type::one (i, j))
+ return one_;
+ else
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference at_element (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+ return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1_, bad_index ());
+ BOOST_UBLAS_CHECK (j < size2_, bad_index ());
+ if (!triangular_type::other (i, j)) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, size_type j, const_reference t) {
+ return (operator () (i, j) = t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ operator () (i, j) = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ // data ().clear ();
+ std::fill (data ().begin (), data ().end (), value_type/*zero*/());
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ triangular_matrix &operator = (const triangular_matrix &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ triangular_matrix &assign_temporary (triangular_matrix &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_matrix &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ triangular_matrix& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ triangular_matrix& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (triangular_matrix &m) {
+ if (this != &m) {
+ // BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (triangular_matrix &m1, triangular_matrix &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (rank == 1)
+ i = triangular_type::restrict1 (i, j, size1_, size2_);
+ if (rank == 0)
+ i = triangular_type::global_restrict1 (i, size1_, j, size2_);
+ return const_iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1_, size2_);
+ if (rank == 0)
+ i = triangular_type::global_mutable_restrict1 (i, size1_, j, size2_);
+ return iterator1 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (rank == 1)
+ j = triangular_type::restrict2 (i, j, size1_, size2_);
+ if (rank == 0)
+ j = triangular_type::global_restrict2 (i, size1_, j, size2_);
+ return const_iterator2 (*this, i, j);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1_, size2_);
+ if (rank == 0)
+ j = triangular_type::global_mutable_restrict2 (i, size1_, j, size2_);
+ return iterator2 (*this, i, j);
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<triangular_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename triangular_matrix::value_type value_type;
+ typedef typename triangular_matrix::difference_type difference_type;
+ typedef typename triangular_matrix::const_reference reference;
+ typedef const typename triangular_matrix::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<triangular_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename triangular_matrix::value_type value_type;
+ typedef typename triangular_matrix::difference_type difference_type;
+ typedef typename triangular_matrix::reference reference;
+ typedef typename triangular_matrix::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, it1_, 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, it1_, (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<triangular_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename triangular_matrix::value_type value_type;
+ typedef typename triangular_matrix::difference_type difference_type;
+ typedef typename triangular_matrix::const_reference reference;
+ typedef const typename triangular_matrix::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, size_type it1, size_type it2):
+ container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<triangular_matrix>,
+ public random_access_iterator_base<packed_random_access_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename triangular_matrix::value_type value_type;
+ typedef typename triangular_matrix::difference_type difference_type;
+ typedef typename triangular_matrix::reference reference;
+ typedef typename triangular_matrix::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, size_type it1, size_type it2):
+ container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ return (*this) () (it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), it2_);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ size_type it1_;
+ size_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ static const value_type zero_;
+ static const value_type one_;
+ };
+
+ template<class T, class TRI, class L, class A>
+ const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::zero_ = value_type/*zero*/();
+ template<class T, class TRI, class L, class A>
+ const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::one_ (1);
+
+
+ // Triangular matrix adaptor class
+ template<class M, class TRI>
+ class triangular_adaptor:
+ public matrix_expression<triangular_adaptor<M, TRI> > {
+
+ typedef triangular_adaptor<M, TRI> self_type;
+
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_expression<self_type>::operator ();
+#endif
+ typedef const M const_matrix_type;
+ typedef M matrix_type;
+ typedef TRI triangular_type;
+ typedef typename M::size_type size_type;
+ typedef typename M::difference_type difference_type;
+ typedef typename M::value_type value_type;
+ typedef typename M::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_reference,
+ typename M::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_closure_type,
+ typename M::closure_type>::type matrix_closure_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ // Replaced by _temporary_traits to avoid type requirements on M
+ //typedef typename M::vector_temporary_type vector_temporary_type;
+ //typedef typename M::matrix_temporary_type matrix_temporary_type;
+ typedef typename storage_restrict_traits<typename M::storage_category,
+ packed_proxy_tag>::storage_category storage_category;
+ typedef typename M::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ triangular_adaptor (matrix_type &data):
+ matrix_expression<self_type> (),
+ data_ (data) {}
+ BOOST_UBLAS_INLINE
+ triangular_adaptor (const triangular_adaptor &m):
+ matrix_expression<self_type> (),
+ data_ (m.data_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return data_.size1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return data_.size2 ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const matrix_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ matrix_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return data () (i, j);
+ else if (triangular_type::one (i, j))
+ return one_;
+ else
+ return zero_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (!triangular_type::other (i, j)) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return data () (i, j);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) const {
+ BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
+ if (!triangular_type::other (i, j)) {
+ bad_index ().raise ();
+ // NEVER reached
+ }
+ return data () (i, j);
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &operator = (const triangular_adaptor &m) {
+ matrix_assign<scalar_assign> (*this, m);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &assign_temporary (triangular_adaptor &m) {
+ *this = m;
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &operator = (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor& operator += (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor& operator -= (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ triangular_adaptor& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const triangular_adaptor &ta) const {
+ return (*this).data ().same_closure (ta.data ());
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (triangular_adaptor &m) {
+ if (this != &m)
+ matrix_swap<scalar_swap> (*this, m);
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (triangular_adaptor &m1, triangular_adaptor &m2) {
+ m1.swap (m2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename M::const_iterator1 const_subiterator1_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator1,
+ typename M::iterator1>::type subiterator1_type;
+ typedef typename M::const_iterator2 const_subiterator2_type;
+ typedef typename boost::mpl::if_<boost::is_const<M>,
+ typename M::const_iterator2,
+ typename M::iterator2>::type subiterator2_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
+ typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
+ typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
+ typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
+#else
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+#endif
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator1 find1 (int rank, size_type i, size_type j) const {
+ if (rank == 1)
+ i = triangular_type::restrict1 (i, j, size1(), size2());
+ if (rank == 0)
+ i = triangular_type::global_restrict1 (i, size1(), j, size2());
+ return const_iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 find1 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
+ if (rank == 0)
+ i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
+ return iterator1 (*this, data ().find1 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 find2 (int rank, size_type i, size_type j) const {
+ if (rank == 1)
+ j = triangular_type::restrict2 (i, j, size1(), size2());
+ if (rank == 0)
+ j = triangular_type::global_restrict2 (i, size1(), j, size2());
+ return const_iterator2 (*this, data ().find2 (rank, i, j));
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 find2 (int rank, size_type i, size_type j) {
+ if (rank == 1)
+ j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
+ if (rank == 0)
+ j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
+ return iterator2 (*this, data ().find2 (rank, i, j));
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator1:
+ public container_const_reference<triangular_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ const_iterator1, value_type> {
+ public:
+ typedef typename const_subiterator1_type::value_type value_type;
+ typedef typename const_subiterator1_type::difference_type difference_type;
+ typedef typename const_subiterator1_type::reference reference;
+ typedef typename const_subiterator1_type::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
+ container_const_reference<self_type> (m), it1_ (it1) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return *it1_;
+ else
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator1:
+ public container_reference<triangular_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator1, value_type> {
+ public:
+ typedef typename subiterator1_type::value_type value_type;
+ typedef typename subiterator1_type::difference_type difference_type;
+ typedef typename subiterator1_type::reference reference;
+ typedef typename subiterator1_type::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), it1_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, const subiterator1_type &it1):
+ container_reference<self_type> (m), it1_ (it1) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return *it1_;
+ else
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ return (*this) ().find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it1_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it1_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ subiterator1_type it1_;
+
+ friend class const_iterator1;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1 (), 0);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator2:
+ public container_const_reference<triangular_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ const_iterator2, value_type> {
+ public:
+ typedef typename const_subiterator2_type::value_type value_type;
+ typedef typename const_subiterator2_type::difference_type difference_type;
+ typedef typename const_subiterator2_type::reference reference;
+ typedef typename const_subiterator2_type::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (m), it2_ (it2) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return *it2_;
+ else
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2 ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator2:
+ public container_reference<triangular_adaptor>,
+ public random_access_iterator_base<typename iterator_restrict_traits<
+ typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
+ iterator2, value_type> {
+ public:
+ typedef typename subiterator2_type::value_type value_type;
+ typedef typename subiterator2_type::difference_type difference_type;
+ typedef typename subiterator2_type::reference reference;
+ typedef typename subiterator2_type::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, const subiterator2_type &it2):
+ container_reference<self_type> (m), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ size_type i = index1 ();
+ size_type j = index2 ();
+ BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
+ if (triangular_type::other (i, j))
+ return *it2_;
+ else
+ return (*this) () (i, j);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ return (*this) ().find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ return it2_.index1 ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ return it2_.index2 ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ subiterator2_type it2_;
+
+ friend class const_iterator2;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2 ());
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ private:
+ matrix_closure_type data_;
+ static const value_type zero_;
+ static const value_type one_;
+ };
+
+ template<class M, class TRI>
+ const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::zero_ = value_type/*zero*/();
+ template<class M, class TRI>
+ const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::one_ (1);
+
+ template <class M, class TRI>
+ struct vector_temporary_traits< triangular_adaptor<M, TRI> >
+ : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
+ template <class M, class TRI>
+ struct vector_temporary_traits< const triangular_adaptor<M, TRI> >
+ : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
+
+ template <class M, class TRI>
+ struct matrix_temporary_traits< triangular_adaptor<M, TRI> >
+ : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
+ template <class M, class TRI>
+ struct matrix_temporary_traits< const triangular_adaptor<M, TRI> >
+ : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
+
+
+ template<class E1, class E2>
+ struct matrix_vector_solve_traits {
+ typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
+ typedef vector<promote_type> result_type;
+ };
+
+ // Operations:
+ // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
+ // n * (n - 1) / 2 additions
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag, column_major_tag, dense_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (size_type m = n + 1; m < size; ++ m)
+ e2 () (m) -= e1 () (m, n) * t;
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag, column_major_tag, packed_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
+ typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
+ difference_type m (it1e1_end - it1e1);
+ while (-- m >= 0)
+ e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag, column_major_tag, unknown_storage_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
+ typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
+ while (it1e1 != it1e1_end)
+ e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ // Redirectors :-)
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag, column_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e1, e2,
+ lower_tag (), column_major_tag (), storage_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag, row_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e2, trans (e1),
+ upper_tag (), row_major_tag (), storage_category ());
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ lower_tag) {
+ typedef typename E1::orientation_category orientation_category;
+ inplace_solve (e1, e2,
+ lower_tag (), orientation_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ unit_lower_tag) {
+ typedef typename E1::orientation_category orientation_category;
+ inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
+ unit_lower_tag (), orientation_category ());
+ }
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag, column_major_tag, dense_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (difference_type m = n - 1; m >= 0; -- m)
+ e2 () (m) -= e1 () (m, n) * t;
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag, column_major_tag, packed_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
+ typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
+ difference_type m (it1e1_rend - it1e1);
+ while (-- m >= 0)
+ e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag, column_major_tag, unknown_storage_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
+ size_type size = e2 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e2 () (n) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
+ typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
+ while (it1e1 != it1e1_rend)
+ e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ // Redirectors :-)
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag, column_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e1, e2,
+ upper_tag (), column_major_tag (), storage_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag, row_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e2, trans (e1),
+ lower_tag (), row_major_tag (), storage_category ());
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ upper_tag) {
+ typedef typename E1::orientation_category orientation_category;
+ inplace_solve (e1, e2,
+ upper_tag (), orientation_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
+ unit_upper_tag) {
+ typedef typename E1::orientation_category orientation_category;
+ inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
+ unit_upper_tag (), orientation_category ());
+ }
+
+ template<class E1, class E2, class C>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_solve_traits<E1, E2>::result_type
+ solve (const matrix_expression<E1> &e1,
+ const vector_expression<E2> &e2,
+ C) {
+ typename matrix_vector_solve_traits<E1, E2>::result_type r (e2);
+ inplace_solve (e1, r, C ());
+ return r;
+ }
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag, row_major_tag, dense_proxy_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (difference_type m = n - 1; m >= 0; -- m)
+ e1 () (m) -= t * e2 () (n, m);
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag, row_major_tag, packed_proxy_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
+ typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
+ difference_type m (it2e2_rend - it2e2);
+ while (-- m >= 0)
+ e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag, row_major_tag, unknown_storage_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (difference_type n = size - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
+ typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
+ while (it2e2 != it2e2_rend)
+ e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
+ }
+ }
+ }
+ // Redirectors :-)
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag, row_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e1, e2,
+ lower_tag (), row_major_tag (), storage_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag, column_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (trans (e2), e1,
+ upper_tag (), row_major_tag (), storage_category ());
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ lower_tag) {
+ typedef typename E2::orientation_category orientation_category;
+ inplace_solve (e1, e2,
+ lower_tag (), orientation_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ unit_lower_tag) {
+ typedef typename E2::orientation_category orientation_category;
+ inplace_solve (e1, triangular_adaptor<const E2, unit_lower> (e2 ()),
+ unit_lower_tag (), orientation_category ());
+ }
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag, row_major_tag, dense_proxy_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (size_type m = n + 1; m < size; ++ m)
+ e1 () (m) -= t * e2 () (n, m);
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag, row_major_tag, packed_proxy_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
+ typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
+ difference_type m (it2e2_end - it2e2);
+ while (-- m >= 0)
+ e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag, row_major_tag, unknown_storage_tag) {
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename E1::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
+ BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
+ size_type size = e1 ().size ();
+ for (size_type n = 0; n < size; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e2 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ value_type t = e1 () (n) /= e2 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
+ typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
+ while (it2e2 != it2e2_end)
+ e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
+ }
+ }
+ }
+ // Redirectors :-)
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag, row_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (e1, e2,
+ upper_tag (), row_major_tag (), storage_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag, column_major_tag) {
+ typedef typename E1::storage_category storage_category;
+ inplace_solve (trans (e2), e1,
+ lower_tag (), row_major_tag (), storage_category ());
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ upper_tag) {
+ typedef typename E2::orientation_category orientation_category;
+ inplace_solve (e1, e2,
+ upper_tag (), orientation_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
+ unit_upper_tag) {
+ typedef typename E2::orientation_category orientation_category;
+ inplace_solve (e1, triangular_adaptor<const E2, unit_upper> (e2 ()),
+ unit_upper_tag (), orientation_category ());
+ }
+
+ template<class E1, class E2, class C>
+ BOOST_UBLAS_INLINE
+ typename matrix_vector_solve_traits<E1, E2>::result_type
+ solve (const vector_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ C) {
+ typename matrix_vector_solve_traits<E1, E2>::result_type r (e1);
+ inplace_solve (r, e2, C ());
+ return r;
+ }
+
+ template<class E1, class E2>
+ struct matrix_matrix_solve_traits {
+ typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
+ typedef matrix<promote_type> result_type;
+ };
+
+ // Operations:
+ // k * n * (n - 1) / 2 + k * n = k * n * (n + 1) / 2 multiplications,
+ // k * n * (n - 1) / 2 additions
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ lower_tag, dense_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (size_type n = 0; n < size1; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (size_type l = 0; l < size2; ++ l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (size_type m = n + 1; m < size1; ++ m)
+ e2 () (m, l) -= e1 () (m, n) * t;
+ }
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ lower_tag, packed_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (size_type n = 0; n < size1; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (size_type l = 0; l < size2; ++ l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
+ typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
+ difference_type m (it1e1_end - it1e1);
+ while (-- m >= 0)
+ e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ lower_tag, unknown_storage_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (size_type n = 0; n < size1; ++ n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (size_type l = 0; l < size2; ++ l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
+ typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
+ while (it1e1 != it1e1_end)
+ e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ lower_tag) {
+ typedef typename E1::storage_category dispatch_category;
+ inplace_solve (e1, e2,
+ lower_tag (), dispatch_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ unit_lower_tag) {
+ typedef typename E1::storage_category dispatch_category;
+ inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
+ unit_lower_tag (), dispatch_category ());
+ }
+
+ // Dense (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ upper_tag, dense_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (difference_type n = size1 - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (difference_type l = size2 - 1; l >= 0; -- l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ for (difference_type m = n - 1; m >= 0; -- m)
+ e2 () (m, l) -= e1 () (m, n) * t;
+ }
+ }
+ }
+ }
+ // Packed (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ upper_tag, packed_proxy_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (difference_type n = size1 - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (difference_type l = size2 - 1; l >= 0; -- l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
+ typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
+ difference_type m (it1e1_rend - it1e1);
+ while (-- m >= 0)
+ e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ }
+ // Sparse (proxy) case
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ upper_tag, unknown_storage_tag) {
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename E2::value_type value_type;
+
+ BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
+ BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
+ size_type size1 = e2 ().size1 ();
+ size_type size2 = e2 ().size2 ();
+ for (difference_type n = size1 - 1; n >= 0; -- n) {
+#ifndef BOOST_UBLAS_SINGULAR_CHECK
+ BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
+#else
+ if (e1 () (n, n) == value_type/*zero*/())
+ singular ().raise ();
+#endif
+ for (difference_type l = size2 - 1; l >= 0; -- l) {
+ value_type t = e2 () (n, l) /= e1 () (n, n);
+ if (t != value_type/*zero*/()) {
+ typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
+ typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
+ while (it1e1 != it1e1_rend)
+ e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
+ }
+ }
+ }
+ }
+ // Dispatcher
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ upper_tag) {
+ typedef typename E1::storage_category dispatch_category;
+ inplace_solve (e1, e2,
+ upper_tag (), dispatch_category ());
+ }
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
+ unit_upper_tag) {
+ typedef typename E1::storage_category dispatch_category;
+ inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
+ unit_upper_tag (), dispatch_category ());
+ }
+
+ template<class E1, class E2, class C>
+ BOOST_UBLAS_INLINE
+ typename matrix_matrix_solve_traits<E1, E2>::result_type
+ solve (const matrix_expression<E1> &e1,
+ const matrix_expression<E2> &e2,
+ C) {
+ typename matrix_matrix_solve_traits<E1, E2>::result_type r (e2);
+ inplace_solve (e1, r, C ());
+ return r;
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2000-2010
+// Joerg Walter, Mathias Koch, David Bellot
+//
+// 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.
+//
+// And we acknowledge the support from all contributors.
+
+/// \file vector.hpp Definition for the class vector and its derivative
+
+#ifndef _BOOST_UBLAS_VECTOR_
+#define _BOOST_UBLAS_VECTOR_
+
+#include <boost/numeric/ublas/storage.hpp>
+#include <boost/numeric/ublas/vector_expression.hpp>
+#include <boost/numeric/ublas/detail/vector_assign.hpp>
+#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/nvp.hpp>
+
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \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 unbounded_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 unbounded_array<T>. \c <bounded_array<T> and \c std::vector<T> can also be used
+ */
+ template<class T, class A>
+ class vector:
+ public vector_container<vector<T, A> > {
+
+ typedef vector<T, 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 vector
+ /// By default it is empty, i.e. \c size()==0.
+ BOOST_UBLAS_INLINE
+ vector ():
+ vector_container<self_type> (),
+ data_ () {}
+
+ /// \brief Constructor of a vector with a predefined size
+ /// By default, its elements are initialized to 0.
+ /// \param size initial size of the vector
+ explicit BOOST_UBLAS_INLINE
+ vector (size_type size):
+ vector_container<self_type> (),
+ data_ (size) {
+ }
+
+ /// \brief Constructor of a vector by copying from another container
+ /// This type has the generic name \c array_typ within the vector definition.
+ /// \param size initial size of the vector \bug this value is not used
+ /// \param data container of type \c A
+ /// \todo remove this definition because \c size is not used
+ BOOST_UBLAS_INLINE
+ vector (size_type size, const array_type &data):
+ vector_container<self_type> (),
+ data_ (data) {}
+
+ /// \brief Constructor of a 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
+ vector (const array_type &data):
+ vector_container<self_type> (),
+ data_ (data) {}
+
+ /// \brief Constructor of a vector with a predefined size and a unique initial value
+ /// \param size of the vector
+ /// \param init value to assign to each element of the vector
+ BOOST_UBLAS_INLINE
+ vector (size_type size, const value_type &init):
+ vector_container<self_type> (),
+ data_ (size, init) {}
+
+ /// \brief Copy-constructor of a vector
+ /// \param v is the vector to be duplicated
+ BOOST_UBLAS_INLINE
+ vector (const 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
+ vector (const vector_expression<AE> &ae):
+ vector_container<self_type> (),
+ data_ (ae ().size ()) {
+ vector_assign<scalar_assign> (*this, ae);
+ }
+
+ // -----------------------
+ // 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
+ bool empty () const {
+ return data_.size () == 0;
+ }
+
+ // ---------
+ // Accessors
+ // ---------
+
+ /// \brief Return the size of the vector
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ 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_;
+ }
+
+ // --------
+ // Resizing
+ // --------
+
+ /// \brief Resize the vector
+ /// Resize the vector to a new size. If \c preserve is true, data are copied otherwise data are lost. If the new size is bigger, the remaining values are filled in with the initial value (0 by default) in the case of \c unbounded_array, which is the container by default. If the new size is smaller, last values are lost. This behaviour can be different if you explicitely specify another type of container.
+ /// \param size new size of the vector
+ /// \param preserve if true, keep values
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ if (preserve)
+ data ().resize (size, typename A::value_type ());
+ else
+ data ().resize (size);
+ }
+
+ // ---------------
+ // 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 {
+ 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 {
+ 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) {
+ 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 {
+ 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) {
+ 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) {
+ 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) {
+ 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 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)
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ vector &operator = (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
+ vector &operator = (const vector &v) {
+ data () = v.data ();
+ return *this;
+ }
+#endif
+
+ /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
+ /// Assign a full vector (\e RHS-vector) to the current 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
+ vector &operator = (const vector_container<C> &v) {
+ resize (v ().size (), false);
+ 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
+ vector &assign_temporary (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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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 (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 (vector &v1, 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<vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator, value_type, difference_type> {
+ public:
+ typedef typename vector::difference_type difference_type;
+ typedef typename vector::value_type value_type;
+ typedef typename vector::const_reference reference;
+ typedef const typename 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<vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator, value_type, difference_type> {
+ public:
+ typedef typename vector::difference_type difference_type;
+ typedef typename vector::value_type value_type;
+ typedef typename vector::reference reference;
+ typedef typename 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_;
+ };
+
+
+ // --------------------
+ // Bounded vector class
+ // --------------------
+
+ /// \brief a dense vector of values of type \c T, of variable size but with maximum \f$N\f$.
+ /// A dense vector of values of type \c T, of variable size but with maximum \f$N\f$. The default constructor
+ /// creates the vector with size \f$N\f$. Elements are constructed by the storage type \c bounded_array, which \b need \b not \b initialise their value.
+ template<class T, std::size_t N>
+ class bounded_vector:
+ public vector<T, bounded_array<T, N> > {
+
+ typedef vector<T, bounded_array<T, N> > vector_type;
+ public:
+ typedef typename vector_type::size_type size_type;
+ static const size_type max_size = N;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ bounded_vector ():
+ vector_type (N) {}
+ BOOST_UBLAS_INLINE
+ bounded_vector (size_type size):
+ vector_type (size) {}
+ BOOST_UBLAS_INLINE
+ bounded_vector (const bounded_vector &v):
+ vector_type (v) {}
+ template<class A2> // Allow vector<T,bounded_array<N> construction
+ BOOST_UBLAS_INLINE
+ bounded_vector (const vector<T, A2> &v):
+ vector_type (v) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ bounded_vector (const vector_expression<AE> &ae):
+ vector_type (ae) {}
+ BOOST_UBLAS_INLINE
+ ~bounded_vector () {}
+
+ // Assignment
+#ifdef BOOST_UBLAS_MOVE_SEMANTICS
+
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ bounded_vector &operator = (bounded_vector v) {
+ vector_type::operator = (v);
+ return *this;
+ }
+#else
+ BOOST_UBLAS_INLINE
+ bounded_vector &operator = (const bounded_vector &v) {
+ vector_type::operator = (v);
+ return *this;
+ }
+#endif
+ template<class A2> // Generic vector assignment
+ BOOST_UBLAS_INLINE
+ bounded_vector &operator = (const vector<T, A2> &v) {
+ vector_type::operator = (v);
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ bounded_vector &operator = (const vector_container<C> &v) {
+ vector_type::operator = (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ bounded_vector &operator = (const vector_expression<AE> &ae) {
+ vector_type::operator = (ae);
+ return *this;
+ }
+ };
+
+
+ // -----------------
+ // Zero vector class
+ // -----------------
+
+ /// \brief A zero vector of type \c T and a given \c size
+ /// A zero vector of type \c T and a given \c size. This is a virtual vector in the sense that no memory is allocated
+ /// for storing the zero values: it still acts like any other vector. However assigning values to it will not change the zero
+ /// vector into a normal vector. It must first be assigned to another normal vector by any suitable means. Its memory footprint is constant.
+ template<class T, class ALLOC>
+ class zero_vector:
+ public vector_container<zero_vector<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef zero_vector<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const vector_reference<const self_type> const_closure_type;
+ typedef vector_reference<self_type> closure_type;
+ typedef sparse_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ zero_vector ():
+ vector_container<self_type> (),
+ size_ (0) {}
+ explicit BOOST_UBLAS_INLINE
+ zero_vector (size_type size):
+ vector_container<self_type> (),
+ size_ (size) {}
+ BOOST_UBLAS_INLINE
+ zero_vector (const zero_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool /*preserve*/ = true) {
+ size_ = size;
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ return & zero_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type /* i */) const {
+ return zero_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ zero_vector &operator = (const zero_vector &v) {
+ size_ = v.size_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ zero_vector &assign_temporary (zero_vector &v) {
+ swap (v);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (zero_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (zero_vector &v1, zero_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Iterator types
+ public:
+ class const_iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type /*i*/) const {
+ return const_iterator (*this);
+ }
+
+ class const_iterator:
+ public container_const_reference<zero_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename zero_vector::difference_type difference_type;
+ typedef typename zero_vector::value_type value_type;
+ typedef typename zero_vector::const_reference reference;
+ typedef typename zero_vector::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &v):
+ container_const_reference<self_type> (v) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return zero_; // arbitary return value
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK_FALSE (bad_index ());
+ return 0; // arbitary return value
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ detail::ignore_unused_variable_warning(it);
+ return true;
+ }
+ };
+
+ typedef const_iterator iterator;
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ }
+
+ private:
+ size_type size_;
+ typedef const value_type const_value_type;
+ static const_value_type zero_;
+ };
+
+ template<class T, class ALLOC>
+ typename zero_vector<T, ALLOC>::const_value_type zero_vector<T, ALLOC>::zero_ = T(/*zero*/);
+
+
+ // Unit vector class
+ /// \brief unit_vector represents a canonical unit vector
+ /// unit_vector represents a canonical unit vector. The \e k-th unit vector of dimension \f$n\f$ holds 0 for every value \f$u_i\f$ s.t. \f$i \neq k\f$ and 1 when \f$i=k\f$.
+ /// At construction, the value \e k is given after the dimension of the vector.
+ /// \tparam T is the type of elements in the vector. They must be 0 and 1 assignable in order for the vector to have its unit-vector semantic.
+ /// \tparam ALLOC a specific allocator can be specified if needed. Most of the time this parameter is omited.
+ template<class T, class ALLOC>
+ class unit_vector:
+ public vector_container<unit_vector<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef unit_vector<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const vector_reference<const self_type> const_closure_type;
+ typedef vector_reference<self_type> closure_type;
+ typedef sparse_tag storage_category;
+
+ // Construction and destruction
+ /// \brief Simple constructor with dimension and index 0
+ BOOST_UBLAS_INLINE
+ unit_vector ():
+ vector_container<self_type> (),
+ size_ (0), index_ (0) {}
+
+ /// \brief Constructor of unit_vector
+ /// \param size is the dimension of the vector
+ /// \param index is the order of the vector
+ BOOST_UBLAS_INLINE
+ explicit unit_vector (size_type size, size_type index = 0):
+ vector_container<self_type> (),
+ size_ (size), index_ (index) {}
+
+ /// \brief Copy-constructor
+ BOOST_UBLAS_INLINE
+ unit_vector (const unit_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_), index_ (v.index_) {}
+
+ // Accessors
+ //----------
+
+ /// \brief Return the size (dimension) of the vector
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ /// \brief Return the order of the unit vector
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return index_;
+ }
+
+ // Resizing
+ // --------
+
+ /// \brief Resize the vector. The values are preserved by default (i.e. the index does not change)
+ /// \param size is the new size of the vector
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool /*preserve*/ = true) {
+ size_ = size;
+ }
+
+ // Element support
+ // ---------------
+
+ /// \brief Return a const pointer to the element of index i
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ if (i == index_)
+ return & one_;
+ else
+ return & zero_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ if (i == index_)
+ return one_;
+ else
+ return zero_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ unit_vector &operator = (const unit_vector &v) {
+ size_ = v.size_;
+ index_ = v.index_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ unit_vector &assign_temporary (unit_vector &v) {
+ swap (v);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (unit_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ std::swap (index_, v.index_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (unit_vector &v1, unit_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Iterator types
+ private:
+ // Use bool to indicate begin (one_ as value)
+ typedef bool const_subiterator_type;
+ public:
+ class const_iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, i <= index_);
+ }
+
+ class const_iterator:
+ public container_const_reference<unit_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename unit_vector::difference_type difference_type;
+ typedef typename unit_vector::value_type value_type;
+ typedef typename unit_vector::const_reference reference;
+ typedef typename unit_vector::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<unit_vector> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const unit_vector &v, const const_subiterator_type &it):
+ container_const_reference<unit_vector> (v), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ BOOST_UBLAS_CHECK (it_, bad_index ());
+ it_ = !it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ BOOST_UBLAS_CHECK (!it_, bad_index ());
+ it_ = !it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (it_, bad_index ());
+ return one_;
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (it_, bad_index ());
+ return (*this) ().index_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<unit_vector>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ 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_;
+ };
+
+ typedef const_iterator iterator;
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this, true);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this, false);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ ar & serialization::make_nvp("index", index_);
+ }
+
+ private:
+ size_type size_;
+ size_type index_;
+ typedef const value_type const_value_type;
+ static const_value_type zero_;
+ static const_value_type one_;
+ };
+
+ template<class T, class ALLOC>
+ typename unit_vector<T, ALLOC>::const_value_type unit_vector<T, ALLOC>::zero_ = T(/*zero*/);
+ template<class T, class ALLOC>
+ typename unit_vector<T, ALLOC>::const_value_type unit_vector<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here
+
+ /// \brief A scalar (i.e. unique value) vector of type \c T and a given \c size
+ /// A scalar (i.e. unique value) vector of type \c T and a given \c size. This is a virtual vector in the sense that no memory is allocated
+ /// for storing the unique value more than once: it still acts like any other vector. However assigning a new value will change all the value at once.
+ /// vector into a normal vector. It must first be assigned to another normal vector by any suitable means. Its memory footprint is constant.
+ /// \tparam T type of the objects stored in the vector: it can be anything even if most of the time, scalar types will be used like \c double or \c int. Complex types can be used, or even classes like boost::interval.
+ template<class T, class ALLOC>
+ class scalar_vector:
+ public vector_container<scalar_vector<T, ALLOC> > {
+
+ typedef const T *const_pointer;
+ typedef scalar_vector<T, ALLOC> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ typedef typename ALLOC::size_type size_type;
+ typedef typename ALLOC::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef const vector_reference<const self_type> const_closure_type;
+ typedef vector_reference<self_type> closure_type;
+ typedef dense_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ scalar_vector ():
+ vector_container<self_type> (),
+ size_ (0), value_ () {}
+ BOOST_UBLAS_INLINE
+ explicit scalar_vector (size_type size, const value_type &value = value_type(1)):
+ vector_container<self_type> (),
+ size_ (size), value_ (value) {}
+ BOOST_UBLAS_INLINE
+ scalar_vector (const scalar_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_), value_ (v.value_) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool /*preserve*/ = true) {
+ size_ = size;
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type /*i*/) const {
+ return & value_;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type /*i*/) const {
+ return value_;
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type /*i*/) const {
+ return value_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ scalar_vector &operator = (const scalar_vector &v) {
+ size_ = v.size_;
+ value_ = v.value_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ scalar_vector &assign_temporary (scalar_vector &v) {
+ swap (v);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (scalar_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ std::swap (value_, v.value_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (scalar_vector &v1, scalar_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Iterator types
+ private:
+ // Use an index
+ typedef size_type const_subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_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;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, i);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<scalar_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename scalar_vector::difference_type difference_type;
+ typedef typename scalar_vector::value_type value_type;
+ typedef typename scalar_vector::const_reference reference;
+ typedef typename scalar_vector::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<scalar_vector> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const scalar_vector &v, const const_subiterator_type &it):
+ container_const_reference<scalar_vector> (v), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
+ return (*this) () (index ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
+ return it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<scalar_vector>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ 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_;
+ };
+
+ typedef const_iterator iterator;
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size_);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ ar & serialization::make_nvp("value", value_);
+ }
+
+ private:
+ size_type size_;
+ value_type value_;
+ };
+
+ // ------------------------
+ // Array based vector class
+ // ------------------------
+
+ /// \brief A dense vector of values of type \c T with the given \c size. The data is stored as an ordinary C++ array \c T \c data_[M]
+ template<class T, std::size_t N>
+ class c_vector:
+ public vector_container<c_vector<T, N> > {
+
+ typedef c_vector<T, N> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+ typedef T &reference;
+ typedef value_type array_type[N];
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ 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
+ BOOST_UBLAS_INLINE
+ c_vector ():
+ size_ (N) /* , data_ () */ {}
+ explicit BOOST_UBLAS_INLINE
+ c_vector (size_type size):
+ size_ (size) /* , data_ () */ {
+ if (size_ > N)
+ bad_size ().raise ();
+ }
+ BOOST_UBLAS_INLINE
+ c_vector (const c_vector &v):
+ size_ (v.size_) /* , data_ () */ {
+ if (size_ > N)
+ bad_size ().raise ();
+ assign(v);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector (const vector_expression<AE> &ae):
+ size_ (ae ().size ()) /* , data_ () */ {
+ if (size_ > N)
+ bad_size ().raise ();
+ vector_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ pointer data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ if (size > N)
+ bad_size ().raise ();
+ size_ = size;
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ return & data_ [i];
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return data_ [i];
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ reference insert_element (size_type i, const_reference t) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return (data_ [i] = t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ data_ [i] = value_type/*zero*/();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ std::fill (data_, data_ + size_, value_type/*zero*/());
+ }
+
+ // Assignment
+#ifdef BOOST_UBLAS_MOVE_SEMANTICS
+
+ /*! @note "pass by value" the key idea to enable move semantics */
+ BOOST_UBLAS_INLINE
+ c_vector &operator = (c_vector v) {
+ assign_temporary(v);
+ return *this;
+ }
+#else
+ BOOST_UBLAS_INLINE
+ c_vector &operator = (const c_vector &v) {
+ size_ = v.size_;
+ std::copy (v.data_, v.data_ + v.size_, data_);
+ return *this;
+ }
+#endif
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_vector &operator = (const vector_container<C> &v) {
+ resize (v ().size (), false);
+ assign (v);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ c_vector &assign_temporary (c_vector &v) {
+ swap (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &operator = (const vector_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+
+ // Computed assignment
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &operator += (const vector_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_vector &operator += (const vector_container<C> &v) {
+ plus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> ( *this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &operator -= (const vector_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ c_vector &operator -= (const vector_container<C> &v) {
+ minus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ c_vector &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ c_vector &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ c_vector &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (c_vector &v) {
+ if (this != &v) {
+ BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ());
+ std::swap (size_, v.size_);
+ std::swap_ranges (data_, data_ + size_, v.data_);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (c_vector &v1, c_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Iterator types
+ private:
+ // Use pointers for iterator
+ typedef const_pointer const_subiterator_type;
+ typedef pointer 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
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, &data_ [i]);
+#else
+ return const_iterator (*this, i);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, &data_ [i]);
+#else
+ return iterator (*this, i);
+#endif
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<c_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename c_vector::difference_type difference_type;
+ typedef typename c_vector::value_type value_type;
+ typedef typename c_vector::const_reference reference;
+ typedef typename c_vector::const_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 self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_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 ());
+ const self_type &v = (*this) ();
+ return it_ - v.begin ().it_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ return it_ == it.it_;
+ }
+ 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
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size_);
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<c_vector>,
+ public random_access_iterator_base<dense_random_access_iterator_tag,
+ iterator, value_type> {
+ public:
+ typedef typename c_vector::difference_type difference_type;
+ typedef typename c_vector::value_type value_type;
+ typedef typename c_vector::reference reference;
+ typedef typename c_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 ());
+ // EDG won't allow const self_type it doesn't allow friend access to it_
+ self_type &v = (*this) ();
+ return it_ - v.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
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size_);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+
+ // copy the value back if loading
+ if (Archive::is_loading::value) {
+ if (s > N) bad_size("too large size in bounded_vector::load()\n").raise();
+ size_ = s;
+ }
+ // ISSUE: this writes the full array
+ ar & serialization::make_nvp("data",data_);
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ };
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_VECTOR_EXPRESSION_
+#define _BOOST_UBLAS_VECTOR_EXPRESSION_
+
+#include <boost/numeric/ublas/expression_types.hpp>
+
+
+// Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
+// Iterators based on ideas of Jeremy Siek
+//
+// Classes that model the Vector Expression concept
+
+namespace boost { namespace numeric { namespace ublas {
+
+ template<class E>
+ class vector_reference:
+ public vector_expression<vector_reference<E> > {
+
+ typedef vector_reference<E> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<vector_reference<E> >::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename E::value_type value_type;
+ typedef typename E::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_reference,
+ typename E::reference>::type reference;
+ typedef E referred_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename E::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit vector_reference (referred_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return expression ().size ();
+ }
+
+ public:
+ // Expression accessors - const correct
+ BOOST_UBLAS_INLINE
+ const referred_type &expression () const {
+ return e_;
+ }
+ BOOST_UBLAS_INLINE
+ referred_type &expression () {
+ return e_;
+ }
+
+ public:
+ // Element access
+#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return expression () (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return expression () (i);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return expression () [i];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return expression () [i];
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return expression () (i);
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return expression () [i];
+ }
+#endif
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ vector_reference &operator = (const vector_reference &v) {
+ expression ().operator = (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &operator = (const vector_expression<AE> &ae) {
+ expression ().operator = (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &assign (const vector_expression<AE> &ae) {
+ expression ().assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &operator += (const vector_expression<AE> &ae) {
+ expression ().operator += (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &plus_assign (const vector_expression<AE> &ae) {
+ expression ().plus_assign (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &operator -= (const vector_expression<AE> &ae) {
+ expression ().operator -= (ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_reference &minus_assign (const vector_expression<AE> &ae) {
+ expression ().minus_assign (ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_reference &operator *= (const AT &at) {
+ expression ().operator *= (at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_reference &operator /= (const AT &at) {
+ expression ().operator /= (at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (vector_reference &v) {
+ expression ().swap (v.expression ());
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_reference &vr) const {
+ return &(*this).e_ == &vr.e_;
+ }
+
+ // Iterator types
+ typedef typename E::const_iterator const_iterator;
+ typedef typename boost::mpl::if_<boost::is_const<E>,
+ typename E::const_iterator,
+ typename E::iterator>::type iterator;
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ return expression ().find (i);
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ return expression ().find (i);
+ }
+
+ // Iterator is the iterator of the referenced expression.
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return expression ().begin ();
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return expression ().end ();
+ }
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return expression ().begin ();
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return expression ().end ();
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ referred_type &e_;
+ };
+
+
+ template<class E, class F>
+ class vector_unary:
+ public vector_expression<vector_unary<E, F> > {
+
+ typedef F functor_type;
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
+ E,
+ const E>::type expression_type;
+ typedef typename boost::mpl::if_<boost::is_const<expression_type>,
+ typename E::const_closure_type,
+ typename E::closure_type>::type expression_closure_type;
+ typedef vector_unary<E, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<vector_unary<E, F> >::operator ();
+#endif
+ typedef typename E::size_type size_type;
+ typedef typename E::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
+ typename E::reference,
+ value_type>::type reference;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ // May be used as mutable expression.
+ explicit vector_unary (expression_type &e):
+ e_ (e) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e_.size ();
+ }
+
+ public:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
+ return e_ (i);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return functor_type::apply (e_ [i]);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
+ return e_ [i];
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_unary &vu) const {
+ return (*this).expression ().same_closure (vu.expression ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E::const_iterator const_subiterator_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ const_subiterator_type it (e_.find (i));
+ return const_iterator (*this, it.index ());
+#else
+ return const_iterator (*this, e_.find (i));
+#endif
+ }
+
+ // Iterator enhances the iterator of the referenced expression
+ // with the unary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_unary>,
+ public iterator_base_traits<typename E::const_iterator::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename E::const_iterator::iterator_category iterator_category;
+ typedef typename vector_unary::difference_type difference_type;
+ typedef typename vector_unary::value_type value_type;
+ typedef typename vector_unary::const_reference reference;
+ typedef typename vector_unary::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vu, const const_subiterator_type &it):
+ container_const_reference<self_type> (vu), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression_closure_type e_;
+ };
+
+ template<class E, class F>
+ struct vector_unary_traits {
+ typedef vector_unary<E, F> expression_type;
+//FIXME
+// #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+// #else
+// typedef typename E::vector_temporary_type result_type;
+// #endif
+ };
+
+ // (- v) [i] = - v [i]
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type
+ operator - (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (conj v) [i] = conj (v [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
+ conj (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (real v) [i] = real (v [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type
+ real (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (imag v) [i] = imag (v [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type
+ imag (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (trans v) [i] = v [i]
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type
+ trans (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type
+ trans (vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // (herm v) [i] = conj (v [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
+ herm (const vector_expression<E> &e) {
+ typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E1, class E2, class F>
+ class vector_binary:
+ public vector_expression<vector_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ typedef vector_binary<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<vector_binary<E1, E2, F> >::operator ();
+#endif
+ typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
+ typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
+ }
+
+ private:
+ // Accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_ (i), e2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return functor_type::apply (e1_ [i], e2_ [i]);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_binary &vb) const {
+ return (*this).expression1 ().same_closure (vb.expression1 ()) &&
+ (*this).expression2 ().same_closure (vb.expression2 ());
+ }
+
+ // Iterator types
+ private:
+ typedef typename E1::const_iterator const_subiterator1_type;
+ typedef typename E2::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
+ typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
+ typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ const_subiterator1_type it1 (e1_.find (i));
+ const_subiterator1_type it1_end (e1_.find (size ()));
+ const_subiterator2_type it2 (e2_.find (i));
+ const_subiterator2_type it2_end (e2_.find (size ()));
+ i = (std::min) (it1 != it1_end ? it1.index () : size (),
+ it2 != it2_end ? it2.index () : size ());
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, i);
+#else
+ return const_iterator (*this, i, it1, it1_end, it2, it2_end);
+#endif
+ }
+
+ // Iterator merges the iterators of the referenced expressions and
+ // enhances them with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_binary>,
+ public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef typename vector_binary::difference_type difference_type;
+ typedef typename vector_binary::value_type value_type;
+ typedef typename vector_binary::const_reference reference;
+ typedef typename vector_binary::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vb, size_type i,
+ const const_subiterator1_type &it1, const const_subiterator1_type &it1_end,
+ const const_subiterator2_type &it2, const const_subiterator2_type &it2_end):
+ container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
+
+ private:
+ // Dense specializations
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag) {
+ ++ i_; ++ it1_; ++ it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag) {
+ -- i_; -- it1_; -- it2_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (dense_random_access_iterator_tag, difference_type n) {
+ i_ += n; it1_ += n; it2_ += n;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (dense_random_access_iterator_tag, difference_type n) {
+ i_ -= n; it1_ -= n; it2_ -= n;
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (dense_random_access_iterator_tag) const {
+ return functor_type::apply (*it1_, *it2_);
+ }
+
+ // Packed specializations
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (it1_.index () <= i_)
+ ++ it1_;
+ if (it2_ != it2_end_)
+ if (it2_.index () <= i_)
+ ++ it2_;
+ ++ i_;
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag) {
+ if (it1_ != it1_end_)
+ if (i_ <= it1_.index ())
+ -- it1_;
+ if (it2_ != it2_end_)
+ if (i_ <= it2_.index ())
+ -- it2_;
+ -- i_;
+ }
+ BOOST_UBLAS_INLINE
+ void increment (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (packed_random_access_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (packed_random_access_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (packed_random_access_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (packed_random_access_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_)
+ if (it1_.index () == i_)
+ t1 = *it1_;
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_)
+ if (it2_.index () == i_)
+ t2 = *it2_;
+ return functor_type::apply (t1, t2);
+ }
+
+ // Sparse specializations
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size ();
+ if (it1_ != it1_end_) {
+ if (it1_.index () <= i_)
+ ++ it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index ();
+ }
+ size_type index2 = (*this) ().size ();
+ if (it2_ != it2_end_) {
+ if (it2_.index () <= i_)
+ ++ it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index ();
+ }
+ i_ = (std::min) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag) {
+ size_type index1 = (*this) ().size ();
+ if (it1_ != it1_end_) {
+ if (i_ <= it1_.index ())
+ -- it1_;
+ if (it1_ != it1_end_)
+ index1 = it1_.index ();
+ }
+ size_type index2 = (*this) ().size ();
+ if (it2_ != it2_end_) {
+ if (i_ <= it2_.index ())
+ -- it2_;
+ if (it2_ != it2_end_)
+ index2 = it2_.index ();
+ }
+ i_ = (std::max) (index1, index2);
+ }
+ BOOST_UBLAS_INLINE
+ void increment (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
+ while (n > 0) {
+ decrement (sparse_bidirectional_iterator_tag ());
+ --n;
+ }
+ while (n < 0) {
+ increment (sparse_bidirectional_iterator_tag ());
+ ++n;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ value_type dereference (sparse_bidirectional_iterator_tag) const {
+ value_type t1 = value_type/*zero*/();
+ if (it1_ != it1_end_)
+ if (it1_.index () == i_)
+ t1 = *it1_;
+ value_type t2 = value_type/*zero*/();
+ if (it2_ != it2_end_)
+ if (it2_.index () == i_)
+ t2 = *it2_;
+ return functor_type::apply (t1, t2);
+ }
+
+ public:
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ increment (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ decrement (iterator_category ());
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ increment (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ decrement (iterator_category (), n);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return index () - it.index ();
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return dereference (iterator_category ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return i_;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ i_ = it.i_;
+ it1_ = it.it1_;
+ it1_end_ = it.it1_end_;
+ it2_ = it.it2_;
+ it2_end_ = it.it2_end_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return index () == it.index ();
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return index () < it.index ();
+ }
+
+ private:
+ size_type i_;
+ const_subiterator1_type it1_;
+ const_subiterator1_type it1_end_;
+ const_subiterator2_type it2_;
+ const_subiterator2_type it2_end_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct vector_binary_traits {
+ typedef vector_binary<E1, E2, F> expression_type;
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::vector_temporary_type result_type;
+#endif
+ };
+
+ // (v1 + v2) [i] = v1 [i] + v2 [i]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ operator + (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (v1 - v2) [i] = v1 [i] - v2 [i]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ operator - (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (v1 * v2) [i] = v1 [i] * v2 [i]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ element_prod (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ // (v1 / v2) [i] = v1 [i] / v2 [i]
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+ typename E2::value_type> >::result_type
+ element_div (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
+ typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+
+ template<class E1, class E2, class F>
+ class vector_binary_scalar1:
+ public vector_expression<vector_binary_scalar1<E1, E2, F> > {
+
+ typedef F functor_type;
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ public:
+ typedef const E1& expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ private:
+ typedef vector_binary_scalar1<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<vector_binary_scalar1<E1, E2, F> >::operator ();
+#endif
+ typedef typename E2::size_type size_type;
+ typedef typename E2::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e2_.size ();
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_, e2_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return functor_type::apply (e1_, e2_ [i]);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_binary_scalar1 &vbs1) const {
+ return &e1_ == &(vbs1.e1_) &&
+ (*this).e2_.same_closure (vbs1.e2_);
+ }
+
+ // Iterator types
+ private:
+ typedef expression1_type const_subiterator1_type;
+ typedef typename expression2_type::const_iterator const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ const_subiterator2_type it (e2_.find (i));
+ return const_iterator (*this, it.index ());
+#else
+ return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i));
+#endif
+ }
+
+ // Iterator enhances the iterator of the referenced vector expression
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_binary_scalar1>,
+ public iterator_base_traits<typename E2::const_iterator::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename E2::const_iterator::iterator_category iterator_category;
+ typedef typename vector_binary_scalar1::difference_type difference_type;
+ typedef typename vector_binary_scalar1::value_type value_type;
+ typedef typename vector_binary_scalar1::const_reference reference;
+ typedef typename vector_binary_scalar1::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it2_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it2_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it2_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ - it.it2_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (it1_, *it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it2_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ == it.it2_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
+ return it2_ < it.it2_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct vector_binary_scalar1_traits {
+ typedef vector_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E2::vector_temporary_type result_type;
+#endif
+ };
+
+ // (t * v) [i] = t * v [i]
+ template<class T1, class E2>
+ BOOST_UBLAS_INLINE
+ typename enable_if< is_convertible<T1, typename E2::value_type >,
+ typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
+ >::type
+ operator * (const T1 &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
+ return expression_type (e1, e2 ());
+ }
+
+
+ template<class E1, class E2, class F>
+ class vector_binary_scalar2:
+ public vector_expression<vector_binary_scalar2<E1, E2, F> > {
+
+ typedef F functor_type;
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef const E2& expression2_closure_type;
+ typedef vector_binary_scalar2<E1, E2, F> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator ();
+#endif
+ typedef typename E1::size_type size_type;
+ typedef typename E1::difference_type difference_type;
+ typedef typename F::result_type value_type;
+ typedef value_type const_reference;
+ typedef const_reference reference;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return e1_.size ();
+ }
+
+ public:
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return functor_type::apply (e1_ (i), e2_);
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return functor_type::apply (e1_ [i], e2_);
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_binary_scalar2 &vbs2) const {
+ return (*this).e1_.same_closure (vbs2.e1_) &&
+ &e2_ == &(vbs2.e2_);
+ }
+
+ // Iterator types
+ private:
+ typedef typename expression1_type::const_iterator const_subiterator1_type;
+ typedef expression2_type const_subiterator2_type;
+ typedef const value_type *const_pointer;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
+ typedef const_iterator iterator;
+#else
+ class const_iterator;
+ typedef const_iterator iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ const_subiterator1_type it (e1_.find (i));
+ return const_iterator (*this, it.index ());
+#else
+ return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_));
+#endif
+ }
+
+ // Iterator enhances the iterator of the referenced vector expression
+ // with the binary functor.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_binary_scalar2>,
+ public iterator_base_traits<typename E1::const_iterator::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename E1::const_iterator::iterator_category iterator_category;
+ typedef typename vector_binary_scalar2::difference_type difference_type;
+ typedef typename vector_binary_scalar2::value_type value_type;
+ typedef typename vector_binary_scalar2::const_reference reference;
+ typedef typename vector_binary_scalar2::const_pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it1_ (), it2_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
+ container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it1_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it1_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it1_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ - it.it1_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ return functor_type::apply (*it1_, it2_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it1_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it1_ = it.it1_;
+ it2_ = it.it2_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ == it.it1_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ // FIXME we shouldn't compare floats
+ // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
+ return it1_ < it.it1_;
+ }
+
+ private:
+ const_subiterator1_type it1_;
+ const_subiterator2_type it2_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct vector_binary_scalar2_traits {
+ typedef vector_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
+#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
+ typedef expression_type result_type;
+#else
+ typedef typename E1::vector_temporary_type result_type;
+#endif
+ };
+
+ // (v * t) [i] = v [i] * t
+ template<class E1, class T2>
+ BOOST_UBLAS_INLINE
+ typename enable_if< is_convertible<T2, typename E1::value_type >,
+ typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
+ >::type
+ operator * (const vector_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+ }
+
+ // (v / t) [i] = v [i] / t
+ template<class E1, class T2>
+ BOOST_UBLAS_INLINE
+ typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
+ operator / (const vector_expression<E1> &e1,
+ const T2 &e2) {
+ typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
+ return expression_type (e1 (), e2);
+ }
+
+
+ template<class E, class F>
+ class vector_scalar_unary:
+ public scalar_expression<vector_scalar_unary<E, F> > {
+
+ typedef E expression_type;
+ typedef F functor_type;
+ typedef typename E::const_closure_type expression_closure_type;
+ typedef typename E::const_iterator::iterator_category iterator_category;
+ typedef vector_scalar_unary<E, F> self_type;
+ public:
+ typedef typename F::result_type value_type;
+ typedef typename E::difference_type difference_type;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ explicit vector_scalar_unary (const expression_type &e):
+ e_ (e) {}
+
+ private:
+ // Expression accessors
+ BOOST_UBLAS_INLINE
+ const expression_closure_type &expression () const {
+ return e_;
+ }
+
+ public:
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return evaluate (iterator_category ());
+ }
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (dense_random_access_iterator_tag) const {
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return functor_type::apply (e_);
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = e_.size ();
+ return functor_type::apply (size, e_.begin ());
+#else
+ difference_type size = e_.size ();
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ return functor_type::apply (size, e_.begin ());
+ else
+ return functor_type::apply (e_);
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (packed_random_access_iterator_tag) const {
+ return functor_type::apply (e_.begin (), e_.end ());
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (sparse_bidirectional_iterator_tag) const {
+ return functor_type::apply (e_.begin (), e_.end ());
+ }
+
+ private:
+ expression_closure_type e_;
+ };
+
+ template<class E, class F>
+ struct vector_scalar_unary_traits {
+ typedef vector_scalar_unary<E, F> expression_type;
+#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
+// FIXME don't define USE_SCALAR_ET other then for testing
+// They do not work for complex types
+ typedef expression_type result_type;
+#else
+ typedef typename F::result_type result_type;
+#endif
+ };
+
+ // sum v = sum (v [i])
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type
+ sum (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // real: norm_1 v = sum (abs (v [i]))
+ // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type
+ norm_1 (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // real: norm_2 v = sqrt (sum (v [i] * v [i]))
+ // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type
+ norm_2 (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // real: norm_inf v = maximum (abs (v [i]))
+ // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type
+ norm_inf (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
+ template<class E>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type
+ index_norm_inf (const vector_expression<E> &e) {
+ typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type;
+ return expression_type (e ());
+ }
+
+ template<class E1, class E2, class F>
+ class vector_scalar_binary:
+ public scalar_expression<vector_scalar_binary<E1, E2, F> > {
+
+ typedef E1 expression1_type;
+ typedef E2 expression2_type;
+ typedef F functor_type;
+ typedef typename E1::const_closure_type expression1_closure_type;
+ typedef typename E2::const_closure_type expression2_closure_type;
+ typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
+ typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
+ typedef vector_scalar_binary<E1, E2, F> self_type;
+ public:
+ static const unsigned complexity = 1;
+ typedef typename F::result_type value_type;
+ typedef typename E1::difference_type difference_type;
+ typedef const self_type const_closure_type;
+ typedef const_closure_type closure_type;
+ typedef unknown_storage_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_scalar_binary (const expression1_type &e1, const expression2_type &e2):
+ e1_ (e1), e2_ (e2) {}
+
+ private:
+ // Accessors
+ BOOST_UBLAS_INLINE
+ const expression1_closure_type &expression1 () const {
+ return e1_;
+ }
+ BOOST_UBLAS_INLINE
+ const expression2_closure_type &expression2 () const {
+ return e2_;
+ }
+
+ public:
+ BOOST_UBLAS_INLINE
+ operator value_type () const {
+ return evaluate (iterator_category ());
+ }
+
+ private:
+ // Dense random access specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (dense_random_access_iterator_tag) const {
+ BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
+#ifdef BOOST_UBLAS_USE_INDEXING
+ return functor_type::apply (e1_, e2_);
+#elif BOOST_UBLAS_USE_ITERATING
+ difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
+ return functor_type::apply (size, e1_.begin (), e2_.begin ());
+#else
+ difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
+ if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
+ return functor_type::apply (size, e1_.begin (), e2_.begin ());
+ else
+ return functor_type::apply (e1_, e2_);
+#endif
+ }
+
+ // Packed bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (packed_random_access_iterator_tag) const {
+ BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
+ return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ());
+ }
+
+ // Sparse bidirectional specialization
+ BOOST_UBLAS_INLINE
+ value_type evaluate (sparse_bidirectional_iterator_tag) const {
+ BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
+ return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ());
+ }
+
+ private:
+ expression1_closure_type e1_;
+ expression2_closure_type e2_;
+ };
+
+ template<class E1, class E2, class F>
+ struct vector_scalar_binary_traits {
+ typedef vector_scalar_binary<E1, E2, F> expression_type;
+#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
+// FIXME don't define USE_SCALAR_ET other then for testing
+// They do not work for complex types
+ typedef expression_type result_type;
+#else
+ typedef typename F::result_type result_type;
+#endif
+ };
+
+ // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
+ typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type> >::result_type
+ inner_prod (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
+ typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+ template<class E1, class E2>
+ BOOST_UBLAS_INLINE
+ typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
+ typename type_traits<typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type>::precision_type> >::result_type
+ prec_inner_prod (const vector_expression<E1> &e1,
+ const vector_expression<E2> &e2) {
+ typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
+ typename type_traits<typename promote_traits<typename E1::value_type,
+ typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type;
+ return expression_type (e1 (), e2 ());
+ }
+
+}}}
+
+#endif
--- /dev/null
+//
+// Copyright (c) 2003
+// Gunter Winkler, Joerg Walter
+//
+// 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_VECTOR_OF_VECTOR_
+#define _BOOST_UBLAS_VECTOR_OF_VECTOR_
+
+#include <boost/type_traits.hpp>
+
+#include <boost/numeric/ublas/storage_sparse.hpp>
+#include <boost/numeric/ublas/matrix_sparse.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ // uBLAS sparse vector based sparse matrix class
+ // FIXME outer vector can be sparse type but it is completely filled
+ template<class T, class L, class A>
+ class generalized_vector_of_vector:
+ public matrix_container<generalized_vector_of_vector<T, L, A> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef L layout_type;
+ typedef generalized_vector_of_vector<T, L, A> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using matrix_container<self_type>::operator ();
+#endif
+ typedef typename A::size_type size_type;
+ typedef typename A::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ typedef T &reference;
+#else
+ typedef sparse_matrix_element<self_type> reference;
+#endif
+ typedef A array_type;
+ typedef const matrix_reference<const self_type> const_closure_type;
+ typedef matrix_reference<self_type> closure_type;
+ typedef typename A::value_type vector_data_value_type;
+ typedef vector_data_value_type vector_temporary_type;
+ typedef self_type matrix_temporary_type;
+ typedef sparse_tag storage_category;
+ typedef typename L::orientation_category orientation_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector ():
+ matrix_container<self_type> (),
+ size1_ (0), size2_ (0), data_ (1) {
+ const size_type sizeM = layout_type::size_M (size1_, size2_);
+ // create size1+1 empty vector elements
+ data_.insert_element (sizeM, vector_data_value_type ());
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) {
+ const size_type sizeM = layout_type::size_M (size1_, size2_);
+ const size_type sizem = layout_type::size_m (size1_, size2_);
+ for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
+ data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
+ data_.insert_element (sizeM, vector_data_value_type ());
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector (const generalized_vector_of_vector &m):
+ matrix_container<self_type> (),
+ size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {
+ storage_invariants ();
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
+ matrix_container<self_type> (),
+ size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
+ const size_type sizeM = layout_type::size_M (size1_, size2_);
+ const size_type sizem = layout_type::size_m (size1_, size2_);
+ for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
+ data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
+ data_.insert_element (sizeM, vector_data_value_type ());
+ storage_invariants ();
+ matrix_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size1 () const {
+ return size1_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type size2 () const {
+ return size2_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ size_type non_zeros = 0;
+ for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
+ non_zeros += (*itv).nnz_capacity ();
+ return non_zeros;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ size_type non_zeros = 0;
+ for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
+ non_zeros += (*itv).nnz ();
+ return non_zeros;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ BOOST_UBLAS_INLINE
+ void resize (size_type size1, size_type size2, bool preserve = true) {
+ const size_type oldM = layout_type::size_M (size1_, size2_);
+ size1_ = size1;
+ size2_ = size2;
+ const size_type sizeM = layout_type::size_M (size1_, size2_);
+ const size_type sizem = layout_type::size_m (size1_, size2_);
+ data ().resize (sizeM + 1, preserve);
+ if (preserve) {
+ for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i)
+ ref (data () [i]).resize (sizem, preserve);
+ for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements
+ data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
+ if (sizeM > oldM) {
+ data_.insert_element (sizeM, vector_data_value_type ());
+ } else {
+ ref (data () [sizeM]).resize (0, false);
+ }
+ } else {
+ for (size_type i = 0; i < sizeM; ++ i)
+ data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
+ data_.insert_element (sizeM, vector_data_value_type ());
+ }
+ storage_invariants ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i, size_type j) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i, size_type j) const {
+ const size_type elementM = layout_type::index_M (i, j);
+ const size_type elementm = layout_type::index_m (i, j);
+ // optimise: check the storage_type and index directly if element always exists
+ if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
+ return & (data () [elementM] [elementm]);
+ }
+ else {
+ const typename array_type::value_type *pv = data ().find_element (elementM);
+ if (!pv)
+ return 0;
+ return pv->find_element (elementm);
+ }
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i, size_type j) const {
+ const_pointer p = find_element (i, j);
+ // optimise: check the storage_type and index directly if element always exists
+ if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
+ BOOST_UBLAS_CHECK (p, internal_logic () );
+ return *p;
+ }
+ else {
+ if (p)
+ return *p;
+ else
+ return zero_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i, size_type j) {
+#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
+ return at_element (i, j);
+#else
+ return reference (*this, i, j);
+#endif
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) {
+ if (this != &m) {
+ size1_ = m.size1_;
+ size2_ = m.size2_;
+ data () = m.data ();
+ }
+ storage_invariants ();
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) {
+ swap (m);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) {
+ self_type temporary (ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) {
+ self_type temporary (*this + ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
+ self_type temporary (*this - ae);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
+ matrix_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector& operator *= (const AT &at) {
+ matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ generalized_vector_of_vector& operator /= (const AT &at) {
+ matrix_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (generalized_vector_of_vector &m) {
+ if (this != &m) {
+ std::swap (size1_, m.size1_);
+ std::swap (size2_, m.size2_);
+ data ().swap (m.data ());
+ }
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) {
+ m1.swap (m2);
+ }
+
+ // Sorting
+ void sort () {
+ vectoriterator_type itv (data ().begin ());
+ vectoriterator_type itv_end (data ().end ());
+ while (itv != itv_end) {
+ (*itv).sort ();
+ ++ itv;
+ }
+ }
+
+ // Element insertion and erasure
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, size_type j, const_reference t) {
+ const size_type elementM = layout_type::index_M (i, j);
+ const size_type elementm = layout_type::index_m (i, j);
+ vector_data_value_type& vd (ref (data () [elementM]));
+ storage_invariants ();
+ return vd.insert_element (elementm, t);
+ }
+ BOOST_UBLAS_INLINE
+ void append_element (size_type i, size_type j, const_reference t) {
+ const size_type elementM = layout_type::index_M (i, j);
+ const size_type elementm = layout_type::index_m (i, j);
+ vector_data_value_type& vd (ref (data () [elementM]));
+ storage_invariants ();
+ return vd.append_element (elementm, t);
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i, size_type j) {
+ vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
+ if (itv == data ().end ())
+ return;
+ (*itv).erase_element (layout_type::index_m (i, j));
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ void clear () {
+ const size_type sizeM = layout_type::size_M (size1_, size2_);
+ // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving
+ for (size_type i = 0; i < sizeM; ++ i)
+ ref (data () [i]).clear ();
+ storage_invariants ();
+ }
+
+ // Iterator types
+ private:
+ // Use vector iterator
+ typedef typename A::const_iterator const_vectoriterator_type;
+ typedef typename A::iterator vectoriterator_type;
+ typedef typename A::value_type::const_iterator const_subiterator_type;
+ typedef typename A::value_type::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i, size_type j) {
+ return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]);
+ }
+
+ public:
+ class const_iterator1;
+ class iterator1;
+ class const_iterator2;
+ class iterator2;
+ typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
+ typedef reverse_iterator_base1<iterator1> reverse_iterator1;
+ typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
+ typedef reverse_iterator_base2<iterator2> reverse_iterator2;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
+ for (;;) {
+ const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
+ const_vectoriterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
+
+ const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
+ const_subiterator_type it_end ((*itv).end ());
+ if (rank == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && it.index () == layout_type::index_m (i, j))
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ i = it.index ();
+ } else {
+ if (i >= size1_)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == (*itv).begin ())
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ --it;
+ i = it.index ();
+ } else {
+ if (i == 0)
+ return const_iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
+ for (;;) {
+ vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
+ vectoriterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
+
+ subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
+ subiterator_type it_end ((*itv).end ());
+ if (rank == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (it != it_end && it.index () == layout_type::index_m (i, j))
+ return iterator1 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_i ()) {
+ if (it == it_end)
+ return iterator1 (*this, rank, i, j, itv, it);
+ i = it.index ();
+ } else {
+ if (i >= size1_)
+ return iterator1 (*this, rank, i, j, itv, it);
+ ++ i;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_i ()) {
+ if (it == (*itv).begin ())
+ return iterator1 (*this, rank, i, j, itv, it);
+ --it;
+ i = it.index ();
+ } else {
+ if (i == 0)
+ return iterator1 (*this, rank, i, j, itv, it);
+ -- i;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
+ for (;;) {
+ const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
+ const_vectoriterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
+
+ const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
+ const_subiterator_type it_end ((*itv).end ());
+ if (rank == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && it.index () == layout_type::index_m (i, j))
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ j = it.index ();
+ } else {
+ if (j >= size2_)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == (*itv).begin ())
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ --it;
+ j = it.index ();
+ } else {
+ if (j == 0)
+ return const_iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
+ for (;;) {
+ vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
+ vectoriterator_type itv_end (data ().end ());
+ if (itv == itv_end)
+ return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
+
+ subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
+ subiterator_type it_end ((*itv).end ());
+ if (rank == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (it != it_end && it.index () == layout_type::index_m (i, j))
+ return iterator2 (*this, rank, i, j, itv, it);
+ if (direction > 0) {
+ if (layout_type::fast_j ()) {
+ if (it == it_end)
+ return iterator2 (*this, rank, i, j, itv, it);
+ j = it.index ();
+ } else {
+ if (j >= size2_)
+ return iterator2 (*this, rank, i, j, itv, it);
+ ++ j;
+ }
+ } else /* if (direction < 0) */ {
+ if (layout_type::fast_j ()) {
+ if (it == (*itv).begin ())
+ return iterator2 (*this, rank, i, j, itv, it);
+ --it;
+ j = it.index ();
+ } else {
+ if (j == 0)
+ return iterator2 (*this, rank, i, j, itv, it);
+ -- j;
+ }
+ }
+ }
+ }
+
+
+ class const_iterator1:
+ public container_const_reference<generalized_vector_of_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator1, value_type> {
+ public:
+ typedef typename generalized_vector_of_vector::difference_type difference_type;
+ typedef typename generalized_vector_of_vector::value_type value_type;
+ typedef typename generalized_vector_of_vector::const_reference reference;
+ typedef const typename generalized_vector_of_vector::pointer pointer;
+
+ typedef const_iterator2 dual_iterator_type;
+ typedef const_reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator1 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator1 (const iterator1 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ const self_type &m = (*this) ();
+ i_ = index1 () + 1;
+ if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ const self_type &m = (*this) ();
+ i_ = index1 () - 1;
+ if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return *it_;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 begin () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator2 end () const {
+ const self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rbegin () const {
+ return const_reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator2 rend () const {
+ return const_reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_.index (), it_.index ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_.index (), it_.index ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator1 &operator = (const const_iterator1 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ const_vectoriterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator1 begin1 () const {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator1 end1 () const {
+ return find1 (0, size1_, 0);
+ }
+
+ class iterator1:
+ public container_reference<generalized_vector_of_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator1, value_type> {
+ public:
+ typedef typename generalized_vector_of_vector::difference_type difference_type;
+ typedef typename generalized_vector_of_vector::value_type value_type;
+ typedef typename generalized_vector_of_vector::true_reference reference;
+ typedef typename generalized_vector_of_vector::pointer pointer;
+
+ typedef iterator2 dual_iterator_type;
+ typedef reverse_iterator2 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator1 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator1 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ ++ it_;
+ else {
+ self_type &m = (*this) ();
+ i_ = index1 () + 1;
+ if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_i ())
+ -- it_;
+ else {
+ self_type &m = (*this) ();
+ i_ = index1 () - 1;
+ if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index2 () != j_)
+ *this = m.find1 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ true_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return *it_;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 begin () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), 0);
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator2 end () const {
+ self_type &m = (*this) ();
+ return m.find2 (1, index1 (), m.size2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rbegin () const {
+ return reverse_iterator2 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator2 rend () const {
+ return reverse_iterator2 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_.index (), it_.index ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_.index (), it_.index ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator1 &operator = (const iterator1 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator1 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vectoriterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator1;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator1 begin1 () {
+ return find1 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator1 end1 () {
+ return find1 (0, size1_, 0);
+ }
+
+ class const_iterator2:
+ public container_const_reference<generalized_vector_of_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator2, value_type> {
+ public:
+ typedef typename generalized_vector_of_vector::difference_type difference_type;
+ typedef typename generalized_vector_of_vector::value_type value_type;
+ typedef typename generalized_vector_of_vector::const_reference reference;
+ typedef const typename generalized_vector_of_vector::pointer pointer;
+
+ typedef const_iterator1 dual_iterator_type;
+ typedef const_reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator2 ():
+ container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
+ container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator2 (const iterator2 &it):
+ container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ const self_type &m = (*this) ();
+ j_ = index2 () + 1;
+ if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ const self_type &m = (*this) ();
+ j_ = index2 () - 1;
+ if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return *it_;
+ } else {
+ return (*this) () (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 begin () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_iterator1 end () const {
+ const self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rbegin () const {
+ return const_reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ const_reverse_iterator1 rend () const {
+ return const_reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_.index (), it_.index ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_.index (), it_.index ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator2 &operator = (const const_iterator2 &it) {
+ container_const_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ const_vectoriterator_type itv_;
+ const_subiterator_type it_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator2 begin2 () const {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator2 end2 () const {
+ return find2 (0, 0, size2_);
+ }
+
+ class iterator2:
+ public container_reference<generalized_vector_of_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator2, value_type> {
+ public:
+ typedef typename generalized_vector_of_vector::difference_type difference_type;
+ typedef typename generalized_vector_of_vector::value_type value_type;
+ typedef typename generalized_vector_of_vector::true_reference reference;
+ typedef typename generalized_vector_of_vector::pointer pointer;
+
+ typedef iterator1 dual_iterator_type;
+ typedef reverse_iterator1 dual_reverse_iterator_type;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator2 ():
+ container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
+ container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ iterator2 &operator ++ () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ ++ it_;
+ else {
+ self_type &m = (*this) ();
+ j_ = index2 () + 1;
+ if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, 1);
+ }
+ }
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 &operator -- () {
+ if (rank_ == 1 && layout_type::fast_j ())
+ -- it_;
+ else {
+ self_type &m = (*this) ();
+ j_ = index2 () - 1;
+ if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ else if (rank_ == 1) {
+ it_ = (*itv_).begin ();
+ if (it_ == (*itv_).end () || index1 () != i_)
+ *this = m.find2 (rank_, i_, j_, -1);
+ }
+ }
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ true_reference operator * () const {
+ BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
+ BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
+ if (rank_ == 1) {
+ return *it_;
+ } else {
+ return (*this) ().at_element (i_, j_);
+ }
+ }
+
+#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 begin () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, 0, index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ iterator1 end () const {
+ self_type &m = (*this) ();
+ return m.find1 (1, m.size1 (), index2 ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rbegin () const {
+ return reverse_iterator1 (end ());
+ }
+ BOOST_UBLAS_INLINE
+#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
+ typename self_type::
+#endif
+ reverse_iterator1 rend () const {
+ return reverse_iterator1 (begin ());
+ }
+#endif
+
+ // Indices
+ BOOST_UBLAS_INLINE
+ size_type index1 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
+ return layout_type::index_M (itv_.index (), it_.index ());
+ } else {
+ return i_;
+ }
+ }
+ BOOST_UBLAS_INLINE
+ size_type index2 () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
+ if (rank_ == 1) {
+ BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
+ return layout_type::index_m (itv_.index (), it_.index ());
+ } else {
+ return j_;
+ }
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ iterator2 &operator = (const iterator2 &it) {
+ container_reference<self_type>::assign (&it ());
+ rank_ = it.rank_;
+ i_ = it.i_;
+ j_ = it.j_;
+ itv_ = it.itv_;
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const iterator2 &it) const {
+ BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
+ // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
+ if (rank_ == 1 || it.rank_ == 1) {
+ return it_ == it.it_;
+ } else {
+ return i_ == it.i_ && j_ == it.j_;
+ }
+ }
+
+ private:
+ int rank_;
+ size_type i_;
+ size_type j_;
+ vectoriterator_type itv_;
+ subiterator_type it_;
+
+ friend class const_iterator2;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator2 begin2 () {
+ return find2 (0, 0, 0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator2 end2 () {
+ return find2 (0, 0, size2_);
+ }
+
+ // Reverse iterators
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rbegin1 () const {
+ return const_reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator1 rend1 () const {
+ return const_reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rbegin1 () {
+ return reverse_iterator1 (end1 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator1 rend1 () {
+ return reverse_iterator1 (begin1 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rbegin2 () const {
+ return const_reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator2 rend2 () const {
+ return const_reverse_iterator2 (begin2 ());
+ }
+
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rbegin2 () {
+ return reverse_iterator2 (end2 ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator2 rend2 () {
+ return reverse_iterator2 (begin2 ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+
+ // we need to copy to a collection_size_type to get a portable
+ // and efficient serialization
+ serialization::collection_size_type s1 (size1_);
+ serialization::collection_size_type s2 (size2_);
+
+ // serialize the sizes
+ ar & serialization::make_nvp("size1",s1)
+ & serialization::make_nvp("size2",s2);
+
+ // copy the values back if loading
+ if (Archive::is_loading::value) {
+ size1_ = s1;
+ size2_ = s2;
+ }
+
+ ar & serialization::make_nvp("data", data_);
+
+ storage_invariants();
+ }
+
+ private:
+ void storage_invariants () const
+ {
+ BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
+
+ }
+ size_type size1_;
+ size_type size2_;
+ array_type data_;
+ static const value_type zero_;
+ };
+
+ template<class T, class L, class A>
+ const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/();
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_VECTOR_PROXY_
+#define _BOOST_UBLAS_VECTOR_PROXY_
+
+#include <boost/numeric/ublas/vector_expression.hpp>
+#include <boost/numeric/ublas/detail/vector_assign.hpp>
+#include <boost/numeric/ublas/detail/temporary.hpp>
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+ /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range.
+ *
+ * A vector range can be used as a normal vector in any expression.
+ * If the specified range falls outside that of the index range of the vector, then
+ * the \c vector_range is not a well formed \i Vector \i Expression and access to an
+ * element outside of index range of the vector is \b undefined.
+ *
+ * \tparam V the type of vector referenced (for example \c vector<double>)
+ */
+ template<class V>
+ class vector_range:
+ public vector_expression<vector_range<V> > {
+
+ typedef vector_range<V> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef const V const_vector_type;
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+ typedef typename V::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_reference,
+ typename V::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_closure_type,
+ typename V::closure_type>::type vector_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename V::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_range (vector_type &data, const range_type &r):
+ data_ (data), r_ (r.preprocess (data.size ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
+ // r_.start () + r_.size () <= data_.size (), bad_index ());
+ }
+ BOOST_UBLAS_INLINE
+ vector_range (const vector_closure_type &data, const range_type &r, bool):
+ data_ (data), r_ (r.preprocess (data.size ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
+ // r_.start () + r_.size () <= data_.size (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start () const {
+ return r_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return r_.size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const vector_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ vector_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (r_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (r_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (r_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that vector_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ vector_range<vector_type> project (const range_type &r) const {
+ return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ vector_range &operator = (const vector_range &vr) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ vector_range &assign_temporary (vector_range &vr) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, vr);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_range &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_range &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_range &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_range &vr) const {
+ return (*this).data_.same_closure (vr.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const vector_range &vr) const {
+ return (*this).data_ == vr.data_ && r_ == vr.r_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (vector_range vr) {
+ if (this != &vr) {
+ BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), vr.begin ());
+ vector_swap<scalar_swap> (*this, vr);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (vector_range vr1, vector_range vr2) {
+ vr1.swap (vr2);
+ }
+
+ // Iterator types
+ private:
+ typedef typename V::const_iterator const_subiterator_type;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_iterator,
+ typename V::iterator>::type subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator<vector_range<vector_type>,
+ typename subiterator_type::iterator_category> iterator;
+ typedef indexed_const_iterator<vector_range<vector_type>,
+ typename const_subiterator_type::iterator_category> const_iterator;
+#else
+ class const_iterator;
+ class iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+ const_subiterator_type it (data_.find (start () + i));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, it.index ());
+#else
+ return const_iterator (*this, it);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+ subiterator_type it (data_.find (start () + i));
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, it.index ());
+#else
+ return iterator (*this, it);
+#endif
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_range>,
+ public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename const_subiterator_type::difference_type difference_type;
+ typedef typename const_subiterator_type::value_type value_type;
+ typedef typename const_subiterator_type::reference reference;
+ typedef typename const_subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vr, const const_subiterator_type &it):
+ container_const_reference<self_type> (vr), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index () - (*this) ().start ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<vector_range>,
+ public iterator_base_traits<typename subiterator_type::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ typedef typename subiterator_type::difference_type difference_type;
+ typedef typename subiterator_type::value_type value_type;
+ typedef typename subiterator_type::reference reference;
+ typedef typename subiterator_type::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &vr, const subiterator_type &it):
+ container_reference<self_type> (vr), 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) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return *it_;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index () - (*this) ().start ();
+ }
+
+ // 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) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ vector_closure_type data_;
+ range_type r_;
+ };
+
+ // ------------------
+ // Simple Projections
+ // ------------------
+
+ /** \brief Return a \c vector_range on a specified vector, a start and stop index.
+ * Return a \c vector_range on a specified vector, a start and stop index. The resulting \c vector_range can be manipulated like a normal vector.
+ * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
+ typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
+ return vector_range<V> (data, range_type (start, stop));
+ }
+
+ /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
+ * Return a \c const \c vector_range on a specified vector, a start and stop index. The resulting \c const \c vector_range can be manipulated like a normal vector.
+ *If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
+ typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
+ return vector_range<const V> (data, range_type (start, stop));
+ }
+
+ // -------------------
+ // Generic Projections
+ // -------------------
+
+ /** \brief Return a \c const \c vector_range on a specified vector and \c range
+ * Return a \c const \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
+ * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
+ return vector_range<V> (data, r);
+ }
+
+ /** \brief Return a \c vector_range on a specified vector and \c range
+ * Return a \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
+ * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
+ // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
+ return vector_range<const V> (data, r);
+ }
+
+ /** \brief Return a \c const \c vector_range on a specified vector and const \c range
+ * Return a \c const \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
+ * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
+ return data.project (r);
+ }
+
+ /** \brief Return a \c vector_range on a specified vector and const \c range
+ * Return a \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
+ * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
+ * Vector Expression and access to an element outside of index range of the vector is \b undefined.
+ */
+ template<class V>
+ BOOST_UBLAS_INLINE
+ const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
+ return data.project (r);
+ }
+
+ // Specialization of temporary_traits
+ template <class V>
+ struct vector_temporary_traits< vector_range<V> >
+ : vector_temporary_traits< V > {} ;
+ template <class V>
+ struct vector_temporary_traits< const vector_range<V> >
+ : vector_temporary_traits< V > {} ;
+
+
+ /** \brief A vector referencing a non continuous subvector of elements of vector v containing all elements specified by \c slice.
+ *
+ * A vector slice can be used as a normal vector in any expression.
+ * If the specified slice falls outside that of the index slice of the vector, then
+ * the \c vector_slice is not a well formed \i Vector \i Expression and access to an
+ * element outside of index slice of the vector is \b undefined.
+ *
+ * A slice is a generalization of a range. In a range going from \f$a\f$ to \f$b\f$,
+ * all elements belong to the range. In a slice, a \i \f$step\f$ can be specified meaning to
+ * take one element over \f$step\f$ in the range specified from \f$a\f$ to \f$b\f$.
+ * Obviously, a slice with a \f$step\f$ of 1 is equivalent to a range.
+ *
+ * \tparam V the type of vector referenced (for example \c vector<double>)
+ */
+ template<class V>
+ class vector_slice:
+ public vector_expression<vector_slice<V> > {
+
+ typedef vector_slice<V> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef const V const_vector_type;
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+ typedef typename V::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_reference,
+ typename V::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_closure_type,
+ typename V::closure_type>::type vector_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef basic_slice<size_type, difference_type> slice_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename V::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_slice (vector_type &data, const slice_type &s):
+ data_ (data), s_ (s.preprocess (data.size ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
+ // s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
+ }
+ BOOST_UBLAS_INLINE
+ vector_slice (const vector_closure_type &data, const slice_type &s, int):
+ data_ (data), s_ (s.preprocess (data.size ())) {
+ // Early checking of preconditions here.
+ // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
+ // s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type start () const {
+ return s_.start ();
+ }
+ BOOST_UBLAS_INLINE
+ difference_type stride () const {
+ return s_.stride ();
+ }
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return s_.size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const vector_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ vector_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (s_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (s_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (s_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that vector_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ vector_slice<vector_type> project (const range_type &r) const {
+ return vector_slice<vector_type> (data_, s_.compose (r.preprocess (data_.size ())), false);
+ }
+ BOOST_UBLAS_INLINE
+ vector_slice<vector_type> project (const slice_type &s) const {
+ return vector_slice<vector_type> (data_, s_.compose (s.preprocess (data_.size ())), false);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ vector_slice &operator = (const vector_slice &vs) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ vector_slice &assign_temporary (vector_slice &vs) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, vs);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_slice &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_slice &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_slice &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_slice &vr) const {
+ return (*this).data_.same_closure (vr.data_);
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const vector_slice &vs) const {
+ return (*this).data_ == vs.data_ && s_ == vs.s_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (vector_slice vs) {
+ if (this != &vs) {
+ BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), vs.begin ());
+ vector_swap<scalar_swap> (*this, vs);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (vector_slice vs1, vector_slice vs2) {
+ vs1.swap (vs2);
+ }
+
+ // Iterator types
+ private:
+ // Use slice as an index - FIXME this fails for packed assignment
+ typedef typename slice_type::const_iterator const_subiterator_type;
+ typedef typename slice_type::const_iterator subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator<vector_slice<vector_type>,
+ typename vector_type::iterator::iterator_category> iterator;
+ typedef indexed_const_iterator<vector_slice<vector_type>,
+ typename vector_type::const_iterator::iterator_category> const_iterator;
+#else
+ class const_iterator;
+ class iterator;
+#endif
+
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, i);
+#else
+ return const_iterator (*this, s_.begin () + i);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, i);
+#else
+ return iterator (*this, s_.begin () + i);
+#endif
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_slice>,
+ public iterator_base_traits<typename V::const_iterator::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename V::const_iterator::difference_type difference_type;
+ typedef typename V::const_iterator::value_type value_type;
+ typedef typename V::const_reference reference; //FIXME due to indexing access
+ typedef typename V::const_iterator::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vs, const const_subiterator_type &it):
+ container_const_reference<self_type> (vs), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().data_ (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<vector_slice>,
+ public iterator_base_traits<typename V::iterator::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ typedef typename V::iterator::difference_type difference_type;
+ typedef typename V::iterator::value_type value_type;
+ typedef typename V::reference reference; //FIXME due to indexing access
+ typedef typename V::iterator::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &vs, const subiterator_type &it):
+ container_reference<self_type> (vs), 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) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().data_ (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index ();
+ }
+
+ // 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) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ vector_closure_type data_;
+ slice_type s_;
+ };
+
+ // Simple Projections
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
+ typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
+ return vector_slice<V> (data, slice_type (start, stride, size));
+ }
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
+ typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
+ return vector_slice<const V> (data, slice_type (start, stride, size));
+ }
+
+ // Generic Projections
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
+ return vector_slice<V> (data, s);
+ }
+ template<class V>
+ BOOST_UBLAS_INLINE
+ const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
+ // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
+ return vector_slice<const V> (data, s);
+ }
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
+ return data.project (s);
+ }
+ template<class V>
+ BOOST_UBLAS_INLINE
+ const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
+ return data.project (s);
+ }
+ // ISSUE in the following two functions it would be logical to use vector_slice<V>::range_type but this confuses VC7.1 and 8.0
+ template<class V>
+ BOOST_UBLAS_INLINE
+ vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
+ return data.project (r);
+ }
+ template<class V>
+ BOOST_UBLAS_INLINE
+ const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
+ return data.project (r);
+ }
+
+ // Specialization of temporary_traits
+ template <class V>
+ struct vector_temporary_traits< vector_slice<V> >
+ : vector_temporary_traits< V > {} ;
+ template <class V>
+ struct vector_temporary_traits< const vector_slice<V> >
+ : vector_temporary_traits< V > {} ;
+
+
+ // Vector based indirection class
+ // Contributed by Toon Knapen.
+ // Extended and optimized by Kresimir Fresl.
+
+ /** \brief A vector referencing a non continuous subvector of elements given another vector of indices.
+ *
+ * It is the most general version of any subvectors because it uses another vector of indices to reference
+ * the subvector.
+ *
+ * The vector of indices can be of any type with the restriction that its elements must be
+ * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
+ * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
+ * - \c std::vector<A> where \c A can \c int, \c size_t, \c long, etc...
+ * - \c boost::numeric::ublas::vector<int> can work too (\c int can be replaced by another integer type)
+ * - etc...
+ *
+ * An indirect vector can be used as a normal vector in any expression. If the specified indirect vector
+ * falls outside that of the indices of the vector, then the \c vector_indirect is not a well formed
+ * \i Vector \i Expression and access to an element outside of indices of the vector is \b undefined.
+ *
+ * \tparam V the type of vector referenced (for example \c vector<double>)
+ * \tparam IA the type of index vector. Default is \c ublas::indirect_array<>
+ */
+ template<class V, class IA>
+ class vector_indirect:
+ public vector_expression<vector_indirect<V, IA> > {
+
+ typedef vector_indirect<V, IA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_expression<self_type>::operator ();
+#endif
+ typedef const V const_vector_type;
+ typedef V vector_type;
+ typedef const IA const_indirect_array_type;
+ typedef IA indirect_array_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::difference_type difference_type;
+ typedef typename V::value_type value_type;
+ typedef typename V::const_reference const_reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_reference,
+ typename V::reference>::type reference;
+ typedef typename boost::mpl::if_<boost::is_const<V>,
+ typename V::const_closure_type,
+ typename V::closure_type>::type vector_closure_type;
+ typedef basic_range<size_type, difference_type> range_type;
+ typedef basic_slice<size_type, difference_type> slice_type;
+ typedef const self_type const_closure_type;
+ typedef self_type closure_type;
+ typedef typename storage_restrict_traits<typename V::storage_category,
+ dense_proxy_tag>::storage_category storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ vector_indirect (vector_type &data, size_type size):
+ data_ (data), ia_ (size) {}
+ BOOST_UBLAS_INLINE
+ vector_indirect (vector_type &data, const indirect_array_type &ia):
+ data_ (data), ia_ (ia.preprocess (data.size ())) {}
+ BOOST_UBLAS_INLINE
+ vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
+ data_ (data), ia_ (ia.preprocess (data.size ())) {}
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return ia_.size ();
+ }
+ BOOST_UBLAS_INLINE
+ const_indirect_array_type &indirect () const {
+ return ia_;
+ }
+ BOOST_UBLAS_INLINE
+ indirect_array_type &indirect () {
+ return ia_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const vector_closure_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ vector_closure_type &data () {
+ return data_;
+ }
+
+ // Element access
+#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ return data_ (ia_ (i));
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+ return data_ (ia_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+#else
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) const {
+ return data_ (ia_ (i));
+ }
+
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+#endif
+
+ // ISSUE can this be done in free project function?
+ // Although a const function can create a non-const proxy to a non-const object
+ // Critical is that vector_type and data_ (vector_closure_type) are const correct
+ BOOST_UBLAS_INLINE
+ vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
+ return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
+ }
+ BOOST_UBLAS_INLINE
+ vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
+ return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
+ }
+ BOOST_UBLAS_INLINE
+ vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
+ return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator = (const vector_indirect &vi) {
+ // ISSUE need a temporary, proxy can be overlaping alias
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ vector_indirect &assign_temporary (vector_indirect &vi) {
+ // assign elements, proxied container remains the same
+ vector_assign<scalar_assign> (*this, vi);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator = (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator += (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator -= (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ vector_indirect &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ vector_indirect &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Closure comparison
+ BOOST_UBLAS_INLINE
+ bool same_closure (const vector_indirect &vr) const {
+return true;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const vector_indirect &vi) const {
+ return (*this).data_ == vi.data_ && ia_ == vi.ia_;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (vector_indirect vi) {
+ if (this != &vi) {
+ BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
+ // Sparse ranges may be nonconformant now.
+ // std::swap_ranges (begin (), end (), vi.begin ());
+ vector_swap<scalar_swap> (*this, vi);
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (vector_indirect vi1, vector_indirect vi2) {
+ vi1.swap (vi2);
+ }
+
+ // Iterator types
+ private:
+ // Use indirect array as an index - FIXME this fails for packed assignment
+ typedef typename IA::const_iterator const_subiterator_type;
+ typedef typename IA::const_iterator subiterator_type;
+
+ public:
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
+ typename vector_type::iterator::iterator_category> iterator;
+ typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
+ typename vector_type::const_iterator::iterator_category> const_iterator;
+#else
+ class const_iterator;
+ class iterator;
+#endif
+ // Element lookup
+ BOOST_UBLAS_INLINE
+ const_iterator find (size_type i) const {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return const_iterator (*this, i);
+#else
+ return const_iterator (*this, ia_.begin () + i);
+#endif
+ }
+ BOOST_UBLAS_INLINE
+ iterator find (size_type i) {
+#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ return iterator (*this, i);
+#else
+ return iterator (*this, ia_.begin () + i);
+#endif
+ }
+
+ // Iterators simply are indices.
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class const_iterator:
+ public container_const_reference<vector_indirect>,
+ public iterator_base_traits<typename V::const_iterator::iterator_category>::template
+ iterator_base<const_iterator, value_type>::type {
+ public:
+ typedef typename V::const_iterator::difference_type difference_type;
+ typedef typename V::const_iterator::value_type value_type;
+ typedef typename V::const_reference reference; //FIXME due to indexing access
+ typedef typename V::const_iterator::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ const_iterator ():
+ container_const_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const self_type &vi, const const_subiterator_type &it):
+ container_const_reference<self_type> (vi), it_ (it) {}
+ BOOST_UBLAS_INLINE
+ const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator += (difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -= (difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ difference_type operator - (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ // FIXME replace find with at_element
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().data_ (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ BOOST_UBLAS_INLINE
+ bool operator == (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const const_iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ const_subiterator_type it_;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size ());
+ }
+
+#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
+ class iterator:
+ public container_reference<vector_indirect>,
+ public iterator_base_traits<typename V::iterator::iterator_category>::template
+ iterator_base<iterator, value_type>::type {
+ public:
+ typedef typename V::iterator::difference_type difference_type;
+ typedef typename V::iterator::value_type value_type;
+ typedef typename V::reference reference; //FIXME due to indexing access
+ typedef typename V::iterator::pointer pointer;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ iterator ():
+ container_reference<self_type> (), it_ () {}
+ BOOST_UBLAS_INLINE
+ iterator (self_type &vi, const subiterator_type &it):
+ container_reference<self_type> (vi), 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) ().same_closure (it ()), external_logic ());
+ return it_ - it.it_;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ // FIXME replace find with at_element
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().data_ (*it_);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (difference_type n) const {
+ return *(*this + n);
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ return it_.index ();
+ }
+
+ // 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) ().same_closure (it ()), external_logic ());
+ return it_ == it.it_;
+ }
+ BOOST_UBLAS_INLINE
+ bool operator < (const iterator &it) const {
+ BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
+ return it_ < it.it_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+#endif
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ private:
+ vector_closure_type data_;
+ indirect_array_type ia_;
+ };
+
+ // Projections
+ template<class V, class A>
+ BOOST_UBLAS_INLINE
+ vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
+ return vector_indirect<V, indirect_array<A> > (data, ia);
+ }
+ template<class V, class A>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
+ // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
+ return vector_indirect<const V, indirect_array<A> > (data, ia);
+ }
+ template<class V, class IA>
+ BOOST_UBLAS_INLINE
+ vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
+ return data.project (r);
+ }
+ template<class V, class IA>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
+ return data.project (r);
+ }
+ template<class V, class IA>
+ BOOST_UBLAS_INLINE
+ vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
+ return data.project (s);
+ }
+ template<class V, class IA>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
+ return data.project (s);
+ }
+ template<class V, class A>
+ BOOST_UBLAS_INLINE
+ vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
+ return data.project (ia);
+ }
+ template<class V, class A>
+ BOOST_UBLAS_INLINE
+ const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
+ return data.project (ia);
+ }
+
+ // Specialization of temporary_traits
+ template <class V>
+ struct vector_temporary_traits< vector_indirect<V> >
+ : vector_temporary_traits< V > {} ;
+ template <class V>
+ struct vector_temporary_traits< const vector_indirect<V> >
+ : vector_temporary_traits< V > {} ;
+
+}}}
+
+#endif
--- /dev/null
+//
+// 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_VECTOR_SPARSE_
+#define _BOOST_UBLAS_VECTOR_SPARSE_
+
+#include <boost/numeric/ublas/storage_sparse.hpp>
+#include <boost/numeric/ublas/vector_expression.hpp>
+#include <boost/numeric/ublas/detail/vector_assign.hpp>
+#if BOOST_UBLAS_TYPE_CHECK
+#include <boost/numeric/ublas/vector.hpp>
+#endif
+
+// Iterators based on ideas of Jeremy Siek
+
+namespace boost { namespace numeric { namespace ublas {
+
+#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+
+ template<class V>
+ class sparse_vector_element:
+ public container_reference<V> {
+ public:
+ typedef V vector_type;
+ typedef typename V::size_type size_type;
+ typedef typename V::value_type value_type;
+ typedef const value_type &const_reference;
+ typedef value_type *pointer;
+
+ private:
+ // Proxied element operations
+ void get_d () const {
+ pointer p = (*this) ().find_element (i_);
+ if (p)
+ d_ = *p;
+ else
+ d_ = value_type/*zero*/();
+ }
+
+ void set (const value_type &s) const {
+ pointer p = (*this) ().find_element (i_);
+ if (!p)
+ (*this) ().insert_element (i_, s);
+ else
+ *p = s;
+ }
+
+ public:
+ // Construction and destruction
+ sparse_vector_element (vector_type &v, size_type i):
+ container_reference<vector_type> (v), i_ (i) {
+ }
+ BOOST_UBLAS_INLINE
+ sparse_vector_element (const sparse_vector_element &p):
+ container_reference<vector_type> (p), i_ (p.i_) {}
+ BOOST_UBLAS_INLINE
+ ~sparse_vector_element () {
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator = (const sparse_vector_element &p) {
+ // Overide the implict copy assignment
+ p.get_d ();
+ set (p.d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator = (const D &d) {
+ set (d);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator += (const D &d) {
+ get_d ();
+ d_ += d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator -= (const D &d) {
+ get_d ();
+ d_ -= d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator *= (const D &d) {
+ get_d ();
+ d_ *= d;
+ set (d_);
+ return *this;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ sparse_vector_element &operator /= (const D &d) {
+ get_d ();
+ d_ /= d;
+ set (d_);
+ return *this;
+ }
+
+ // Comparison
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator == (const D &d) const {
+ get_d ();
+ return d_ == d;
+ }
+ template<class D>
+ BOOST_UBLAS_INLINE
+ bool operator != (const D &d) const {
+ get_d ();
+ return d_ != d;
+ }
+
+ // Conversion - weak link in proxy as d_ is not a perfect alias for the element
+ BOOST_UBLAS_INLINE
+ operator const_reference () const {
+ get_d ();
+ return d_;
+ }
+
+ // Conversion to reference - may be invalidated
+ BOOST_UBLAS_INLINE
+ value_type& ref () const {
+ const pointer p = (*this) ().find_element (i_);
+ if (!p)
+ return (*this) ().insert_element (i_, value_type/*zero*/());
+ else
+ return *p;
+ }
+
+ private:
+ size_type i_;
+ mutable value_type d_;
+ };
+
+ /*
+ * Generalise explicit reference access
+ */
+ namespace detail {
+ template <class R>
+ struct element_reference {
+ typedef R& reference;
+ static reference get_reference (reference r)
+ {
+ return r;
+ }
+ };
+ template <class V>
+ struct element_reference<sparse_vector_element<V> > {
+ typedef typename V::value_type& reference;
+ static reference get_reference (const sparse_vector_element<V>& sve)
+ {
+ return sve.ref ();
+ }
+ };
+ }
+ template <class VER>
+ typename detail::element_reference<VER>::reference ref (VER& ver) {
+ return detail::element_reference<VER>::get_reference (ver);
+ }
+ template <class VER>
+ typename detail::element_reference<VER>::reference ref (const VER& ver) {
+ return detail::element_reference<VER>::get_reference (ver);
+ }
+
+
+ template<class V>
+ struct type_traits<sparse_vector_element<V> > {
+ typedef typename V::value_type element_type;
+ typedef type_traits<sparse_vector_element<V> > self_type;
+ typedef typename type_traits<element_type>::value_type value_type;
+ typedef typename type_traits<element_type>::const_reference const_reference;
+ typedef sparse_vector_element<V> reference;
+ typedef typename type_traits<element_type>::real_type real_type;
+ typedef typename type_traits<element_type>::precision_type precision_type;
+
+ static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
+ static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type real (const_reference t) {
+ return type_traits<element_type>::real (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type imag (const_reference t) {
+ return type_traits<element_type>::imag (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type conj (const_reference t) {
+ return type_traits<element_type>::conj (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type type_abs (const_reference t) {
+ return type_traits<element_type>::type_abs (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ value_type type_sqrt (const_reference t) {
+ return type_traits<element_type>::type_sqrt (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_1 (const_reference t) {
+ return type_traits<element_type>::norm_1 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_2 (const_reference t) {
+ return type_traits<element_type>::norm_2 (t);
+ }
+ static
+ BOOST_UBLAS_INLINE
+ real_type norm_inf (const_reference t) {
+ return type_traits<element_type>::norm_inf (t);
+ }
+
+ static
+ BOOST_UBLAS_INLINE
+ bool equals (const_reference t1, const_reference t2) {
+ return type_traits<element_type>::equals (t1, t2);
+ }
+ };
+
+ template<class V1, class T2>
+ struct promote_traits<sparse_vector_element<V1>, T2> {
+ typedef typename promote_traits<typename sparse_vector_element<V1>::value_type, T2>::promote_type promote_type;
+ };
+ template<class T1, class V2>
+ struct promote_traits<T1, sparse_vector_element<V2> > {
+ typedef typename promote_traits<T1, typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
+ };
+ template<class V1, class V2>
+ struct promote_traits<sparse_vector_element<V1>, sparse_vector_element<V2> > {
+ typedef typename promote_traits<typename sparse_vector_element<V1>::value_type,
+ typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
+ };
+
+#endif
+
+
+ /** \brief Index map based sparse vector
+ *
+ * A sparse vector of values of type T of variable size. The sparse storage type A can be
+ * \c std::map<size_t, T> or \c map_array<size_t, T>. This means that only non-zero elements
+ * are effectively stored.
+ *
+ * For a \f$n\f$-dimensional sparse vector, and 0 <= i < n the non-zero elements \f$v_i\f$
+ * are mapped to consecutive elements of the associative container, i.e. for elements
+ * \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of the container, holds \f$i_1 < i_2\f$.
+ *
+ * Supported parameters for the adapted array are \c map_array<std::size_t, T> and
+ * \c map_std<std::size_t, T>. The latter is equivalent to \c std::map<std::size_t, T>.
+ *
+ * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
+ * \tparam A the type of Storage array
+ */
+ template<class T, class A>
+ class mapped_vector:
+ public vector_container<mapped_vector<T, A> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef mapped_vector<T, 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 A array_type;
+ typedef const value_type &const_reference;
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ typedef typename detail::map_traits<A,T>::reference reference;
+#else
+ typedef sparse_vector_element<self_type> reference;
+#endif
+ typedef const vector_reference<const self_type> const_closure_type;
+ typedef vector_reference<self_type> closure_type;
+ typedef self_type vector_temporary_type;
+ typedef sparse_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ mapped_vector ():
+ vector_container<self_type> (),
+ size_ (0), data_ () {}
+ BOOST_UBLAS_INLINE
+ mapped_vector (size_type size, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (size), data_ () {
+ detail::map_reserve (data(), restrict_capacity (non_zeros));
+ }
+ BOOST_UBLAS_INLINE
+ mapped_vector (const mapped_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_), data_ (v.data_) {}
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (ae ().size ()), data_ () {
+ detail::map_reserve (data(), restrict_capacity (non_zeros));
+ vector_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return detail::map_capacity (data ());
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return data (). size ();
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ const array_type &data () const {
+ return data_;
+ }
+ BOOST_UBLAS_INLINE
+ array_type &data () {
+ return data_;
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ size_type restrict_capacity (size_type non_zeros) const {
+ non_zeros = (std::min) (non_zeros, size_);
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ size_ = size;
+ if (preserve) {
+ data ().erase (data ().lower_bound(size_), data ().end());
+ }
+ else {
+ data ().clear ();
+ }
+ }
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type non_zeros = 0, bool preserve = true) {
+ detail::map_reserve (data (), restrict_capacity (non_zeros));
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ const_subiterator_type it (data ().find (i));
+ if (it == data ().end ())
+ return 0;
+ BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
+ return &(*it).second;
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ const_subiterator_type it (data ().find (i));
+ if (it == data ().end ())
+ return zero_;
+ BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
+ return (*it).second;
+ }
+ BOOST_UBLAS_INLINE
+ true_reference ref (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (i, value_type/*zero*/())));
+ BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ()); // broken map
+ return (ii.first)->second;
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ return ref (i);
+#else
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return reference (*this, i);
+#endif
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, const_reference t) {
+ std::pair<subiterator_type, bool> ii = data ().insert (typename array_type::value_type (i, t));
+ BOOST_UBLAS_CHECK (ii.second, bad_index ()); // duplicate element
+ BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ()); // broken map
+ if (!ii.second) // existing element
+ (ii.first)->second = t;
+ return (ii.first)->second;
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i) {
+ subiterator_type it = data ().find (i);
+ if (it == data ().end ())
+ return;
+ data ().erase (it);
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ data ().clear ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator = (const mapped_vector &v) {
+ if (this != &v) {
+ size_ = v.size_;
+ data () = v.data ();
+ }
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator = (const vector_container<C> &v) {
+ resize (v ().size (), false);
+ assign (v);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ mapped_vector &assign_temporary (mapped_vector &v) {
+ swap (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator = (const vector_expression<AE> &ae) {
+ self_type temporary (ae, detail::map_capacity (data()));
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+
+ // Computed assignment
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator += (const vector_expression<AE> &ae) {
+ self_type temporary (*this + ae, detail::map_capacity (data()));
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator += (const vector_container<C> &v) {
+ plus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator -= (const vector_expression<AE> &ae) {
+ self_type temporary (*this - ae, detail::map_capacity (data()));
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator -= (const vector_container<C> &v) {
+ minus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ mapped_vector &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ mapped_vector &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (mapped_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ data ().swap (v.data ());
+ }
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (mapped_vector &v1, mapped_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Iterator types
+ private:
+ // Use storage iterator
+ typedef typename A::const_iterator const_subiterator_type;
+ typedef typename A::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ subiterator_type it (data ().find (i));
+ BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
+ BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
+ return it->second;
+ }
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, data ().lower_bound (i));
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator find (size_type i) {
+ return iterator (*this, data ().lower_bound (i));
+ }
+
+
+ class const_iterator:
+ public container_const_reference<mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename mapped_vector::value_type value_type;
+ typedef typename mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector::const_reference reference;
+ typedef const typename mapped_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 self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*it_).second;
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
+ return (*it_).first;
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ 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_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return const_iterator (*this, data ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return const_iterator (*this, data ().end ());
+ }
+
+ class iterator:
+ public container_reference<mapped_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator, value_type> {
+ public:
+ typedef typename mapped_vector::value_type value_type;
+ typedef typename mapped_vector::difference_type difference_type;
+ typedef typename mapped_vector::true_reference reference;
+ typedef typename mapped_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;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*it_).second;
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
+ return (*it_).first;
+ }
+
+ // 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_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return iterator (*this, data ().begin ());
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return iterator (*this, data ().end ());
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ ar & serialization::make_nvp("data", data_);
+ }
+
+ private:
+ size_type size_;
+ array_type data_;
+ static const value_type zero_;
+ };
+
+ template<class T, class A>
+ const typename mapped_vector<T, A>::value_type mapped_vector<T, A>::zero_ = value_type/*zero*/();
+
+
+ // Thanks to Kresimir Fresl for extending this to cover different index bases.
+
+ /** \brief Compressed array based sparse vector
+ *
+ * a sparse vector of values of type T of variable size. The non zero values are stored as
+ * two seperate arrays: an index array and a value array. The index array is always sorted
+ * and there is at most one entry for each index. Inserting an element can be time consuming.
+ * If the vector contains a few zero entries, then it is better to have a normal vector.
+ * If the vector has a very high dimension with a few non-zero values, then this vector is
+ * very memory efficient (at the cost of a few more computations).
+ *
+ * For a \f$n\f$-dimensional compressed vector and \f$0 \leq i < n\f$ the non-zero elements
+ * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
+ * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
+ *
+ * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
+ * \c bounded_array<> and \c std::vector<>.
+ *
+ * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
+ * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
+ * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
+ * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
+ */
+ template<class T, std::size_t IB, class IA, class TA>
+ class compressed_vector:
+ public vector_container<compressed_vector<T, IB, IA, TA> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef compressed_vector<T, IB, IA, TA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ // ISSUE require type consistency check
+ // is_convertable (IA::size_type, TA::size_type)
+ typedef typename IA::value_type size_type;
+ typedef typename IA::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ typedef T &reference;
+#else
+ typedef sparse_vector_element<self_type> reference;
+#endif
+ typedef IA index_array_type;
+ typedef TA value_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 sparse_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ compressed_vector ():
+ vector_container<self_type> (),
+ size_ (0), capacity_ (restrict_capacity (0)), filled_ (0),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ explicit BOOST_UBLAS_INLINE
+ compressed_vector (size_type size, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (size), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ compressed_vector (const compressed_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_), capacity_ (v.capacity_), filled_ (v.filled_),
+ index_data_ (v.index_data_), value_data_ (v.value_data_) {
+ storage_invariants ();
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ vector_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return capacity_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return filled_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ static size_type index_base () {
+ return IB;
+ }
+ BOOST_UBLAS_INLINE
+ typename index_array_type::size_type filled () const {
+ return filled_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index_data () const {
+ return index_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const value_array_type &value_data () const {
+ return value_data_;
+ }
+ BOOST_UBLAS_INLINE
+ void set_filled (const typename index_array_type::size_type & filled) {
+ filled_ = filled;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index_data () {
+ return index_data_;
+ }
+ BOOST_UBLAS_INLINE
+ value_array_type &value_data () {
+ return value_data_;
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ size_type restrict_capacity (size_type non_zeros) const {
+ non_zeros = (std::max) (non_zeros, size_type (1));
+ non_zeros = (std::min) (non_zeros, size_);
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ size_ = size;
+ capacity_ = restrict_capacity (capacity_);
+ if (preserve) {
+ index_data_. resize (capacity_, size_type ());
+ value_data_. resize (capacity_, value_type ());
+ filled_ = (std::min) (capacity_, filled_);
+ while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
+ --filled_;
+ }
+ }
+ else {
+ index_data_. resize (capacity_);
+ value_data_. resize (capacity_);
+ filled_ = 0;
+ }
+ storage_invariants ();
+ }
+
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type non_zeros, bool preserve = true) {
+ capacity_ = restrict_capacity (non_zeros);
+ if (preserve) {
+ index_data_. resize (capacity_, size_type ());
+ value_data_. resize (capacity_, value_type ());
+ filled_ = (std::min) (capacity_, filled_);
+ }
+ else {
+ index_data_. resize (capacity_);
+ value_data_. resize (capacity_);
+ filled_ = 0;
+ }
+ storage_invariants ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return 0;
+ return &value_data_ [it - index_data_.begin ()];
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return zero_;
+ return value_data_ [it - index_data_.begin ()];
+ }
+ BOOST_UBLAS_INLINE
+ true_reference ref (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return insert_element (i, value_type/*zero*/());
+ else
+ return value_data_ [it - index_data_.begin ()];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ return ref (i) ;
+#else
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return reference (*this, i);
+#endif
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i), bad_index ()); // duplicate element
+ if (filled_ >= capacity_)
+ reserve (2 * capacity_, true);
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ // ISSUE max_capacity limit due to difference_type
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
+ BOOST_UBLAS_CHECK (filled_ == 0 || filled_ == typename index_array_type::size_type (n) || *it != k_based (i), internal_logic ()); // duplicate found by lower_bound
+ ++ filled_;
+ it = index_data_.begin () + n;
+ std::copy_backward (it, index_data_.begin () + filled_ - 1, index_data_.begin () + filled_);
+ *it = k_based (i);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy_backward (itt, value_data_.begin () + filled_ - 1, value_data_.begin () + filled_);
+ *itt = t;
+ storage_invariants ();
+ return *itt;
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i) {
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
+ if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
+ std::copy (it + 1, index_data_.begin () + filled_, it);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy (itt + 1, value_data_.begin () + filled_, itt);
+ -- filled_;
+ }
+ storage_invariants ();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ filled_ = 0;
+ storage_invariants ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator = (const compressed_vector &v) {
+ if (this != &v) {
+ size_ = v.size_;
+ capacity_ = v.capacity_;
+ filled_ = v.filled_;
+ index_data_ = v.index_data_;
+ value_data_ = v.value_data_;
+ }
+ storage_invariants ();
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator = (const vector_container<C> &v) {
+ resize (v ().size (), false);
+ assign (v);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ compressed_vector &assign_temporary (compressed_vector &v) {
+ swap (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator = (const vector_expression<AE> &ae) {
+ self_type temporary (ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+
+ // Computed assignment
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator += (const vector_expression<AE> &ae) {
+ self_type temporary (*this + ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator += (const vector_container<C> &v) {
+ plus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator -= (const vector_expression<AE> &ae) {
+ self_type temporary (*this - ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator -= (const vector_container<C> &v) {
+ minus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ compressed_vector &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ compressed_vector &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (compressed_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ std::swap (capacity_, v.capacity_);
+ std::swap (filled_, v.filled_);
+ index_data_.swap (v.index_data_);
+ value_data_.swap (v.value_data_);
+ }
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (compressed_vector &v1, compressed_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Back element insertion and erasure
+ BOOST_UBLAS_INLINE
+ void push_back (size_type i, const_reference t) {
+ BOOST_UBLAS_CHECK (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i), external_logic ());
+ if (filled_ >= capacity_)
+ reserve (2 * capacity_, true);
+ BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
+ index_data_ [filled_] = k_based (i);
+ value_data_ [filled_] = t;
+ ++ filled_;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ void pop_back () {
+ BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
+ -- filled_;
+ storage_invariants ();
+ }
+
+ // Iterator types
+ private:
+ // Use index array iterator
+ typedef typename IA::const_iterator const_subiterator_type;
+ typedef typename IA::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
+ return value_data_ [it - index_data_.begin ()];
+ }
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator find (size_type i) const {
+ return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator find (size_type i) {
+ return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ }
+
+
+ class const_iterator:
+ public container_const_reference<compressed_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename compressed_vector::value_type value_type;
+ typedef typename compressed_vector::difference_type difference_type;
+ typedef typename compressed_vector::const_reference reference;
+ typedef const typename compressed_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 self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
+ return (*this) ().zero_based (*it_);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ 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_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size_);
+ }
+
+ class iterator:
+ public container_reference<compressed_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator, value_type> {
+ public:
+ typedef typename compressed_vector::value_type value_type;
+ typedef typename compressed_vector::difference_type difference_type;
+ typedef typename compressed_vector::true_reference reference;
+ typedef typename compressed_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;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
+ return (*this) ().zero_based (*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_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size_);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ // ISSUE: filled may be much less than capacity
+ // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
+ ar & serialization::make_nvp("capacity", capacity_);
+ ar & serialization::make_nvp("filled", filled_);
+ ar & serialization::make_nvp("index_data", index_data_);
+ ar & serialization::make_nvp("value_data", value_data_);
+ storage_invariants();
+ }
+
+ private:
+ void storage_invariants () const
+ {
+ BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
+ BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
+ }
+
+ size_type size_;
+ typename index_array_type::size_type capacity_;
+ typename index_array_type::size_type filled_;
+ index_array_type index_data_;
+ value_array_type value_data_;
+ static const value_type zero_;
+
+ BOOST_UBLAS_INLINE
+ static size_type zero_based (size_type k_based_index) {
+ return k_based_index - IB;
+ }
+ BOOST_UBLAS_INLINE
+ static size_type k_based (size_type zero_based_index) {
+ return zero_based_index + IB;
+ }
+
+ friend class iterator;
+ friend class const_iterator;
+ };
+
+ template<class T, std::size_t IB, class IA, class TA>
+ const typename compressed_vector<T, IB, IA, TA>::value_type compressed_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
+
+ // Thanks to Kresimir Fresl for extending this to cover different index bases.
+
+ /** \brief Coordimate array based sparse vector
+ *
+ * a sparse vector of values of type \c T of variable size. The non zero values are stored
+ * as two seperate arrays: an index array and a value array. The arrays may be out of order
+ * with multiple entries for each vector element. If there are multiple values for the same
+ * index the sum of these values is the real value. It is way more efficient for inserting values
+ * than a \c compressed_vector but less memory efficient. Also linearly parsing a vector can
+ * be longer in specific cases than a \c compressed_vector.
+ *
+ * For a n-dimensional sorted coordinate vector and \f$ 0 \leq i < n\f$ the non-zero elements
+ * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
+ * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
+ *
+ * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
+ * \c bounded_array<> and \c std::vector<>.
+ *
+ * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
+ * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
+ * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
+ * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
+ */
+ template<class T, std::size_t IB, class IA, class TA>
+ class coordinate_vector:
+ public vector_container<coordinate_vector<T, IB, IA, TA> > {
+
+ typedef T &true_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef coordinate_vector<T, IB, IA, TA> self_type;
+ public:
+#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
+ using vector_container<self_type>::operator ();
+#endif
+ // ISSUE require type consistency check
+ // is_convertable (IA::size_type, TA::size_type)
+ typedef typename IA::value_type size_type;
+ typedef typename IA::difference_type difference_type;
+ typedef T value_type;
+ typedef const T &const_reference;
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ typedef T &reference;
+#else
+ typedef sparse_vector_element<self_type> reference;
+#endif
+ typedef IA index_array_type;
+ typedef TA value_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 sparse_tag storage_category;
+
+ // Construction and destruction
+ BOOST_UBLAS_INLINE
+ coordinate_vector ():
+ vector_container<self_type> (),
+ size_ (0), capacity_ (restrict_capacity (0)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ explicit BOOST_UBLAS_INLINE
+ coordinate_vector (size_type size, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (size), capacity_ (restrict_capacity (non_zeros)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ coordinate_vector (const coordinate_vector &v):
+ vector_container<self_type> (),
+ size_ (v.size_), capacity_ (v.capacity_),
+ filled_ (v.filled_), sorted_filled_ (v.sorted_filled_), sorted_ (v.sorted_),
+ index_data_ (v.index_data_), value_data_ (v.value_data_) {
+ storage_invariants ();
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
+ vector_container<self_type> (),
+ size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)),
+ filled_ (0), sorted_filled_ (filled_), sorted_ (true),
+ index_data_ (capacity_), value_data_ (capacity_) {
+ storage_invariants ();
+ vector_assign<scalar_assign> (*this, ae);
+ }
+
+ // Accessors
+ BOOST_UBLAS_INLINE
+ size_type size () const {
+ return size_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz_capacity () const {
+ return capacity_;
+ }
+ BOOST_UBLAS_INLINE
+ size_type nnz () const {
+ return filled_;
+ }
+
+ // Storage accessors
+ BOOST_UBLAS_INLINE
+ static size_type index_base () {
+ return IB;
+ }
+ BOOST_UBLAS_INLINE
+ typename index_array_type::size_type filled () const {
+ return filled_;
+ }
+ BOOST_UBLAS_INLINE
+ const index_array_type &index_data () const {
+ return index_data_;
+ }
+ BOOST_UBLAS_INLINE
+ const value_array_type &value_data () const {
+ return value_data_;
+ }
+ BOOST_UBLAS_INLINE
+ void set_filled (const typename index_array_type::size_type &sorted, const typename index_array_type::size_type &filled) {
+ sorted_filled_ = sorted;
+ filled_ = filled;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ index_array_type &index_data () {
+ return index_data_;
+ }
+ BOOST_UBLAS_INLINE
+ value_array_type &value_data () {
+ return value_data_;
+ }
+
+ // Resizing
+ private:
+ BOOST_UBLAS_INLINE
+ size_type restrict_capacity (size_type non_zeros) const {
+ // minimum non_zeros
+ non_zeros = (std::max) (non_zeros, size_type (1));
+ // ISSUE no maximum as coordinate may contain inserted duplicates
+ return non_zeros;
+ }
+ public:
+ BOOST_UBLAS_INLINE
+ void resize (size_type size, bool preserve = true) {
+ if (preserve)
+ sort (); // remove duplicate elements.
+ size_ = size;
+ capacity_ = restrict_capacity (capacity_);
+ if (preserve) {
+ index_data_. resize (capacity_, size_type ());
+ value_data_. resize (capacity_, value_type ());
+ filled_ = (std::min) (capacity_, filled_);
+ while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
+ --filled_;
+ }
+ }
+ else {
+ index_data_. resize (capacity_);
+ value_data_. resize (capacity_);
+ filled_ = 0;
+ }
+ sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+ // Reserving
+ BOOST_UBLAS_INLINE
+ void reserve (size_type non_zeros, bool preserve = true) {
+ if (preserve)
+ sort (); // remove duplicate elements.
+ capacity_ = restrict_capacity (non_zeros);
+ if (preserve) {
+ index_data_. resize (capacity_, size_type ());
+ value_data_. resize (capacity_, value_type ());
+ filled_ = (std::min) (capacity_, filled_);
+ }
+ else {
+ index_data_. resize (capacity_);
+ value_data_. resize (capacity_);
+ filled_ = 0;
+ }
+ sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+
+ // Element support
+ BOOST_UBLAS_INLINE
+ pointer find_element (size_type i) {
+ return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
+ }
+ BOOST_UBLAS_INLINE
+ const_pointer find_element (size_type i) const {
+ sort ();
+ const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return 0;
+ return &value_data_ [it - index_data_.begin ()];
+ }
+
+ // Element access
+ BOOST_UBLAS_INLINE
+ const_reference operator () (size_type i) const {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ sort ();
+ const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return zero_;
+ return value_data_ [it - index_data_.begin ()];
+ }
+ BOOST_UBLAS_INLINE
+ true_reference ref (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ sort ();
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ if (it == index_data_.begin () + filled_ || *it != k_based (i))
+ return insert_element (i, value_type/*zero*/());
+ else
+ return value_data_ [it - index_data_.begin ()];
+ }
+ BOOST_UBLAS_INLINE
+ reference operator () (size_type i) {
+#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
+ return ref (i);
+#else
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ return reference (*this, i);
+#endif
+ }
+
+ BOOST_UBLAS_INLINE
+ const_reference operator [] (size_type i) const {
+ return (*this) (i);
+ }
+ BOOST_UBLAS_INLINE
+ reference operator [] (size_type i) {
+ return (*this) (i);
+ }
+
+ // Element assignment
+ BOOST_UBLAS_INLINE
+ void append_element (size_type i, const_reference t) {
+ if (filled_ >= capacity_)
+ reserve (2 * filled_, true);
+ BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
+ index_data_ [filled_] = k_based (i);
+ value_data_ [filled_] = t;
+ ++ filled_;
+ sorted_ = false;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ true_reference insert_element (size_type i, const_reference t) {
+ BOOST_UBLAS_CHECK (!find_element (i), bad_index ()); // duplicate element
+ append_element (i, t);
+ return value_data_ [filled_ - 1];
+ }
+ BOOST_UBLAS_INLINE
+ void erase_element (size_type i) {
+ sort ();
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
+ if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
+ std::copy (it + 1, index_data_.begin () + filled_, it);
+ typename value_array_type::iterator itt (value_data_.begin () + n);
+ std::copy (itt + 1, value_data_.begin () + filled_, itt);
+ -- filled_;
+ sorted_filled_ = filled_;
+ }
+ storage_invariants ();
+ }
+
+ // Zeroing
+ BOOST_UBLAS_INLINE
+ void clear () {
+ filled_ = 0;
+ sorted_filled_ = filled_;
+ sorted_ = true;
+ storage_invariants ();
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator = (const coordinate_vector &v) {
+ if (this != &v) {
+ size_ = v.size_;
+ capacity_ = v.capacity_;
+ filled_ = v.filled_;
+ sorted_filled_ = v.sorted_filled_;
+ sorted_ = v.sorted_;
+ index_data_ = v.index_data_;
+ value_data_ = v.value_data_;
+ }
+ storage_invariants ();
+ return *this;
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator = (const vector_container<C> &v) {
+ resize (v ().size (), false);
+ assign (v);
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ coordinate_vector &assign_temporary (coordinate_vector &v) {
+ swap (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator = (const vector_expression<AE> &ae) {
+ self_type temporary (ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_assign> (*this, ae);
+ return *this;
+ }
+
+ // Computed assignment
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator += (const vector_expression<AE> &ae) {
+ self_type temporary (*this + ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator += (const vector_container<C> &v) {
+ plus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &plus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_plus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator -= (const vector_expression<AE> &ae) {
+ self_type temporary (*this - ae, capacity_);
+ return assign_temporary (temporary);
+ }
+ template<class C> // Container assignment without temporary
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator -= (const vector_container<C> &v) {
+ minus_assign (v);
+ return *this;
+ }
+ template<class AE>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &minus_assign (const vector_expression<AE> &ae) {
+ vector_assign<scalar_minus_assign> (*this, ae);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator *= (const AT &at) {
+ vector_assign_scalar<scalar_multiplies_assign> (*this, at);
+ return *this;
+ }
+ template<class AT>
+ BOOST_UBLAS_INLINE
+ coordinate_vector &operator /= (const AT &at) {
+ vector_assign_scalar<scalar_divides_assign> (*this, at);
+ return *this;
+ }
+
+ // Swapping
+ BOOST_UBLAS_INLINE
+ void swap (coordinate_vector &v) {
+ if (this != &v) {
+ std::swap (size_, v.size_);
+ std::swap (capacity_, v.capacity_);
+ std::swap (filled_, v.filled_);
+ std::swap (sorted_filled_, v.sorted_filled_);
+ std::swap (sorted_, v.sorted_);
+ index_data_.swap (v.index_data_);
+ value_data_.swap (v.value_data_);
+ }
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ friend void swap (coordinate_vector &v1, coordinate_vector &v2) {
+ v1.swap (v2);
+ }
+
+ // Sorting and summation of duplicates
+ BOOST_UBLAS_INLINE
+ void sort () const {
+ if (! sorted_ && filled_ > 0) {
+ typedef index_pair_array<index_array_type, value_array_type> array_pair;
+ array_pair ipa (filled_, index_data_, value_data_);
+ const typename array_pair::iterator iunsorted = ipa.begin () + sorted_filled_;
+ // sort new elements and merge
+ std::sort (iunsorted, ipa.end ());
+ std::inplace_merge (ipa.begin (), iunsorted, ipa.end ());
+
+ // sum duplicates with += and remove
+ size_type filled = 0;
+ for (size_type i = 1; i < filled_; ++ i) {
+ if (index_data_ [filled] != index_data_ [i]) {
+ ++ filled;
+ if (filled != i) {
+ index_data_ [filled] = index_data_ [i];
+ value_data_ [filled] = value_data_ [i];
+ }
+ } else {
+ value_data_ [filled] += value_data_ [i];
+ }
+ }
+ filled_ = filled + 1;
+ sorted_filled_ = filled_;
+ sorted_ = true;
+ storage_invariants ();
+ }
+ }
+
+ // Back element insertion and erasure
+ BOOST_UBLAS_INLINE
+ void push_back (size_type i, const_reference t) {
+ // must maintain sort order
+ BOOST_UBLAS_CHECK (sorted_ && (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i)), external_logic ());
+ if (filled_ >= capacity_)
+ reserve (2 * filled_, true);
+ BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
+ index_data_ [filled_] = k_based (i);
+ value_data_ [filled_] = t;
+ ++ filled_;
+ sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+ BOOST_UBLAS_INLINE
+ void pop_back () {
+ // ISSUE invariants could be simpilfied if sorted required as precondition
+ BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
+ -- filled_;
+ sorted_filled_ = (std::min) (sorted_filled_, filled_);
+ sorted_ = sorted_filled_ = filled_;
+ storage_invariants ();
+ }
+
+ // Iterator types
+ private:
+ // Use index array iterator
+ typedef typename IA::const_iterator const_subiterator_type;
+ typedef typename IA::iterator subiterator_type;
+
+ BOOST_UBLAS_INLINE
+ true_reference at_element (size_type i) {
+ BOOST_UBLAS_CHECK (i < size_, bad_index ());
+ sort ();
+ subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
+ return value_data_ [it - index_data_.begin ()];
+ }
+
+ public:
+ class const_iterator;
+ class iterator;
+
+ // Element lookup
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ const_iterator find (size_type i) const {
+ sort ();
+ return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ }
+ // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
+ iterator find (size_type i) {
+ sort ();
+ return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
+ }
+
+
+ class const_iterator:
+ public container_const_reference<coordinate_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ const_iterator, value_type> {
+ public:
+ typedef typename coordinate_vector::value_type value_type;
+ typedef typename coordinate_vector::difference_type difference_type;
+ typedef typename coordinate_vector::const_reference reference;
+ typedef const typename coordinate_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 self_type:: stops VC8 using std::iterator here
+ container_const_reference<self_type> (it ()), it_ (it.it_) {}
+
+ // Arithmetic
+ BOOST_UBLAS_INLINE
+ const_iterator &operator ++ () {
+ ++ it_;
+ return *this;
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator &operator -- () {
+ -- it_;
+ return *this;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ const_reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
+ return (*this) ().zero_based (*it_);
+ }
+
+ // Assignment
+ BOOST_UBLAS_INLINE
+ const_iterator &operator = (const const_iterator &it) {
+ container_const_reference<self_type>::assign (&it ());
+ it_ = it.it_;
+ return *this;
+ }
+
+ // Comparison
+ 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_;
+ };
+
+ BOOST_UBLAS_INLINE
+ const_iterator begin () const {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ const_iterator end () const {
+ return find (size_);
+ }
+
+ class iterator:
+ public container_reference<coordinate_vector>,
+ public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
+ iterator, value_type> {
+ public:
+ typedef typename coordinate_vector::value_type value_type;
+ typedef typename coordinate_vector::difference_type difference_type;
+ typedef typename coordinate_vector::true_reference reference;
+ typedef typename coordinate_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;
+ }
+
+ // Dereference
+ BOOST_UBLAS_INLINE
+ reference operator * () const {
+ BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
+ return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
+ }
+
+ // Index
+ BOOST_UBLAS_INLINE
+ size_type index () const {
+ BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
+ BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
+ return (*this) ().zero_based (*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_;
+ }
+
+ private:
+ subiterator_type it_;
+
+ friend class const_iterator;
+ };
+
+ BOOST_UBLAS_INLINE
+ iterator begin () {
+ return find (0);
+ }
+ BOOST_UBLAS_INLINE
+ iterator end () {
+ return find (size_);
+ }
+
+ // Reverse iterator
+ typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator_base<iterator> reverse_iterator;
+
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rbegin () const {
+ return const_reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ const_reverse_iterator rend () const {
+ return const_reverse_iterator (begin ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rbegin () {
+ return reverse_iterator (end ());
+ }
+ BOOST_UBLAS_INLINE
+ reverse_iterator rend () {
+ return reverse_iterator (begin ());
+ }
+
+ // Serialization
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* file_version */){
+ serialization::collection_size_type s (size_);
+ ar & serialization::make_nvp("size",s);
+ if (Archive::is_loading::value) {
+ size_ = s;
+ }
+ // ISSUE: filled may be much less than capacity
+ // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
+ ar & serialization::make_nvp("capacity", capacity_);
+ ar & serialization::make_nvp("filled", filled_);
+ ar & serialization::make_nvp("sorted_filled", sorted_filled_);
+ ar & serialization::make_nvp("sorted", sorted_);
+ ar & serialization::make_nvp("index_data", index_data_);
+ ar & serialization::make_nvp("value_data", value_data_);
+ storage_invariants();
+ }
+
+ private:
+ void storage_invariants () const
+ {
+ BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
+ BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
+ BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
+ BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
+ BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
+ }
+
+ size_type size_;
+ size_type capacity_;
+ mutable typename index_array_type::size_type filled_;
+ mutable typename index_array_type::size_type sorted_filled_;
+ mutable bool sorted_;
+ mutable index_array_type index_data_;
+ mutable value_array_type value_data_;
+ static const value_type zero_;
+
+ BOOST_UBLAS_INLINE
+ static size_type zero_based (size_type k_based_index) {
+ return k_based_index - IB;
+ }
+ BOOST_UBLAS_INLINE
+ static size_type k_based (size_type zero_based_index) {
+ return zero_based_index + IB;
+ }
+
+ friend class iterator;
+ friend class const_iterator;
+ };
+
+ template<class T, std::size_t IB, class IA, class TA>
+ const typename coordinate_vector<T, IB, IA, TA>::value_type coordinate_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
+
+}}}
+
+#endif