?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/numeric.tar
???????
conversion/int_float_mixture.hpp 0000644 00000002022 15125237305 0013175 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/conversion_traits.hpp 0000644 00000001672 15125237305 0013226 0 ustar 00 // (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 { } ; } } // namespace boost::numeric #endif // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/converter.hpp 0000644 00000004277 15125237305 0011466 0 ustar 00 // (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 conversion/sign_mixture_enum.hpp 0000644 00000001510 15125237305 0013203 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/cast.hpp 0000644 00000004115 15125237305 0010400 0 ustar 00 // (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_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 conversion/udt_builtin_mixture_enum.hpp 0000644 00000001351 15125237305 0014570 0 ustar 00 // (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 conversion/int_float_mixture_enum.hpp 0000644 00000001523 15125237305 0014226 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/numeric_cast_traits.hpp 0000644 00000001727 15125237305 0013516 0 ustar 00 // //! 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 conversion/converter_policies.hpp 0000644 00000010734 15125237305 0013350 0 ustar 00 // (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 <functional> #include <typeinfo> // for std::bad_cast #include <boost/config.hpp> #include <boost/config/no_tr1/cmath.hpp> // for std::floor and std::ceil #include <boost/throw_exception.hpp> #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: const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return "bad numeric conversion: overflow"; } }; class negative_overflow : public bad_numeric_cast { public: const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return "bad numeric conversion: negative overflow"; } }; class positive_overflow : public bad_numeric_cast { public: const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return "bad numeric conversion: positive overflow"; } }; struct def_overflow_handler { void operator() ( range_check_result r ) // throw(negative_overflow,positive_overflow) { #ifndef BOOST_NO_EXCEPTIONS if ( r == cNegOverflow ) throw negative_overflow() ; else if ( r == cPosOverflow ) throw positive_overflow() ; #else if ( r == cNegOverflow ) ::boost::throw_exception(negative_overflow()) ; else if ( r == cPosOverflow ) ::boost::throw_exception(positive_overflow()) ; #endif } } ; 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 conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp 0000644 00000022137 15125237305 0021512 0 ustar 00 // //! 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; }; }} conversion/detail/preprocessed/numeric_cast_traits_common.hpp 0000644 00000123430 15125237305 0021022 0 ustar 00 // //! 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; }; }} conversion/detail/int_float_mixture.hpp 0000644 00000005050 15125237305 0014443 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/detail/conversion_traits.hpp 0000644 00000007003 15125237305 0014462 0 ustar 00 // (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 conversion/detail/converter.hpp 0000644 00000045444 15125237305 0012731 0 ustar 00 // (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 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 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 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(BOOST_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 conversion/detail/meta.hpp 0000644 00000007120 15125237305 0011635 0 ustar 00 // (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(BOOST_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 conversion/detail/numeric_cast_traits.hpp 0000644 00000012623 15125237305 0014755 0 ustar 00 // //! 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 conversion/detail/is_subranged.hpp 0000644 00000017006 15125237305 0013360 0 ustar 00 // (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 conversion/detail/udt_builtin_mixture.hpp 0000644 00000004660 15125237305 0015014 0 ustar 00 // (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 conversion/detail/sign_mixture.hpp 0000644 00000004763 15125237305 0013436 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/detail/bounds.hpp 0000644 00000003434 15125237305 0012205 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/detail/old_numeric_cast.hpp 0000644 00000025341 15125237305 0014226 0 ustar 00 // 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 // 02 Jun 14 Remove VC6 workarounds. // 16 Jul 11 Bugfixes for VC6. // 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> 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; } }; 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(BOOST_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(BOOST_BORLANDC) # pragma option pop # endif } // namespace detail #endif template<typename Target, typename Source> inline Target numeric_cast(Source arg) { // 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(BOOST_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(BOOST_BORLANDC) #pragma option pop # endif #endif { throw bad_numeric_cast(); } return static_cast<Target>(arg); } // numeric_cast } // namespace boost #endif // BOOST_OLD_NUMERIC_CAST_HPP conversion/is_subranged.hpp 0000644 00000001614 15125237305 0012114 0 ustar 00 // (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 conversion/udt_builtin_mixture.hpp 0000644 00000001675 15125237305 0013555 0 ustar 00 // (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 conversion/sign_mixture.hpp 0000644 00000001757 15125237305 0012174 0 ustar 00 // (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 // /////////////////////////////////////////////////////////////////////////////////////////////// conversion/bounds.hpp 0000644 00000001302 15125237305 0010733 0 ustar 00 // (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 odeint/config.hpp 0000644 00000002261 15125237305 0010010 0 ustar 00 /* [auto_generated] boost/numeric/odeint/config.hpp [begin_description] Sets configurations for odeint and used libraries. Should be included before any other odeint library [end_description] Copyright 2011-2012 Mario Mulansky Copyright 2011-2012 Karsten Ahnert 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_ODEINT_CONFIG_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_CONFIG_HPP_INCLUDED //increase macro variable to allow rk78 scheme #ifndef FUSION_MAX_VECTOR_SIZE #define FUSION_MAX_VECTOR_SIZE 15 #endif /* * the following definitions are only required if fusion vectors are used as state types * in the rk78 scheme * they should be defined by the user if required, see e.g. libs/numeric/examples/harmonic_oscillator_units.cpp */ #ifndef BOOST_FUSION_INVOKE_MAX_ARITY #define BOOST_FUSION_INVOKE_MAX_ARITY 15 #endif #ifndef BOOST_RESULT_OF_NUM_ARGS #define BOOST_RESULT_OF_NUM_ARGS 15 #endif #include <boost/config.hpp> #if __cplusplus >= 201103L #define BOOST_NUMERIC_ODEINT_CXX11 1 #endif #endif // BOOST_NUMERIC_ODEINT_CONFIG_HPP_INCLUDED odeint/util/split.hpp 0000644 00000002701 15125237305 0010652 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/split.hpp [begin_description] Split abstraction for parallel backends. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_UTIL_SPLIT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_SPLIT_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { /* * No default implementation of the split operation */ template< class Container1, class Container2 , class Enabler = void > struct split_impl { static void split( const Container1 &from , Container2 &to ); }; template< class Container1 , class Container2 > void split( const Container1 &from , Container2 &to ) { split_impl< Container1 , Container2 >::split( from , to ); } /* * No default implementation of the unsplit operation */ template< class Container1, class Container2 , class Enabler = void > struct unsplit_impl { static void unsplit( const Container1 &from , Container2 &to ); }; template< class Container1 , class Container2 > void unsplit( const Container1 &from , Container2 &to ) { unsplit_impl< Container1 , Container2 >::unsplit( from , to ); } } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_COPY_HPP_INCLUDED odeint/util/resize.hpp 0000644 00000006007 15125237305 0011023 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/state_wrapper.hpp [begin_description] State wrapper for the state type in all stepper. The state wrappers are responsible for construction, destruction, copying construction, assignment and resizing. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_UTIL_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_RESIZE_HPP_INCLUDED #include <boost/range.hpp> #include <boost/utility/enable_if.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <boost/fusion/include/zip_view.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/make_fused.hpp> #include <boost/fusion/include/for_each.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> namespace boost { namespace numeric { namespace odeint { template< class StateOut , class StateIn , class Enabler = void > struct resize_impl_sfinae { static void resize( StateOut &x1 , const StateIn &x2 ) { x1.resize( boost::size( x2 ) ); } }; // resize function // standard implementation relies on boost.range and resize member function template< class StateOut , class StateIn > struct resize_impl { static void resize( StateOut &x1 , const StateIn &x2 ) { resize_impl_sfinae< StateOut , StateIn >::resize( x1 , x2 ); } }; // do not overload or specialize this function, specialize resize_impl<> instead template< class StateOut , class StateIn > void resize( StateOut &x1 , const StateIn &x2 ) { resize_impl< StateOut , StateIn >::resize( x1 , x2 ); } namespace detail { struct resizer { typedef void result_type; template< class StateOut , class StateIn > void operator()( StateOut &x1 , const StateIn &x2 ) const { resize_op( x1 , x2 , typename is_resizeable< StateOut >::type() ); } template< class StateOut , class StateIn > void resize_op( StateOut &x1 , const StateIn &x2 , boost::true_type ) const { resize( x1 , x2 ); } template< class StateOut , class StateIn > void resize_op( StateOut &/*x1*/ , const StateIn &/*x2*/ , boost::false_type ) const { } }; } // namespace detail /* * specialization for fusion sequences */ template< class FusionSeq > struct resize_impl_sfinae< FusionSeq , FusionSeq , typename boost::enable_if< typename boost::fusion::traits::is_sequence< FusionSeq >::type >::type > { static void resize( FusionSeq &x1 , const FusionSeq &x2 ) { typedef boost::fusion::vector< FusionSeq& , const FusionSeq& > Sequences; Sequences sequences( x1 , x2 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( detail::resizer() ) ); } }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_RESIZE_HPP_INCLUDED odeint/util/split_adaptor.hpp 0000644 00000006035 15125237305 0012370 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/split_adaptor.hpp [begin_description] A range adaptor which returns even-sized slices. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_UTIL_SPLIT_ADAPTOR_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_SPLIT_ADAPTOR_INCLUDED #include <boost/range/adaptor/argument_fwd.hpp> #include <boost/range/size_type.hpp> #include <boost/range/iterator_range.hpp> #include <algorithm> namespace boost { namespace numeric { namespace odeint { namespace detail { /** \brief Returns the begin and end offset for a sub-range */ inline std::pair<std::size_t, std::size_t> split_offsets( std::size_t total_length, std::size_t index, std::size_t parts ) { BOOST_ASSERT( parts > 0 ); BOOST_ASSERT( index < parts ); const std::size_t slice = total_length / parts, partial = total_length % parts, lo = (std::min)(index, partial), hi = (std::max<std::ptrdiff_t>)(0, index - partial), begin_offset = lo * (slice + 1) + hi * slice, length = slice + (index < partial ? 1 : 0), end_offset = begin_offset + length; return std::make_pair( begin_offset, end_offset ); } /** \brief Return the sub-range `index` from a range which is split into `parts`. * * For example, splitting a range into three about equal-sized sub-ranges: * \code * sub0 = make_split_range(rng, 0, 3); * sub1 = rng | split(1, 3); * sub2 = rng | split(2, 3); * \endcode */ template< class RandomAccessRange > inline iterator_range< typename range_iterator<RandomAccessRange>::type > make_split_range( RandomAccessRange& rng, std::size_t index, std::size_t parts ) { const std::pair<std::size_t, std::size_t> off = split_offsets(boost::size(rng), index, parts); return make_iterator_range( boost::begin(rng) + off.first, boost::begin(rng) + off.second ); } template< class RandomAccessRange > inline iterator_range< typename range_iterator<const RandomAccessRange>::type > make_split_range( const RandomAccessRange& rng, std::size_t index, std::size_t parts ) { const std::pair<std::size_t, std::size_t> off = split_offsets(boost::size(rng), index, parts); return make_iterator_range( boost::begin(rng) + off.first, boost::begin(rng) + off.second ); } struct split { split(std::size_t index, std::size_t parts) : index(index), parts(parts) {} std::size_t index, parts; }; template< class RandomAccessRange > inline iterator_range< typename range_iterator<RandomAccessRange>::type > operator|( RandomAccessRange& rng, const split& f ) { return make_split_range( rng, f.index, f.parts ); } template< class RandomAccessRange > inline iterator_range< typename range_iterator<const RandomAccessRange>::type > operator|( const RandomAccessRange& rng, const split& f ) { return make_split_range( rng, f.index, f.parts ); } } } } } #endif odeint/util/is_pair.hpp 0000644 00000001577 15125237305 0011157 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/is_pair.hpp [begin_description] Metafunction to determine if a type is a std::pair<>. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_UTIL_IS_PAIR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_IS_PAIR_HPP_INCLUDED #include <boost/mpl/bool.hpp> #include <utility> namespace boost { namespace numeric { namespace odeint { template< class T > struct is_pair : public boost::mpl::false_ { }; template< class T1 , class T2 > struct is_pair< std::pair< T1 , T2 > > : public boost::mpl::true_ { }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_IS_PAIR_HPP_INCLUDED odeint/util/copy.hpp 0000644 00000004156 15125237305 0010477 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/copy.hpp [begin_description] Copy abstraction for the usage in the steppers. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_UTIL_COPY_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_COPY_HPP_INCLUDED #include <boost/range/algorithm/copy.hpp> #include <boost/utility/enable_if.hpp> #include <boost/numeric/odeint/util/detail/is_range.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Container1 , class Container2 > void do_copying( const Container1 &from , Container2 &to , boost::mpl::true_ ) { boost::range::copy( from , boost::begin( to ) ); } template< class Container1 , class Container2 > void do_copying( const Container1 &from , Container2 &to , boost::mpl::false_ ) { to = from; } } // namespace detail /* * Default implementation of the copy operation used the assign operator * gsl_vector must copied differently */ template< class Container1 , class Container2 , class Enabler = void > struct copy_impl_sfinae { static void copy( const Container1 &from , Container2 &to ) { typedef typename boost::numeric::odeint::detail::is_range< Container1 >::type is_range_type; detail::do_copying( from , to , is_range_type() ); } }; template< class Container1, class Container2 > struct copy_impl { static void copy( const Container1 &from , Container2 &to ) { copy_impl_sfinae< Container1 , Container2 >::copy( from , to ); } }; // ToDo: allow also to copy INTO a range, not only from a range! Needs "const Container2 &to" template< class Container1 , class Container2 > void copy( const Container1 &from , Container2 &to ) { copy_impl< Container1 , Container2 >::copy( from , to ); } } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_COPY_HPP_INCLUDED odeint/util/stepper_traits.hpp 0000644 00000003012 15125237305 0012563 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/stepper_traits.hpp [begin_description] tba. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_UTIL_STEPPER_TRAITS_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_UTIL_STEPPER_TRAITS_HPP_DEFINED #include <boost/numeric/odeint/util/unwrap_reference.hpp> namespace boost { namespace numeric { namespace odeint { namespace traits { template< class Stepper > struct state_type { typedef typename boost::numeric::odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename stepper_type::state_type type; }; template< class Stepper > struct time_type { typedef typename boost::numeric::odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename stepper_type::time_type type; }; template< class Stepper > struct stepper_category { typedef typename boost::numeric::odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename stepper_type::stepper_category type; }; template< class Stepper > struct value_type { typedef typename boost::numeric::odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename stepper_type::value_type type; }; } // namespace traits } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_STEPPER_TRAITS_HPP_DEFINED odeint/util/resizer.hpp 0000644 00000003625 15125237305 0011210 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/resizer.hpp [begin_description] Implementation of the resizers. [end_description] Copyright 2011-2012 Mario Mulansky Copyright 2011 Karsten Ahnert 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_ODEINT_UTIL_RESIZER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_RESIZER_HPP_INCLUDED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/numeric/odeint/util/resize.hpp> namespace boost { namespace numeric { namespace odeint { template< class ResizeWrappedState , class State > bool adjust_size_by_resizeability( ResizeWrappedState &x , const State &y , boost::true_type ) { if ( !same_size( x.m_v , y ) ) { resize( x.m_v , y ); return true; } else return false; } template< class ResizeWrappedState , class State > bool adjust_size_by_resizeability( ResizeWrappedState & /* x */ , const State & /* y */ , boost::false_type ) { return false; } struct always_resizer { template< class State , class ResizeFunction > bool adjust_size( const State &x , ResizeFunction f ) { return f( x ); } }; struct initially_resizer { bool m_initialized; initially_resizer() : m_initialized( false ) { } template< class State , class ResizeFunction > bool adjust_size( const State &x , ResizeFunction f ) { if( !m_initialized ) { m_initialized = true; return f( x ); } else return false; } }; struct never_resizer { template< class State , class ResizeFunction > bool adjust_size( const State &/*x*/ , ResizeFunction /*f*/ ) { return false; } }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_RESIZER_HPP_INCLUDED odeint/util/bind.hpp 0000644 00000003256 15125237305 0010441 0 ustar 00 /* * [begin_description] * Boost bind pull the placeholders, _1, _2, ... into global * namespace. This can conflict with the C++03 TR1 and C++11 * std::placeholders. This header provides a workaround for * this problem. * [end_description] * * Copyright 2012 Christoph Koke * Copyright 2012 Karsten Ahnert * * 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_ODEINT_UTIL_BIND_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_BIND_HPP_INCLUDED #include <boost/numeric/odeint/config.hpp> #if BOOST_NUMERIC_ODEINT_CXX11 #include <functional> #else #define BOOST_BIND_NO_PLACEHOLDERS #include <boost/bind.hpp> #endif namespace boost { namespace numeric { namespace odeint { namespace detail { #if BOOST_NUMERIC_ODEINT_CXX11 using ::std::bind; using namespace ::std::placeholders; #else // unnamed namespace to avoid multiple declarations (#138) namespace { using ::boost::bind; boost::arg<1> _1; boost::arg<2> _2; } // using ::boost::bind; // using ::_1; // using ::_2; #endif } } } } /* // the following is the suggested way. Unfortunately it does not work with all compilers. #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL #include <boost/bind.hpp> #else #include <functional> #endif namespace boost { namespace numeric { namespace odeint { namespace detail { #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL using ::boost::bind; using ::_1; using ::_2; #else using ::std::bind; using namespace ::std::placeholders; #endif } } } }*/ #endif // BOOST_NUMERIC_ODEINT_UTIL_BIND_HPP_INCLUDED odeint/util/multi_array_adaption.hpp 0000644 00000006645 15125237305 0013741 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/multi_array_adaption.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_UTIL_MULTI_ARRAY_ADAPTION_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_UTIL_MULTI_ARRAY_ADAPTION_HPP_DEFINED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/mpl/and.hpp> #include <boost/mpl/bool.hpp> #include <boost/multi_array.hpp> namespace boost { namespace numeric { namespace odeint { template< typename T > struct is_multi_array { typedef boost::false_type type; const static bool value = type::value; }; template< typename T > struct is_resizeable_multi_array { typedef boost::false_type type; const static bool value = type::value; }; template< typename V , size_t Dim , typename A > struct is_multi_array< boost::multi_array< V , Dim , A > > { typedef boost::true_type type; const static bool value = type::value; }; template< typename V , size_t Dim , typename A > struct is_resizeable_multi_array< boost::multi_array< V , Dim , A > > { typedef boost::true_type type; const static bool value = type::value; }; template< typename T > struct is_resizeable_sfinae< T , typename boost::enable_if< typename is_resizeable_multi_array< T >::type >::type > { typedef boost::true_type type; const static bool value = type::value; }; template< typename T1 , typename T2 > struct same_size_impl_sfinae< T1 , T2 , typename boost::enable_if< typename boost::mpl::and_< is_multi_array< T1 > , is_multi_array< T2 > , boost::mpl::bool_< T1::dimensionality == T2::dimensionality > >::type >::type > { static bool same_size( T1 const &x1 , T2 const &x2 ) { for( size_t i=0 ; i<T1::dimensionality ; ++i ) { if( x1.shape()[i] != x2.shape()[i] ) return false; if( x1.index_bases()[i] != x2.index_bases()[i] ) return false; } return true; } }; template< typename T1 , typename T2 > struct resize_impl_sfinae< T1 , T2 , typename boost::enable_if< typename boost::mpl::and_< is_resizeable_multi_array< T1 > , is_multi_array< T2 > , boost::mpl::bool_< T1::dimensionality == T2::dimensionality > >::type >::type > { static void resize( T1 &x1 , const T2 &x2 ) { boost::array< int , T1::dimensionality > extents; for( size_t i=0 ; i<T1::dimensionality ; ++i ) extents[i] = x2.shape()[i]; x1.resize( extents ); boost::array< int , T1::dimensionality > origins; for( size_t i=0 ; i<T1::dimensionality ; ++i ) origins[i] = x2.index_bases()[i]; x1.reindex( origins ); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_MULTI_ARRAY_ADAPTION_HPP_DEFINED odeint/util/odeint_error.hpp 0000644 00000003000 15125237305 0012203 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/odeint_error.hpp [begin_description] Runtime Exceptions thrown by odeint [end_description] Copyright 2015 Mario Mulansky 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_ODEINT_UTIL_ODEINT_ERROR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_ODEINT_ERROR_HPP_INCLUDED #include <stdexcept> #include <string> namespace boost { namespace numeric { namespace odeint { /** * \brief Runtime error thrown by odeint */ class odeint_error : public std::runtime_error { public: odeint_error(const std::string &s) : std::runtime_error(s) { } }; /** * \brief Runtime error thrown from integrate routines * * This Error occures when too many iterations are performed in between two * observer calls in the integrate routines. */ class no_progress_error : public odeint_error { public: no_progress_error(const std::string &s) : odeint_error(s) { } }; /** * \brief Runtime error thrown during stepsize adjustment * * This Error occures when too many iterations are performed without finding * an appropriate new step size. This usually indicates non-continuous points * in the ODE. */ class step_adjustment_error : public odeint_error { public: step_adjustment_error(const std::string &s) : odeint_error(s) { } }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_ODEINT_ERROR_HPP_INCLUDED odeint/util/unit_helper.hpp 0000644 00000006211 15125237305 0012035 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/unit_helper.hpp [begin_description] Get and set the value of a unit. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_UTIL_UNIT_HELPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_UNIT_HELPER_HPP_INCLUDED #ifndef __CUDACC__ #include <boost/units/quantity.hpp> #include <boost/units/get_dimension.hpp> #include <boost/units/get_system.hpp> #endif namespace boost { namespace numeric { namespace odeint { namespace detail { template<class T , class Enabler = void > struct get_unit_value_impl { static T value(const T &t) { return t; } typedef T result_type; }; #ifndef __CUDACC__ template<class Unit , class T> struct get_unit_value_impl< boost::units::quantity< Unit , T> > { static T value( const boost::units::quantity< Unit , T> &t ) { return t.value(); } typedef T result_type; }; #endif template<class T , class V , class Enabler = void > struct set_unit_value_impl { static void set_value(T &t , const V &v) { t = v; } }; #ifndef __CUDACC__ template<class Unit , class T , class V> struct set_unit_value_impl<boost::units::quantity<Unit , T> , V> { static void set_value(boost::units::quantity<Unit , T> &t , const V &v) { t = boost::units::quantity<Unit , T>::from_value(v); } }; #endif } // namespace detail template<class T> typename detail::get_unit_value_impl<T>::result_type get_unit_value(const T &t) { return detail::get_unit_value_impl<T>::value(t); } template<class T , class V> void set_unit_value(T &t , const V &v) { return detail::set_unit_value_impl<T , V>::set_value(t , v); } template< class T > struct unit_value_type { typedef T type; }; #ifndef __CUDACC__ template< class Unit , class Y > struct unit_value_type< boost::units::quantity< Unit , Y > > { typedef Y type; }; #endif template< typename Time > struct inverse_time { typedef Time type; }; #ifndef __CUDACC__ template< typename Unit , typename Value > struct inverse_time< boost::units::quantity< Unit , Value > > { typedef boost::units::quantity< Unit , Value > time_type; typedef typename boost::units::get_dimension< time_type >::type dimension; typedef typename boost::units::get_system< time_type >::type system; typedef typename boost::mpl::divides< boost::units::dimensionless_type , dimension >::type inv_dimension; typedef boost::units::unit< inv_dimension , system > inv_unit; typedef boost::units::quantity< inv_unit , Value > type; }; #endif } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_UNIT_HELPER_HPP_INCLUDED odeint/util/same_instance.hpp 0000644 00000002224 15125237305 0012330 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/same_instance.hpp [begin_description] Basic check if two variables are the same instance [end_description] Copyright 2012 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_UTIL_SAME_INSTANCE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_SAME_INSTANCE_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { template< class T1 , class T2 , class Enabler=void > struct same_instance_impl { static bool same_instance( const T1& /* x1 */ , const T2& /* x2 */ ) { return false; } }; template< class T > struct same_instance_impl< T , T > { static bool same_instance( const T &x1 , const T &x2 ) { // check pointers return (&x1 == &x2); } }; template< class T1 , class T2 > bool same_instance( const T1 &x1 , const T2 &x2 ) { return same_instance_impl< T1 , T2 >::same_instance( x1 , x2 ); } } // namespace odeint } // namespace numeric } // namespace boost #endif odeint/util/detail/less_with_sign.hpp 0000644 00000003637 15125237305 0014013 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/detail/less_with_sign.hpp [begin_description] Helper function to compare times taking into account the sign of dt [end_description] Copyright 2012-2015 Mario Mulansky Copyright 2012 Karsten Ahnert 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_ODEINT_INTEGRATE_DETAIL_LESS_WITH_SIGN_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_LESS_WITH_SIGN_HPP_INCLUDED #include <limits> #include <boost/numeric/odeint/util/unit_helper.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { /** * return t1 < t2 if dt > 0 and t1 > t2 if dt < 0 with epsilon accuracy */ template< typename T > bool less_with_sign( T t1 , T t2 , T dt ) { if( get_unit_value(dt) > 0 ) //return t1 < t2; return t2-t1 > std::numeric_limits<T>::epsilon(); else //return t1 > t2; return t1-t2 > std::numeric_limits<T>::epsilon(); } /** * return t1 <= t2 if dt > 0 and t1 => t2 if dt < 0 with epsilon accuracy */ template< typename T > bool less_eq_with_sign( T t1 , T t2 , T dt ) { if( get_unit_value(dt) > 0 ) return t1-t2 <= std::numeric_limits<T>::epsilon(); else return t2-t1 <= std::numeric_limits<T>::epsilon(); } template< typename T > T min_abs( T t1 , T t2 ) { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); if( get_unit_value(t1)>0 ) return min BOOST_PREVENT_MACRO_SUBSTITUTION ( t1 , t2 ); else return max BOOST_PREVENT_MACRO_SUBSTITUTION ( t1 , t2 ); } template< typename T > T max_abs( T t1 , T t2 ) { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); if( get_unit_value(t1)>0 ) return max BOOST_PREVENT_MACRO_SUBSTITUTION ( t1 , t2 ); else return min BOOST_PREVENT_MACRO_SUBSTITUTION ( t1 , t2 ); } } } } } #endif odeint/util/detail/is_range.hpp 0000644 00000005230 15125237305 0012550 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/detail/is_range.hpp [begin_description] is_range implementation. Taken from the boost::range library. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Thorsten Ottosen 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_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include <cstddef> #include <boost/range/config.hpp> #include <boost/mpl/has_xxx.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/and.hpp> namespace boost { namespace numeric { namespace odeint { namespace range_detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator) BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator) } namespace detail { template< typename Range > struct is_range : boost::mpl::and_<range_detail::has_iterator<Range>, range_detail::has_const_iterator<Range> > { }; ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// template< typename iteratorT > struct is_range< std::pair<iteratorT,iteratorT> > : boost::mpl::true_ { }; template< typename iteratorT > struct is_range< const std::pair<iteratorT,iteratorT> > : boost::mpl::true_ { }; ////////////////////////////////////////////////////////////////////////// // array ////////////////////////////////////////////////////////////////////////// template< typename elementT, std::size_t sz > struct is_range< elementT[sz] > : boost::mpl::true_ { }; template< typename elementT, std::size_t sz > struct is_range< const elementT[sz] > : boost::mpl::true_ { }; ////////////////////////////////////////////////////////////////////////// // string ////////////////////////////////////////////////////////////////////////// template<> struct is_range< char* > : boost::mpl::true_ { }; template<> struct is_range< wchar_t* > : boost::mpl::true_ { }; template<> struct is_range< const char* > : boost::mpl::true_ { }; template<> struct is_range< const wchar_t* > : boost::mpl::true_ { }; template<> struct is_range< char* const > : boost::mpl::true_ { }; template<> struct is_range< wchar_t* const > : boost::mpl::true_ { }; template<> struct is_range< const char* const > : boost::mpl::true_ { }; template<> struct is_range< const wchar_t* const > : boost::mpl::true_ { }; } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED odeint/util/n_ary_helper.hpp 0000644 00000007755 15125237305 0012204 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/n_ary_helper.hpp Macros to generate scale_sumN and for_eachN functors. Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_UTIL_N_ARY_HELPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_N_ARY_HELPER_HPP_INCLUDED #include <boost/preprocessor/repetition.hpp> // like BOOST_PP_ENUM_SHIFTED but with a comma in front like _TRAILING #define BOOST_ODEINT_ENUM_TRAILING_SHIFTED_PARAMS(count, param) \ BOOST_PP_COMMA_IF(BOOST_PP_DEC(count)) \ BOOST_PP_ENUM_SHIFTED_PARAMS(count, param) #define BOOST_ODEINT_ENUM_TRAILING_SHIFTED_BINARY_PARAMS(count, p1, p2) \ BOOST_PP_COMMA_IF(BOOST_PP_DEC(count)) \ BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(count, p1, p2) // like BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(n, p1, p2) but p2 is shifted left. // generate "p1 ## 0 = p2, p1 ## 1 = p3 ## 0, p1 ## 2 = p3 ## 1" #define BOOST_ODEINT_ENUM_LSHIFTED_BINARY_PARAMS(count, p1, p2, p3) \ BOOST_PP_ENUM(count, BOOST_ODEINT_ENUM_LSHIFTED_BINARY_PARAMS_, (p1, p2, p3)) #define BOOST_ODEINT_ENUM_LSHIFTED_BINARY_PARAMS_(z, n, data) \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, data), n) \ BOOST_PP_IF(n, \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 2, data), BOOST_PP_DEC(n)), \ BOOST_PP_TUPLE_ELEM(3, 1, data)) // like BOOST_PP_ENUM_BINARY_PARAMS(n, p1, p2) but with statements. // "p1 ## 0 p2 ## 0 ; p1 ## 1 p2 ## 1 ; ..." #define BOOST_ODEINT_ENUM_BINARY_STATEMENTS(count, p1, p2) \ BOOST_PP_REPEAT(count, BOOST_ODEINT_ENUM_BINARY_STATEMENTS_, (p1, p2)) #define BOOST_ODEINT_ENUM_BINARY_STATEMENTS_(z, n, data) \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n) \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n) ; // like BOOST_PP_ENUM_BINARY_PARAMS(n, p1, p2) but p2 is in parens. // "p1 ## 0 (p2 ## 0) , p1 ## 1 (p2 ## 1) , ..." #define BOOST_ODEINT_ENUM_UNARY_CALLS(count, p1, p2) \ BOOST_PP_ENUM(count, BOOST_ODEINT_ENUM_UNARY_CALLS_, (p1, p2)) #define BOOST_ODEINT_ENUM_SHIFTED_UNARY_CALLS(count, p1, p2) \ BOOST_PP_ENUM_SHIFTED(count, BOOST_ODEINT_ENUM_UNARY_CALLS_, (p1, p2)) #define BOOST_ODEINT_ENUM_TRAILING_SHIFTED_UNARY_CALLS(count, p1, p2) \ BOOST_PP_COMMA_IF(BOOST_PP_DEC(count)) \ BOOST_PP_ENUM_SHIFTED(count, BOOST_ODEINT_ENUM_UNARY_CALLS_, (p1, p2)) #define BOOST_ODEINT_ENUM_UNARY_CALLS_(z, n, data) \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n) \ ( BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n) ) // maximum arity + 1 for scale_sum and for_each #define BOOST_ODEINT_N_ARY_MAX 16 // generate scale_sum1 to scale_sumN, operator body generated by macro(N) #define BOOST_ODEINT_GEN_SCALE_SUM(macro) \ BOOST_PP_REPEAT_FROM_TO(1, BOOST_ODEINT_N_ARY_MAX, BOOST_ODEINT_GEN_SCALE_SUM_, macro) #define BOOST_ODEINT_GEN_SCALE_SUM_(z, n, macro) \ template< BOOST_ODEINT_ENUM_LSHIFTED_BINARY_PARAMS(n, class Fac, = double, = Fac) > \ struct BOOST_PP_CAT(scale_sum, n) \ { \ BOOST_ODEINT_ENUM_BINARY_STATEMENTS(n, const Fac, m_alpha) \ \ BOOST_PP_CAT(scale_sum, n) \ ( BOOST_PP_ENUM_BINARY_PARAMS(n, Fac, alpha) ) \ : BOOST_ODEINT_ENUM_UNARY_CALLS(n, m_alpha, alpha) {} \ \ template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), class T) > \ void operator()( T0 &t0 \ BOOST_ODEINT_ENUM_TRAILING_SHIFTED_BINARY_PARAMS(BOOST_PP_INC(n), const T, &t) \ ) const \ { macro(n) } \ typedef void result_type; \ }; // generate for_each1 to for_eachN, body generated by macro(N) #define BOOST_ODEINT_GEN_FOR_EACH(macro) \ BOOST_PP_REPEAT_FROM_TO(1, BOOST_ODEINT_N_ARY_MAX, BOOST_ODEINT_GEN_FOR_EACH_, macro) #define BOOST_ODEINT_GEN_FOR_EACH_(z, n, macro) \ template< BOOST_PP_ENUM_PARAMS(n, class S) , class Op > \ static void for_each##n ( BOOST_PP_ENUM_BINARY_PARAMS(n, S, &s) , Op op ) \ { macro(n) } #endif odeint/util/ublas_wrapper.hpp 0000644 00000023241 15125237305 0012367 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/ublas_wrapper.hpp [begin_description] Resizing for ublas::vector and ublas::matrix [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert 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_ODEINT_UTIL_UBLAS_WRAPPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_UBLAS_WRAPPER_HPP_INCLUDED #include <boost/type_traits/integral_constant.hpp> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/lu.hpp> #include <boost/numeric/ublas/vector_expression.hpp> #include <boost/numeric/ublas/matrix_expression.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> /* extend ublas by a few operations */ /* map norm_inf onto reduce( v , default_operations::maximum ) */ namespace boost { namespace numeric { namespace odeint { template< typename T , typename A > struct vector_space_norm_inf< boost::numeric::ublas::vector<T,A> > { typedef T result_type; result_type operator()( const boost::numeric::ublas::vector<T,A> &x ) const { return boost::numeric::ublas::norm_inf( x ); } }; template< class T , class L , class A > struct vector_space_norm_inf< boost::numeric::ublas::matrix<T,L,A> > { typedef T result_type; result_type operator()( const boost::numeric::ublas::matrix<T,L,A> &x ) const { return boost::numeric::ublas::norm_inf( x ); } }; } } } /* additional operations: * abs( v ) * v / w * a + v */ namespace boost { namespace numeric { namespace ublas { // elementwise abs - calculates absolute values of the elements template<class T> struct scalar_abs: 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) { using std::abs; return abs (t); } }; // (abs v) [i] = abs (v [i]) template<class E> BOOST_UBLAS_INLINE typename vector_unary_traits<E, scalar_abs<typename E::value_type> >::result_type abs (const vector_expression<E> &e) { typedef typename vector_unary_traits<E, scalar_abs<typename E::value_type> >::expression_type expression_type; return expression_type (e ()); } // (abs m) [i] = abs (m [i]) template<class E> BOOST_UBLAS_INLINE typename matrix_unary1_traits<E, scalar_abs<typename E::value_type> >::result_type abs (const matrix_expression<E> &e) { typedef typename matrix_unary1_traits<E, scalar_abs<typename E::value_type> >::expression_type expression_type; return expression_type (e ()); } // elementwise division (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 operator / (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 ()); } // elementwise division (m1 / m2) [i] = m1 [i] / m2 [i] 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 operator / (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 ()); } // addition with scalar // (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_plus<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_plus<T1, typename E2::value_type> >::expression_type expression_type; return expression_type (e1, e2 ()); } // addition with scalar // (t + m) [i] = t + m [i] 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_plus<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_plus<T1, typename E2::value_type> >::expression_type expression_type; return expression_type (e1, e2 ()); } } } } /* add resize functionality */ namespace boost { namespace numeric { namespace odeint { /* * resizeable specialization for boost::numeric::ublas::vector */ template< class T , class A > struct is_resizeable< boost::numeric::ublas::vector< T , A > > { typedef boost::true_type type; const static bool value = type::value; }; /* * resizeable specialization for boost::numeric::ublas::matrix */ template< class T , class L , class A > struct is_resizeable< boost::numeric::ublas::matrix< T , L , A > > { typedef boost::true_type type; const static bool value = type::value; }; /* * resizeable specialization for boost::numeric::ublas::permutation_matrix */ template< class T , class A > struct is_resizeable< boost::numeric::ublas::permutation_matrix< T , A > > { typedef boost::true_type type; const static bool value = type::value; }; // specialization for ublas::matrix // same size and resize specialization for matrix-matrix resizing template< class T , class L , class A , class T2 , class L2 , class A2 > struct same_size_impl< boost::numeric::ublas::matrix< T , L , A > , boost::numeric::ublas::matrix< T2 , L2 , A2 > > { static bool same_size( const boost::numeric::ublas::matrix< T , L , A > &m1 , const boost::numeric::ublas::matrix< T2 , L2 , A2 > &m2 ) { return ( ( m1.size1() == m2.size1() ) && ( m1.size2() == m2.size2() ) ); } }; template< class T , class L , class A , class T2 , class L2 , class A2 > struct resize_impl< boost::numeric::ublas::matrix< T , L , A > , boost::numeric::ublas::matrix< T2 , L2 , A2 > > { static void resize( boost::numeric::ublas::matrix< T , L , A > &m1 , const boost::numeric::ublas::matrix< T2 , L2 , A2 > &m2 ) { m1.resize( m2.size1() , m2.size2() ); } }; // same size and resize specialization for matrix-vector resizing template< class T , class L , class A , class T_V , class A_V > struct same_size_impl< boost::numeric::ublas::matrix< T , L , A > , boost::numeric::ublas::vector< T_V , A_V > > { static bool same_size( const boost::numeric::ublas::matrix< T , L , A > &m , const boost::numeric::ublas::vector< T_V , A_V > &v ) { return ( ( m.size1() == v.size() ) && ( m.size2() == v.size() ) ); } }; template< class T , class L , class A , class T_V , class A_V > struct resize_impl< boost::numeric::ublas::matrix< T , L , A > , boost::numeric::ublas::vector< T_V , A_V > > { static void resize( boost::numeric::ublas::matrix< T , L , A > &m , const boost::numeric::ublas::vector< T_V , A_V > &v ) { m.resize( v.size() , v.size() ); } }; // specialization for ublas::permutation_matrix // same size and resize specialization for matrix-vector resizing template< class T , class A , class T_V , class A_V > struct same_size_impl< boost::numeric::ublas::permutation_matrix< T , A > , boost::numeric::ublas::vector< T_V , A_V > > { static bool same_size( const boost::numeric::ublas::permutation_matrix< T , A > &m , const boost::numeric::ublas::vector< T_V , A_V > &v ) { return ( m.size() == v.size() ); // && ( m.size2() == v.size() ) ); } }; template< class T , class A , class T_V , class A_V > struct resize_impl< boost::numeric::ublas::vector< T_V , A_V > , boost::numeric::ublas::permutation_matrix< T , A > > { static void resize( const boost::numeric::ublas::vector< T_V , A_V > &v, boost::numeric::ublas::permutation_matrix< T , A > &m ) { m.resize( v.size() , v.size() ); } }; template< class T , class A > struct state_wrapper< boost::numeric::ublas::permutation_matrix< T , A > > // with resizing { typedef boost::numeric::ublas::permutation_matrix< T , A > state_type; typedef state_wrapper< state_type > state_wrapper_type; state_type m_v; state_wrapper() : m_v( 1 ) // permutation matrix constructor requires a size, choose 1 as default { } }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_UBLAS_WRAPPER_HPP_INCLUDED odeint/util/same_size.hpp 0000644 00000005772 15125237305 0011511 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/state_wrapper.hpp [begin_description] State wrapper for the state type in all stepper. The state wrappers are responsible for construction, destruction, copying construction, assignment and resizing. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_UTIL_SAME_SIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_SAME_SIZE_HPP_INCLUDED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/utility/enable_if.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <boost/fusion/include/zip_view.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/make_fused.hpp> #include <boost/fusion/include/all.hpp> #include <boost/range.hpp> namespace boost { namespace numeric { namespace odeint { template< typename State1 , typename State2 , class Enabler = void > struct same_size_impl_sfinae { static bool same_size( const State1 &x1 , const State2 &x2 ) { return ( boost::size( x1 ) == boost::size( x2 ) ); } }; // same_size function // standard implementation relies on boost.range template< class State1 , class State2 > struct same_size_impl { static bool same_size( const State1 &x1 , const State2 &x2 ) { return same_size_impl_sfinae< State1 , State2 >::same_size( x1 , x2 ); } }; // do not overload or specialize this function, specialize resize_impl<> instead template< class State1 , class State2 > bool same_size( const State1 &x1 , const State2 &x2 ) { return same_size_impl< State1 , State2 >::same_size( x1 , x2 ); } namespace detail { struct same_size_fusion { typedef bool result_type; template< class S1 , class S2 > bool operator()( const S1 &x1 , const S2 &x2 ) const { return same_size_op( x1 , x2 , typename is_resizeable< S1 >::type() ); } template< class S1 , class S2 > bool same_size_op( const S1 &x1 , const S2 &x2 , boost::true_type ) const { return same_size( x1 , x2 ); } template< class S1 , class S2 > bool same_size_op( const S1 &/*x1*/ , const S2 &/*x2*/ , boost::false_type ) const { return true; } }; } // namespace detail template< class FusionSeq > struct same_size_impl_sfinae< FusionSeq , FusionSeq , typename boost::enable_if< typename boost::fusion::traits::is_sequence< FusionSeq >::type >::type > { static bool same_size( const FusionSeq &x1 , const FusionSeq &x2 ) { typedef boost::fusion::vector< const FusionSeq& , const FusionSeq& > Sequences; Sequences sequences( x1 , x2 ); return boost::fusion::all( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( detail::same_size_fusion() ) ); } }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_SAME_SIZE_HPP_INCLUDED odeint/util/is_resizeable.hpp 0000644 00000004066 15125237305 0012345 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/is_resizeable.hpp [begin_description] Metafunction to determine if a state type can resized. For usage in the steppers. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_UTIL_IS_RESIZEABLE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_IS_RESIZEABLE_HPP_INCLUDED #include <vector> #include <boost/type_traits/integral_constant.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/fusion/include/front.hpp> #include <boost/fusion/include/is_sequence.hpp> #include <boost/mpl/find_if.hpp> #include <boost/mpl/end.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/if.hpp> #include <boost/type_traits/is_same.hpp> namespace boost { namespace numeric { namespace odeint { /* * by default any type is not resizable */ template< typename Container , typename Enabler = void > struct is_resizeable_sfinae : boost::false_type {}; template< typename Container > struct is_resizeable : is_resizeable_sfinae< Container > {}; /* * specialization for std::vector */ template< class V, class A > struct is_resizeable< std::vector< V , A > > : boost::true_type {}; /* * sfinae specialization for fusion sequences */ template< typename FusionSequence > struct is_resizeable_sfinae< FusionSequence , typename boost::enable_if< typename boost::fusion::traits::is_sequence< FusionSequence >::type >::type > { typedef typename boost::mpl::find_if< FusionSequence , is_resizeable< boost::mpl::_1 > >::type iter; typedef typename boost::mpl::end< FusionSequence >::type last; typedef typename boost::mpl::if_< boost::is_same< iter , last > , boost::false_type , boost::true_type >::type type; const static bool value = type::value; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_UTIL_IS_RESIZEABLE_HPP_INCLUDED odeint/util/unwrap_reference.hpp 0000644 00000004612 15125237305 0013054 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/unwrap_reference.hpp [begin_description] unwrap_reference [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_UTIL_UNWRAP_REFERENCE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_UNWRAP_REFERENCE_HPP_INCLUDED #include <boost/numeric/odeint/config.hpp> #if BOOST_NUMERIC_ODEINT_CXX11 #include <functional> #else #include <boost/ref.hpp> #endif namespace boost { #if BOOST_NUMERIC_ODEINT_CXX11 template<typename T> class reference_wrapper; template<typename T> struct unwrap_reference; #endif namespace numeric { namespace odeint { #if BOOST_NUMERIC_ODEINT_CXX11 template<typename T> struct unwrap_reference { typedef typename std::remove_reference<T>::type type; }; template<typename T> struct unwrap_reference< std::reference_wrapper<T> > { typedef typename std::remove_reference<T>::type type; }; template<typename T> struct unwrap_reference< boost::reference_wrapper<T> > { typedef typename boost::unwrap_reference<T>::type type; }; #else using ::boost::unwrap_reference; #endif namespace detail { #if BOOST_NUMERIC_ODEINT_CXX11 using ::std::ref; #else using ::boost::ref; #endif } } } } /* * * the following is the suggested way, but unfortunately it does not work with all compilers. */ /* #include <boost/config.hpp> #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL #include <boost/ref.hpp> #else #include <functional> #endif namespace boost { namespace numeric { namespace odeint { #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL template<typename T> struct unwrap_reference { typedef typename std::remove_reference<T>::type type; }; template<typename T> struct unwrap_reference< std::reference_wrapper<T> > { typedef typename std::remove_reference<T>::type type; }; template<typename T> struct unwrap_reference< boost::reference_wrapper<T> > { typedef typename boost::unwrap_reference<T>::type type; }; #else using ::boost::unwrap_reference; #endif } } } namespace boost { namespace numeric { namespace odeint { namespace detail { #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL using ::std::ref; #else using ::boost::ref; #endif } } } } */ #endif // BOOST_NUMERIC_ODEINT_UTIL_UNWRAP_REFERENCE_HPP_INCLUDED odeint/util/state_wrapper.hpp 0000644 00000002112 15125237305 0012373 0 ustar 00 /* [auto_generated] boost/numeric/odeint/util/state_wrapper.hpp [begin_description] State wrapper for the state type in all stepper. The state wrappers are responsible for construction, destruction, copying construction, assignment and resizing. [end_description] Copyright 2011-2012 Mario Mulansky Copyright 2011-2013 Karsten Ahnert 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_ODEINT_UTIL_STATE_WRAPPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_UTIL_STATE_WRAPPER_HPP_INCLUDED #include <boost/type_traits/integral_constant.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> namespace boost { namespace numeric { namespace odeint { template< class V , class Enabler = void > struct state_wrapper { typedef state_wrapper< V > state_wrapper_type; V m_v; }; } } } #endif // BOOST_NUMERIC_ODEINT_UTIL_STATE_WRAPPER_HPP_INCLUDED odeint/stepper/euler.hpp 0000644 00000014673 15125237305 0011353 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/euler.hpp [begin_description] Implementation of the classical explicit Euler stepper. This method is really simple and should only be used for demonstration purposes. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2013 Mario Mulansky 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_ODEINT_STEPPER_EULER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_EULER_HPP_INCLUDED #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class euler : public explicit_stepper_base< euler< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 1 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class euler : public explicit_stepper_base #endif { public : #ifndef DOXYGEN_SKIP typedef explicit_stepper_base< euler< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 1 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_stepper_base< euler< ... > , ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; #endif euler( const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) { } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System /* system */ , const StateIn &in , const DerivIn &dxdt , time_type /* t */ , StateOut &out , time_type dt ) { stepper_base_type::m_algebra.for_each3( out , in , dxdt , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , dt ) ); } template< class StateOut , class StateIn1 , class StateIn2 > void calc_state( StateOut &x , time_type t , const StateIn1 &old_state , time_type t_old , const StateIn2 & /*current_state*/ , time_type /* t_new */ ) const { const time_type delta = t - t_old; stepper_base_type::m_algebra.for_each3( x , old_state , stepper_base_type::m_dxdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , delta ) ); } template< class StateType > void adjust_size( const StateType &x ) { stepper_base_type::adjust_size( x ); } }; /********** DOXYGEN ***********/ /** * \class euler * \brief An implementation of the Euler method. * * The Euler method is a very simply solver for ordinary differential equations. This method should not be used * for real applications. It is only useful for demonstration purposes. Step size control is not provided but * trivial continuous output is available. * * This class derives from explicit_stepper_base and inherits its interface via CRTP (current recurring template pattern), * see explicit_stepper_base * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn euler::euler( const algebra_type &algebra ) * \brief Constructs the euler class. This constructor can be used as a default * constructor of the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn euler::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out of place, hence the input is in `in` and the output in `out`. * Access to this step functionality is provided by explicit_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn euler::calc_state( StateOut &x , time_type t , const StateIn1 &old_state , time_type t_old , const StateIn2 ¤t_state , time_type t_new ) const * \brief This method is used for continuous output and it calculates the state `x` at a time `t` from the * knowledge of two states `old_state` and `current_state` at time points `t_old` and `t_new`. */ /** * \fn euler::adjust_size( const StateType &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_EULER_HPP_INCLUDED odeint/stepper/runge_kutta_cash_karp54_classic.hpp 0000644 00000033756 15125237305 0016457 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta_cash_karp54_classic.hpp [begin_description] Classical implementation of the Runge-Kutta Cash-Karp 5(4) method. [end_description] Copyright 2010-2013 Mario Mulansky Copyright 2010-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/stepper/base/explicit_error_stepper_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class runge_kutta_cash_karp54_classic : public explicit_error_stepper_base< runge_kutta_cash_karp54_classic< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class runge_kutta_cash_karp54_classic : public explicit_error_stepper_base #endif { public : #ifndef DOXYGEN_SKIP typedef explicit_error_stepper_base< runge_kutta_cash_karp54_classic< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_error_stepper_base< runge_kutta_cash_karp54_classic< ... > , ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_base_type::stepper_type stepper_type; #endif runge_kutta_cash_karp54_classic( const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) { } template< class System , class StateIn , class DerivIn , class StateOut , class Err > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) { const value_type c1 = static_cast<value_type> ( 37 ) / static_cast<value_type>( 378 ); const value_type c3 = static_cast<value_type> ( 250 ) / static_cast<value_type>( 621 ); const value_type c4 = static_cast<value_type> ( 125 ) / static_cast<value_type>( 594 ); const value_type c6 = static_cast<value_type> ( 512 ) / static_cast<value_type>( 1771 ); const value_type dc1 = c1 - static_cast<value_type> ( 2825 ) / static_cast<value_type>( 27648 ); const value_type dc3 = c3 - static_cast<value_type> ( 18575 ) / static_cast<value_type>( 48384 ); const value_type dc4 = c4 - static_cast<value_type> ( 13525 ) / static_cast<value_type>( 55296 ); const value_type dc5 = static_cast<value_type> ( -277 ) / static_cast<value_type>( 14336 ); const value_type dc6 = c6 - static_cast<value_type> ( 1 ) / static_cast<value_type> ( 4 ); do_step_impl( system , in , dxdt , t , out , dt ); //error estimate stepper_base_type::m_algebra.for_each6( xerr , dxdt , m_k3.m_v , m_k4.m_v , m_k5.m_v , m_k6.m_v , typename operations_type::template scale_sum5< time_type , time_type , time_type , time_type , time_type >( dt*dc1 , dt*dc3 , dt*dc4 , dt*dc5 , dt*dc6 )); } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { const value_type a2 = static_cast<value_type> ( 1 ) / static_cast<value_type> ( 5 ); const value_type a3 = static_cast<value_type> ( 3 ) / static_cast<value_type> ( 10 ); const value_type a4 = static_cast<value_type> ( 3 ) / static_cast<value_type> ( 5 ); const value_type a5 = static_cast<value_type> ( 1 ); const value_type a6 = static_cast<value_type> ( 7 ) / static_cast<value_type> ( 8 ); const value_type b21 = static_cast<value_type> ( 1 ) / static_cast<value_type> ( 5 ); const value_type b31 = static_cast<value_type> ( 3 ) / static_cast<value_type>( 40 ); const value_type b32 = static_cast<value_type> ( 9 ) / static_cast<value_type>( 40 ); const value_type b41 = static_cast<value_type> ( 3 ) / static_cast<value_type> ( 10 ); const value_type b42 = static_cast<value_type> ( -9 ) / static_cast<value_type> ( 10 ); const value_type b43 = static_cast<value_type> ( 6 ) / static_cast<value_type> ( 5 ); const value_type b51 = static_cast<value_type> ( -11 ) / static_cast<value_type>( 54 ); const value_type b52 = static_cast<value_type> ( 5 ) / static_cast<value_type> ( 2 ); const value_type b53 = static_cast<value_type> ( -70 ) / static_cast<value_type>( 27 ); const value_type b54 = static_cast<value_type> ( 35 ) / static_cast<value_type>( 27 ); const value_type b61 = static_cast<value_type> ( 1631 ) / static_cast<value_type>( 55296 ); const value_type b62 = static_cast<value_type> ( 175 ) / static_cast<value_type>( 512 ); const value_type b63 = static_cast<value_type> ( 575 ) / static_cast<value_type>( 13824 ); const value_type b64 = static_cast<value_type> ( 44275 ) / static_cast<value_type>( 110592 ); const value_type b65 = static_cast<value_type> ( 253 ) / static_cast<value_type>( 4096 ); const value_type c1 = static_cast<value_type> ( 37 ) / static_cast<value_type>( 378 ); const value_type c3 = static_cast<value_type> ( 250 ) / static_cast<value_type>( 621 ); const value_type c4 = static_cast<value_type> ( 125 ) / static_cast<value_type>( 594 ); const value_type c6 = static_cast<value_type> ( 512 ) / static_cast<value_type>( 1771 ); typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); //m_x1 = x + dt*b21*dxdt stepper_base_type::m_algebra.for_each3( m_x_tmp.m_v , in , dxdt , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , dt*b21 ) ); sys( m_x_tmp.m_v , m_k2.m_v , t + dt*a2 ); // m_x_tmp = x + dt*b31*dxdt + dt*b32*m_x2 stepper_base_type::m_algebra.for_each4( m_x_tmp.m_v , in , dxdt , m_k2.m_v , typename operations_type::template scale_sum3< value_type , time_type , time_type >( 1.0 , dt*b31 , dt*b32 )); sys( m_x_tmp.m_v , m_k3.m_v , t + dt*a3 ); // m_x_tmp = x + dt * (b41*dxdt + b42*m_x2 + b43*m_x3) stepper_base_type::m_algebra.for_each5( m_x_tmp.m_v , in , dxdt , m_k2.m_v , m_k3.m_v , typename operations_type::template scale_sum4< value_type , time_type , time_type , time_type >( 1.0 , dt*b41 , dt*b42 , dt*b43 )); sys( m_x_tmp.m_v, m_k4.m_v , t + dt*a4 ); stepper_base_type::m_algebra.for_each6( m_x_tmp.m_v , in , dxdt , m_k2.m_v , m_k3.m_v , m_k4.m_v , typename operations_type::template scale_sum5< value_type , time_type , time_type , time_type , time_type >( 1.0 , dt*b51 , dt*b52 , dt*b53 , dt*b54 )); sys( m_x_tmp.m_v , m_k5.m_v , t + dt*a5 ); stepper_base_type::m_algebra.for_each7( m_x_tmp.m_v , in , dxdt , m_k2.m_v , m_k3.m_v , m_k4.m_v , m_k5.m_v , typename operations_type::template scale_sum6< value_type , time_type , time_type , time_type , time_type , time_type >( 1.0 , dt*b61 , dt*b62 , dt*b63 , dt*b64 , dt*b65 )); sys( m_x_tmp.m_v , m_k6.m_v , t + dt*a6 ); stepper_base_type::m_algebra.for_each6( out , in , dxdt , m_k3.m_v , m_k4.m_v , m_k6.m_v , typename operations_type::template scale_sum5< value_type , time_type , time_type , time_type , time_type >( 1.0 , dt*c1 , dt*c3 , dt*c4 , dt*c6 )); } /** * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x_tmp , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_k2 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k3 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k4 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k5 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k6 , x , typename is_resizeable<deriv_type>::type() ); return resized; } wrapped_state_type m_x_tmp; wrapped_deriv_type m_k2, m_k3, m_k4, m_k5, m_k6; resizer_type m_resizer; }; /************ DOXYGEN *************/ /** * \class runge_kutta_cash_karp54_classic * \brief The Runge-Kutta Cash-Karp method implemented without the generic Runge-Kutta algorithm. * * The Runge-Kutta Cash-Karp method is one of the standard methods for * solving ordinary differential equations, see * <a href="http://en.wikipedia.org/wiki/Cash%E2%80%93Karp_method">en.wikipedia.org/wiki/Cash-Karp_method</a>. * The method is explicit and fulfills the Error Stepper concept. Step size control * is provided but continuous output is not available for this method. * * This class derives from explicit_error_stepper_base and inherits its interface via CRTP (current recurring * template pattern). This class implements the method directly, hence the generic Runge-Kutta algorithm is not used. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta_cash_karp54_classic::runge_kutta_cash_karp54_classic( const algebra_type &algebra ) * \brief Constructs the runge_kutta_cash_karp54_classic class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn runge_kutta_cash_karp54_classic::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * * The result is updated out-of-place, hence the input is in `in` and the output in `out`. Futhermore, an * estimation of the error is stored in `xerr`. * Access to this step functionality is provided by explicit_error_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. * \param xerr The result of the error estimation is written in xerr. */ /** * \fn runge_kutta_cash_karp54_classic::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out-of-place, hence the input is in `in` and the output in `out`. * Access to this step functionality is provided by explicit_error_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED odeint/stepper/runge_kutta_cash_karp54.hpp 0000644 00000020744 15125237305 0014747 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp [begin_description] Implementation of the Runge Kutta Cash Karp 5(4) method. It uses the generic error stepper. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert 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_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED #include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/generation/make_vector.hpp> #include <boost/numeric/odeint/stepper/explicit_error_generic_rk.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP template< class Value = double > struct rk54_ck_coefficients_a1 : boost::array< Value , 1 > { rk54_ck_coefficients_a1( void ) { (*this)[0] = static_cast< Value >( 1 )/static_cast< Value >( 5 ); } }; template< class Value = double > struct rk54_ck_coefficients_a2 : boost::array< Value , 2 > { rk54_ck_coefficients_a2( void ) { (*this)[0] = static_cast<Value>( 3 )/static_cast<Value>( 40 ); (*this)[1] = static_cast<Value>( 9 )/static_cast<Value>( 40 ); } }; template< class Value = double > struct rk54_ck_coefficients_a3 : boost::array< Value , 3 > { rk54_ck_coefficients_a3( void ) { (*this)[0] = static_cast<Value>( 3 )/static_cast<Value>( 10 ); (*this)[1] = static_cast<Value>( -9 )/static_cast<Value>( 10 ); (*this)[2] = static_cast<Value>( 6 )/static_cast<Value>( 5 ); } }; template< class Value = double > struct rk54_ck_coefficients_a4 : boost::array< Value , 4 > { rk54_ck_coefficients_a4( void ) { (*this)[0] = static_cast<Value>( -11 )/static_cast<Value>( 54 ); (*this)[1] = static_cast<Value>( 5 )/static_cast<Value>( 2 ); (*this)[2] = static_cast<Value>( -70 )/static_cast<Value>( 27 ); (*this)[3] = static_cast<Value>( 35 )/static_cast<Value>( 27 ); } }; template< class Value = double > struct rk54_ck_coefficients_a5 : boost::array< Value , 5 > { rk54_ck_coefficients_a5( void ) { (*this)[0] = static_cast<Value>( 1631 )/static_cast<Value>( 55296 ); (*this)[1] = static_cast<Value>( 175 )/static_cast<Value>( 512 ); (*this)[2] = static_cast<Value>( 575 )/static_cast<Value>( 13824 ); (*this)[3] = static_cast<Value>( 44275 )/static_cast<Value>( 110592 ); (*this)[4] = static_cast<Value>( 253 )/static_cast<Value>( 4096 ); } }; template< class Value = double > struct rk54_ck_coefficients_b : boost::array< Value , 6 > { rk54_ck_coefficients_b( void ) { (*this)[0] = static_cast<Value>( 37 )/static_cast<Value>( 378 ); (*this)[1] = static_cast<Value>( 0 ); (*this)[2] = static_cast<Value>( 250 )/static_cast<Value>( 621 ); (*this)[3] = static_cast<Value>( 125 )/static_cast<Value>( 594 ); (*this)[4] = static_cast<Value>( 0 ); (*this)[5] = static_cast<Value>( 512 )/static_cast<Value>( 1771 ); } }; template< class Value = double > struct rk54_ck_coefficients_db : boost::array< Value , 6 > { rk54_ck_coefficients_db( void ) { (*this)[0] = static_cast<Value>( 37 )/static_cast<Value>( 378 ) - static_cast<Value>( 2825 )/static_cast<Value>( 27648 ); (*this)[1] = static_cast<Value>( 0 ); (*this)[2] = static_cast<Value>( 250 )/static_cast<Value>( 621 ) - static_cast<Value>( 18575 )/static_cast<Value>( 48384 ); (*this)[3] = static_cast<Value>( 125 )/static_cast<Value>( 594 ) - static_cast<Value>( 13525 )/static_cast<Value>( 55296 ); (*this)[4] = static_cast<Value>( -277 )/static_cast<Value>( 14336 ); (*this)[5] = static_cast<Value>( 512 )/static_cast<Value>( 1771 ) - static_cast<Value>( 1 )/static_cast<Value>( 4 ); } }; template< class Value = double > struct rk54_ck_coefficients_c : boost::array< Value , 6 > { rk54_ck_coefficients_c( void ) { (*this)[0] = static_cast<Value>(0); (*this)[1] = static_cast<Value>( 1 )/static_cast<Value>( 5 ); (*this)[2] = static_cast<Value>( 3 )/static_cast<Value>( 10 ); (*this)[3] = static_cast<Value>( 3 )/static_cast<Value>( 5 ); (*this)[4] = static_cast<Value>( 1 ); (*this)[5] = static_cast<Value>( 7 )/static_cast<Value>( 8 ); } }; #endif template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class runge_kutta_cash_karp54 : public explicit_error_generic_rk< 6 , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class runge_kutta_cash_karp54 : public explicit_error_generic_rk #endif { public: #ifndef DOXYGEN_SKIP typedef explicit_error_generic_rk< 6 , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_typ; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; #endif runge_kutta_cash_karp54( const algebra_type &algebra = algebra_type() ) : stepper_base_type( boost::fusion::make_vector( rk54_ck_coefficients_a1<Value>() , rk54_ck_coefficients_a2<Value>() , rk54_ck_coefficients_a3<Value>() , rk54_ck_coefficients_a4<Value>() , rk54_ck_coefficients_a5<Value>() ) , rk54_ck_coefficients_b<Value>() , rk54_ck_coefficients_db<Value>() , rk54_ck_coefficients_c<Value>() , algebra ) { } }; /********** DOXYGEN **********/ /** * \class runge_kutta_cash_karp54 * \brief The Runge-Kutta Cash-Karp method. * * The Runge-Kutta Cash-Karp method is one of the standard methods for * solving ordinary differential equations, see * <a href="http://en.wikipedia.org/wiki/Cash%E2%80%93Karp_methods">en.wikipedia.org/wiki/Cash-Karp_methods</a>. * The method is explicit and fulfills the Error Stepper concept. Step size control * is provided but continuous output is not available for this method. * * This class derives from explicit_error_stepper_base and inherits its interface via CRTP (current recurring template pattern). * Furthermore, it derivs from explicit_error_generic_rk which is a generic Runge-Kutta algorithm with error estimation. * For more details see explicit_error_stepper_base and explicit_error_generic_rk. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta_cash_karp54::runge_kutta_cash_karp54( const algebra_type &algebra ) * \brief Constructs the runge_kutta_cash_karp54 class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED odeint/stepper/adams_bashforth_moulton.hpp 0000644 00000027357 15125237305 0015144 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp [begin_description] Implementation of the Adams-Bashforth-Moulton method, a predictor-corrector multistep method. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/adams_bashforth.hpp> #include <boost/numeric/odeint/stepper/adams_moulton.hpp> namespace boost { namespace numeric { namespace odeint { template< size_t Steps , class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer, class InitializingStepper = runge_kutta4< State , Value , Deriv , Time , Algebra , Operations, Resizer > > class adams_bashforth_moulton { #ifndef DOXYGEN_SKIP BOOST_STATIC_ASSERT(( Steps > 0 )); BOOST_STATIC_ASSERT(( Steps < 9 )); #endif public : typedef State state_type; typedef state_wrapper< state_type > wrapped_state_type; typedef Value value_type; typedef Deriv deriv_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef InitializingStepper initializing_stepper_type; static const size_t steps = Steps; #ifndef DOXYGEN_SKIP typedef adams_bashforth< steps , state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type, initializing_stepper_type > adams_bashforth_type; typedef adams_moulton< steps , state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type > adams_moulton_type; typedef adams_bashforth_moulton< steps , state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type , initializing_stepper_type> stepper_type; #endif //DOXYGEN_SKIP typedef unsigned short order_type; static const order_type order_value = steps; /** \brief Constructs the adams_bashforth class. */ adams_bashforth_moulton( void ) : m_adams_bashforth() , m_adams_moulton( m_adams_bashforth.algebra() ) , m_x() , m_resizer() { } adams_bashforth_moulton( const algebra_type &algebra ) : m_adams_bashforth( algebra ) , m_adams_moulton( m_adams_bashforth.algebra() ) , m_x() , m_resizer() { } order_type order( void ) const { return order_value; } template< class System , class StateInOut > void do_step( System system , StateInOut &x , time_type t , time_type dt ) { do_step_impl1( system , x , t , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &x , time_type t , time_type dt ) { do_step_impl1( system , x , t , dt ); } template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , const StateOut &out , time_type dt ) { do_step_impl2( system , in , t , out , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateOut. */ template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { do_step_impl2( system , in ,t , out , dt ); } template< class StateType > void adjust_size( const StateType &x ) { m_adams_bashforth.adjust_size( x ); m_adams_moulton.adjust_size( x ); resize_impl( x ); } template< class ExplicitStepper , class System , class StateIn > void initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) { m_adams_bashforth.initialize( explicit_stepper , system , x , t , dt ); } template< class System , class StateIn > void initialize( System system , StateIn &x , time_type &t , time_type dt ) { m_adams_bashforth.initialize( system , x , t , dt ); } void reset(void) { m_adams_bashforth.reset(); } private: template< typename System , typename StateInOut > void do_step_impl1( System system , StateInOut &x , time_type t , time_type dt ) { if( m_adams_bashforth.is_initialized() ) { m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); m_adams_bashforth.do_step( system , x , t , m_x.m_v , dt ); m_adams_moulton.do_step( system , x , m_x.m_v , t+dt , x , dt , m_adams_bashforth.step_storage() ); } else { m_adams_bashforth.do_step( system , x , t , dt ); } } template< typename System , typename StateIn , typename StateInOut > void do_step_impl2( System system , StateIn const &in , time_type t , StateInOut & out , time_type dt ) { if( m_adams_bashforth.is_initialized() ) { m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); m_adams_bashforth.do_step( system , in , t , m_x.m_v , dt ); m_adams_moulton.do_step( system , in , m_x.m_v , t+dt , out , dt , m_adams_bashforth.step_storage() ); } else { m_adams_bashforth.do_step( system , in , t , out , dt ); } } template< class StateIn > bool resize_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_x , x , typename is_resizeable< state_type >::type() ); } adams_bashforth_type m_adams_bashforth; adams_moulton_type m_adams_moulton; wrapped_state_type m_x; resizer_type m_resizer; }; /********* DOXYGEN ********/ /** * \class adams_bashforth_moulton * \brief The Adams-Bashforth-Moulton multistep algorithm. * * The Adams-Bashforth method is a multi-step predictor-corrector algorithm * with configurable step number. The step number is specified as template * parameter Steps and it then uses the result from the previous Steps steps. * See also * <a href="http://en.wikipedia.org/wiki/Linear_multistep_method">en.wikipedia.org/wiki/Linear_multistep_method</a>. * Currently, a maximum of Steps=8 is supported. * The method is explicit and fulfills the Stepper concept. Step size control * or continuous output are not provided. * * This class derives from algebra_base and inherits its interface via * CRTP (current recurring template pattern). For more details see * algebra_stepper_base. * * \tparam Steps The number of steps (maximal 8). * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. * \tparam InitializingStepper The stepper for the first two steps. */ /** * \fn adams_bashforth_moulton::adams_bashforth_moulton( const algebra_type &algebra ) * \brief Constructs the adams_bashforth class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored. */ /** * \fn adams_bashforth_moulton::order( void ) const * \brief Returns the order of the algorithm, which is equal to the number of steps+1. * \return order of the method. */ /** * \fn adams_bashforth_moulton::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn adams_bashforth_moulton::do_step( System system , const StateIn &in , time_type t , const StateOut &out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn adams_bashforth_moulton::adjust_size( const StateType &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ /** * \fn adams_bashforth_moulton::initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) * \brief Initialized the stepper. Does Steps-1 steps with the explicit_stepper to fill the buffer. * \note The state x and time t are updated to the values after Steps-1 initial steps. * \param explicit_stepper the stepper used to fill the buffer of previous step results * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The initial state of the ODE which should be solved, updated after in this method. * \param t The initial time, updated in this method. * \param dt The step size. */ /** * \fn adams_bashforth_moulton::initialize( System system , StateIn &x , time_type &t , time_type dt ) * \brief Initialized the stepper. Does Steps-1 steps using the standard initializing stepper * of the underlying adams_bashforth stepper. * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn adams_bashforth_moulton::reset( void ) * \brief Resets the internal buffers of the stepper. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED odeint/stepper/stepper_categories.hpp 0000644 00000004162 15125237305 0014116 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/stepper_categories.hpp [begin_description] Definition of all stepper categories. [end_description] Copyright 2010-2011 Mario Mulansky Copyright 2010-2012 Karsten Ahnert 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_ODEINT_STEPPER_STEPPER_CATEGORIES_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_STEPPER_CATEGORIES_HPP_INCLUDED #include <boost/type_traits/integral_constant.hpp> namespace boost { namespace numeric { namespace odeint { /* * Tags to specify stepper types * * These tags are used by integrate() to choose which integration method is used */ struct stepper_tag {}; // struct explicit_stepper_tag : stepper_tag {}; // struct implicit_stepper_tag : stepper_tag {}; struct error_stepper_tag : stepper_tag {}; struct explicit_error_stepper_tag : error_stepper_tag {}; struct explicit_error_stepper_fsal_tag : error_stepper_tag {}; struct controlled_stepper_tag {}; struct explicit_controlled_stepper_tag : controlled_stepper_tag {}; struct explicit_controlled_stepper_fsal_tag : controlled_stepper_tag {}; struct dense_output_stepper_tag {}; template< class tag > struct base_tag ; template< > struct base_tag< stepper_tag > { typedef stepper_tag type; }; template< > struct base_tag< error_stepper_tag > { typedef stepper_tag type; }; template< > struct base_tag< explicit_error_stepper_tag > { typedef stepper_tag type; }; template< > struct base_tag< explicit_error_stepper_fsal_tag > { typedef stepper_tag type; }; template< > struct base_tag< controlled_stepper_tag > { typedef controlled_stepper_tag type; }; template< > struct base_tag< explicit_controlled_stepper_tag > { typedef controlled_stepper_tag type; }; template< > struct base_tag< explicit_controlled_stepper_fsal_tag > { typedef controlled_stepper_tag type; }; template< > struct base_tag< dense_output_stepper_tag > { typedef dense_output_stepper_tag type; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_STEPPER_CATEGORIES_HPP_INCLUDED odeint/stepper/rosenbrock4.hpp 0000644 00000034412 15125237305 0012463 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/rosenbrock4.hpp [begin_description] Implementation of the Rosenbrock 4 method for solving stiff ODEs. Note, that a controller and a dense-output stepper exist for this method, [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2012 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_ROSENBROCK4_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_HPP_INCLUDED #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/lu.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/ublas_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/lu.hpp> namespace boost { namespace numeric { namespace odeint { /* * ToDo: * * 2. Interfacing for odeint, check if controlled_error_stepper can be used * 3. dense output */ template< class Value > struct default_rosenbrock_coefficients { typedef Value value_type; typedef unsigned short order_type; default_rosenbrock_coefficients( void ) : gamma ( static_cast< value_type >( 0.25 ) ) , d1 ( static_cast< value_type >( 0.25 ) ) , d2 ( static_cast< value_type >( -0.1043 ) ) , d3 ( static_cast< value_type >( 0.1035 ) ) , d4 ( static_cast< value_type >( 0.3620000000000023e-01 ) ) , c2 ( static_cast< value_type >( 0.386 ) ) , c3 ( static_cast< value_type >( 0.21 ) ) , c4 ( static_cast< value_type >( 0.63 ) ) , c21 ( static_cast< value_type >( -0.5668800000000000e+01 ) ) , a21 ( static_cast< value_type >( 0.1544000000000000e+01 ) ) , c31 ( static_cast< value_type >( -0.2430093356833875e+01 ) ) , c32 ( static_cast< value_type >( -0.2063599157091915e+00 ) ) , a31 ( static_cast< value_type >( 0.9466785280815826e+00 ) ) , a32 ( static_cast< value_type >( 0.2557011698983284e+00 ) ) , c41 ( static_cast< value_type >( -0.1073529058151375e+00 ) ) , c42 ( static_cast< value_type >( -0.9594562251023355e+01 ) ) , c43 ( static_cast< value_type >( -0.2047028614809616e+02 ) ) , a41 ( static_cast< value_type >( 0.3314825187068521e+01 ) ) , a42 ( static_cast< value_type >( 0.2896124015972201e+01 ) ) , a43 ( static_cast< value_type >( 0.9986419139977817e+00 ) ) , c51 ( static_cast< value_type >( 0.7496443313967647e+01 ) ) , c52 ( static_cast< value_type >( -0.1024680431464352e+02 ) ) , c53 ( static_cast< value_type >( -0.3399990352819905e+02 ) ) , c54 ( static_cast< value_type >( 0.1170890893206160e+02 ) ) , a51 ( static_cast< value_type >( 0.1221224509226641e+01 ) ) , a52 ( static_cast< value_type >( 0.6019134481288629e+01 ) ) , a53 ( static_cast< value_type >( 0.1253708332932087e+02 ) ) , a54 ( static_cast< value_type >( -0.6878860361058950e+00 ) ) , c61 ( static_cast< value_type >( 0.8083246795921522e+01 ) ) , c62 ( static_cast< value_type >( -0.7981132988064893e+01 ) ) , c63 ( static_cast< value_type >( -0.3152159432874371e+02 ) ) , c64 ( static_cast< value_type >( 0.1631930543123136e+02 ) ) , c65 ( static_cast< value_type >( -0.6058818238834054e+01 ) ) , d21 ( static_cast< value_type >( 0.1012623508344586e+02 ) ) , d22 ( static_cast< value_type >( -0.7487995877610167e+01 ) ) , d23 ( static_cast< value_type >( -0.3480091861555747e+02 ) ) , d24 ( static_cast< value_type >( -0.7992771707568823e+01 ) ) , d25 ( static_cast< value_type >( 0.1025137723295662e+01 ) ) , d31 ( static_cast< value_type >( -0.6762803392801253e+00 ) ) , d32 ( static_cast< value_type >( 0.6087714651680015e+01 ) ) , d33 ( static_cast< value_type >( 0.1643084320892478e+02 ) ) , d34 ( static_cast< value_type >( 0.2476722511418386e+02 ) ) , d35 ( static_cast< value_type >( -0.6594389125716872e+01 ) ) {} const value_type gamma; const value_type d1 , d2 , d3 , d4; const value_type c2 , c3 , c4; const value_type c21 ; const value_type a21; const value_type c31 , c32; const value_type a31 , a32; const value_type c41 , c42 , c43; const value_type a41 , a42 , a43; const value_type c51 , c52 , c53 , c54; const value_type a51 , a52 , a53 , a54; const value_type c61 , c62 , c63 , c64 , c65; const value_type d21 , d22 , d23 , d24 , d25; const value_type d31 , d32 , d33 , d34 , d35; static const order_type stepper_order = 4; static const order_type error_order = 3; }; template< class Value , class Coefficients = default_rosenbrock_coefficients< Value > , class Resizer = initially_resizer > class rosenbrock4 { private: public: typedef Value value_type; typedef boost::numeric::ublas::vector< value_type > state_type; typedef state_type deriv_type; typedef value_type time_type; typedef boost::numeric::ublas::matrix< value_type > matrix_type; typedef boost::numeric::ublas::permutation_matrix< size_t > pmatrix_type; typedef Resizer resizer_type; typedef Coefficients rosenbrock_coefficients; typedef stepper_tag stepper_category; typedef unsigned short order_type; typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef state_wrapper< matrix_type > wrapped_matrix_type; typedef state_wrapper< pmatrix_type > wrapped_pmatrix_type; typedef rosenbrock4< Value , Coefficients , Resizer > stepper_type; const static order_type stepper_order = rosenbrock_coefficients::stepper_order; const static order_type error_order = rosenbrock_coefficients::error_order; rosenbrock4( void ) : m_resizer() , m_x_err_resizer() , m_jac() , m_pm() , m_dfdt() , m_dxdt() , m_dxdtnew() , m_g1() , m_g2() , m_g3() , m_g4() , m_g5() , m_cont3() , m_cont4() , m_xtmp() , m_x_err() , m_coef() { } order_type order() const { return stepper_order; } template< class System > void do_step( System system , const state_type &x , time_type t , state_type &xout , time_type dt , state_type &xerr ) { // get the system and jacobi function typedef typename odeint::unwrap_reference< System >::type system_type; typedef typename odeint::unwrap_reference< typename system_type::first_type >::type deriv_func_type; typedef typename odeint::unwrap_reference< typename system_type::second_type >::type jacobi_func_type; system_type &sys = system; deriv_func_type &deriv_func = sys.first; jacobi_func_type &jacobi_func = sys.second; const size_t n = x.size(); m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl<state_type> , detail::ref( *this ) , detail::_1 ) ); for( size_t i=0 ; i<n ; ++i ) m_pm.m_v( i ) = i; deriv_func( x , m_dxdt.m_v , t ); jacobi_func( x , m_jac.m_v , t , m_dfdt.m_v ); m_jac.m_v *= -1.0; m_jac.m_v += 1.0 / m_coef.gamma / dt * boost::numeric::ublas::identity_matrix< value_type >( n ); boost::numeric::ublas::lu_factorize( m_jac.m_v , m_pm.m_v ); for( size_t i=0 ; i<n ; ++i ) m_g1.m_v[i] = m_dxdt.m_v[i] + dt * m_coef.d1 * m_dfdt.m_v[i]; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , m_g1.m_v ); for( size_t i=0 ; i<n ; ++i ) m_xtmp.m_v[i] = x[i] + m_coef.a21 * m_g1.m_v[i]; deriv_func( m_xtmp.m_v , m_dxdtnew.m_v , t + m_coef.c2 * dt ); for( size_t i=0 ; i<n ; ++i ) m_g2.m_v[i] = m_dxdtnew.m_v[i] + dt * m_coef.d2 * m_dfdt.m_v[i] + m_coef.c21 * m_g1.m_v[i] / dt; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , m_g2.m_v ); for( size_t i=0 ; i<n ; ++i ) m_xtmp.m_v[i] = x[i] + m_coef.a31 * m_g1.m_v[i] + m_coef.a32 * m_g2.m_v[i]; deriv_func( m_xtmp.m_v , m_dxdtnew.m_v , t + m_coef.c3 * dt ); for( size_t i=0 ; i<n ; ++i ) m_g3.m_v[i] = m_dxdtnew.m_v[i] + dt * m_coef.d3 * m_dfdt.m_v[i] + ( m_coef.c31 * m_g1.m_v[i] + m_coef.c32 * m_g2.m_v[i] ) / dt; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , m_g3.m_v ); for( size_t i=0 ; i<n ; ++i ) m_xtmp.m_v[i] = x[i] + m_coef.a41 * m_g1.m_v[i] + m_coef.a42 * m_g2.m_v[i] + m_coef.a43 * m_g3.m_v[i]; deriv_func( m_xtmp.m_v , m_dxdtnew.m_v , t + m_coef.c4 * dt ); for( size_t i=0 ; i<n ; ++i ) m_g4.m_v[i] = m_dxdtnew.m_v[i] + dt * m_coef.d4 * m_dfdt.m_v[i] + ( m_coef.c41 * m_g1.m_v[i] + m_coef.c42 * m_g2.m_v[i] + m_coef.c43 * m_g3.m_v[i] ) / dt; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , m_g4.m_v ); for( size_t i=0 ; i<n ; ++i ) m_xtmp.m_v[i] = x[i] + m_coef.a51 * m_g1.m_v[i] + m_coef.a52 * m_g2.m_v[i] + m_coef.a53 * m_g3.m_v[i] + m_coef.a54 * m_g4.m_v[i]; deriv_func( m_xtmp.m_v , m_dxdtnew.m_v , t + dt ); for( size_t i=0 ; i<n ; ++i ) m_g5.m_v[i] = m_dxdtnew.m_v[i] + ( m_coef.c51 * m_g1.m_v[i] + m_coef.c52 * m_g2.m_v[i] + m_coef.c53 * m_g3.m_v[i] + m_coef.c54 * m_g4.m_v[i] ) / dt; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , m_g5.m_v ); for( size_t i=0 ; i<n ; ++i ) m_xtmp.m_v[i] += m_g5.m_v[i]; deriv_func( m_xtmp.m_v , m_dxdtnew.m_v , t + dt ); for( size_t i=0 ; i<n ; ++i ) xerr[i] = m_dxdtnew.m_v[i] + ( m_coef.c61 * m_g1.m_v[i] + m_coef.c62 * m_g2.m_v[i] + m_coef.c63 * m_g3.m_v[i] + m_coef.c64 * m_g4.m_v[i] + m_coef.c65 * m_g5.m_v[i] ) / dt; boost::numeric::ublas::lu_substitute( m_jac.m_v , m_pm.m_v , xerr ); for( size_t i=0 ; i<n ; ++i ) xout[i] = m_xtmp.m_v[i] + xerr[i]; } template< class System > void do_step( System system , state_type &x , time_type t , time_type dt , state_type &xerr ) { do_step( system , x , t , x , dt , xerr ); } /* * do_step without error output - just calls above functions with and neglects the error estimate */ template< class System > void do_step( System system , const state_type &x , time_type t , state_type &xout , time_type dt ) { m_x_err_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_x_err<state_type> , detail::ref( *this ) , detail::_1 ) ); do_step( system , x , t , xout , dt , m_x_err.m_v ); } template< class System > void do_step( System system , state_type &x , time_type t , time_type dt ) { m_x_err_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_x_err<state_type> , detail::ref( *this ) , detail::_1 ) ); do_step( system , x , t , dt , m_x_err.m_v ); } void prepare_dense_output() { const size_t n = m_g1.m_v.size(); for( size_t i=0 ; i<n ; ++i ) { m_cont3.m_v[i] = m_coef.d21 * m_g1.m_v[i] + m_coef.d22 * m_g2.m_v[i] + m_coef.d23 * m_g3.m_v[i] + m_coef.d24 * m_g4.m_v[i] + m_coef.d25 * m_g5.m_v[i]; m_cont4.m_v[i] = m_coef.d31 * m_g1.m_v[i] + m_coef.d32 * m_g2.m_v[i] + m_coef.d33 * m_g3.m_v[i] + m_coef.d34 * m_g4.m_v[i] + m_coef.d35 * m_g5.m_v[i]; } } void calc_state( time_type t , state_type &x , const state_type &x_old , time_type t_old , const state_type &x_new , time_type t_new ) { const size_t n = m_g1.m_v.size(); time_type dt = t_new - t_old; time_type s = ( t - t_old ) / dt; time_type s1 = 1.0 - s; for( size_t i=0 ; i<n ; ++i ) x[i] = x_old[i] * s1 + s * ( x_new[i] + s1 * ( m_cont3.m_v[i] + s * m_cont4.m_v[i] ) ); } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); resize_x_err( x ); } protected: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_dfdt , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdtnew , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_xtmp , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_g1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_g2 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_g3 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_g4 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_g5 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_cont3 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_cont4 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_jac , x , typename is_resizeable<matrix_type>::type() ); resized |= adjust_size_by_resizeability( m_pm , x , typename is_resizeable<pmatrix_type>::type() ); return resized; } template< class StateIn > bool resize_x_err( const StateIn &x ) { return adjust_size_by_resizeability( m_x_err , x , typename is_resizeable<state_type>::type() ); } private: resizer_type m_resizer; resizer_type m_x_err_resizer; wrapped_matrix_type m_jac; wrapped_pmatrix_type m_pm; wrapped_deriv_type m_dfdt , m_dxdt , m_dxdtnew; wrapped_state_type m_g1 , m_g2 , m_g3 , m_g4 , m_g5; wrapped_state_type m_cont3 , m_cont4; wrapped_state_type m_xtmp; wrapped_state_type m_x_err; const rosenbrock_coefficients m_coef; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_HPP_INCLUDED odeint/stepper/velocity_verlet.hpp 0000644 00000032350 15125237305 0013446 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/velocity_verlet.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/resizer.hpp> // #include <boost/numeric/odeint/util/is_pair.hpp> // #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { template < class Coor , class Velocity = Coor , class Value = double , class Acceleration = Coor , class Time = Value , class TimeSq = Time , class Algebra = typename algebra_dispatcher< Coor >::algebra_type , class Operations = typename operations_dispatcher< Coor >::operations_type , class Resizer = initially_resizer > class velocity_verlet : public algebra_stepper_base< Algebra , Operations > { public: typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef typename algebra_stepper_base_type::operations_type operations_type; typedef Coor coor_type; typedef Velocity velocity_type; typedef Acceleration acceleration_type; typedef std::pair< coor_type , velocity_type > state_type; typedef std::pair< velocity_type , acceleration_type > deriv_type; typedef state_wrapper< acceleration_type > wrapped_acceleration_type; typedef Value value_type; typedef Time time_type; typedef TimeSq time_square_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef unsigned short order_type; static const order_type order_value = 1; /** * \return Returns the order of the stepper. */ order_type order( void ) const { return order_value; } velocity_verlet( const algebra_type & algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) , m_first_call( true ) , m_a1() , m_a2() , m_current_a1( true ) { } template< class System , class StateInOut > void do_step( System system , StateInOut & x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } template< class System , class StateInOut > void do_step( System system , const StateInOut & x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } template< class System , class CoorIn , class VelocityIn , class AccelerationIn , class CoorOut , class VelocityOut , class AccelerationOut > void do_step( System system , CoorIn const & qin , VelocityIn const & pin , AccelerationIn const & ain , CoorOut & qout , VelocityOut & pout , AccelerationOut & aout , time_type t , time_type dt ) { const value_type one = static_cast< value_type >( 1.0 ); const value_type one_half = static_cast< value_type >( 0.5 ); algebra_stepper_base_type::m_algebra.for_each4( qout , qin , pin , ain , typename operations_type::template scale_sum3< value_type , time_type , time_square_type >( one , one * dt , one_half * dt * dt ) ); typename odeint::unwrap_reference< System >::type & sys = system; sys( qout , pin , aout , t + dt ); algebra_stepper_base_type::m_algebra.for_each4( pout , pin , ain , aout , typename operations_type::template scale_sum3< value_type , time_type , time_type >( one , one_half * dt , one_half * dt ) ); } template< class StateIn > void adjust_size( const StateIn & x ) { if( resize_impl( x ) ) m_first_call = true; } void reset( void ) { m_first_call = true; } /** * \fn velocity_verlet::initialize( const AccelerationIn &qin ) * \brief Initializes the internal state of the stepper. * \param deriv The acceleration of x. The next call of `do_step` expects that the acceleration of `x` passed to `do_step` * has the value of `qin`. */ template< class AccelerationIn > void initialize( const AccelerationIn & ain ) { // alloc a m_resizer.adjust_size( ain , detail::bind( &velocity_verlet::template resize_impl< AccelerationIn > , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::copy( ain , get_current_acc() ); m_first_call = false; } template< class System , class CoorIn , class VelocityIn > void initialize( System system , const CoorIn & qin , const VelocityIn & pin , time_type t ) { m_resizer.adjust_size( qin , detail::bind( &velocity_verlet::template resize_impl< CoorIn > , detail::ref( *this ) , detail::_1 ) ); initialize_acc( system , qin , pin , t ); } bool is_initialized( void ) const { return ! m_first_call; } private: template< class System , class CoorIn , class VelocityIn > void initialize_acc( System system , const CoorIn & qin , const VelocityIn & pin , time_type t ) { typename odeint::unwrap_reference< System >::type & sys = system; sys( qin , pin , get_current_acc() , t ); m_first_call = false; } template< class System , class StateInOut > void do_step_v1( System system , StateInOut & x , time_type t , time_type dt ) { typedef typename odeint::unwrap_reference< StateInOut >::type state_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type; typedef typename boost::remove_reference< coor_in_type >::type xyz_type; state_in_type & statein = x; coor_in_type & qinout = statein.first; momentum_in_type & pinout = statein.second; // alloc a if( m_resizer.adjust_size( qinout , detail::bind( &velocity_verlet::template resize_impl< xyz_type > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize_acc( system , qinout , pinout , t ); } // check first do_step( system , qinout , pinout , get_current_acc() , qinout , pinout , get_old_acc() , t , dt ); toggle_current_acc(); } template< class StateIn > bool resize_impl( const StateIn & x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_a1 , x , typename is_resizeable< acceleration_type >::type() ); resized |= adjust_size_by_resizeability( m_a2 , x , typename is_resizeable< acceleration_type >::type() ); return resized; } acceleration_type & get_current_acc( void ) { return m_current_a1 ? m_a1.m_v : m_a2.m_v ; } const acceleration_type & get_current_acc( void ) const { return m_current_a1 ? m_a1.m_v : m_a2.m_v ; } acceleration_type & get_old_acc( void ) { return m_current_a1 ? m_a2.m_v : m_a1.m_v ; } const acceleration_type & get_old_acc( void ) const { return m_current_a1 ? m_a2.m_v : m_a1.m_v ; } void toggle_current_acc( void ) { m_current_a1 = ! m_current_a1; } resizer_type m_resizer; bool m_first_call; wrapped_acceleration_type m_a1 , m_a2; bool m_current_a1; }; /** * \class velocity_verlet * \brief The Velocity-Verlet algorithm. * * <a href="http://en.wikipedia.org/wiki/Verlet_integration" >The Velocity-Verlet algorithm</a> is a method for simulation of molecular dynamics systems. It solves the ODE * a=f(r,v',t) where r are the coordinates, v are the velocities and a are the accelerations, hence v = dr/dt, a=dv/dt. * * \tparam Coor The type representing the coordinates. * \tparam Velocity The type representing the velocities. * \tparam Value The type value type. * \tparam Acceleration The type representing the acceleration. * \tparam Time The time representing the independent variable - the time. * \tparam TimeSq The time representing the square of the time. * \tparam Algebra The algebra. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn velocity_verlet::velocity_verlet( const algebra_type &algebra ) * \brief Constructs the velocity_verlet class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored. */ /** * \fn velocity_verlet::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * It can be used like * \code * pair< coordinates , velocities > state; * stepper.do_step( sys , x , t , dt ); * \endcode * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Second Order System concept. * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn velocity_verlet::do_step( System system , const StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * It can be used like * \code * pair< coordinates , velocities > state; * stepper.do_step( sys , x , t , dt ); * \endcode * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Second Order System concept. * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn velocity_verlet::do_step( System system , CoorIn const & qin , VelocityIn const & pin , AccelerationIn const & ain , CoorOut & qout , VelocityOut & pout , AccelerationOut & aout , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. Additionally to the other methods * the coordinates, velocities and accelerations are passed directly to do_step and they are transformed out-of-place. * * It can be used like * \code * coordinates qin , qout; * velocities pin , pout; * accelerations ain, aout; * stepper.do_step( sys , qin , pin , ain , qout , pout , aout , t , dt ); * \endcode * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Second Order System concept. * \param x The state of the ODE which should be solved. The state is pair of Coor and Velocity. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn void velocity_verlet::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ /** * \fn velocity_verlet::reset( void ) * \brief Resets the internal state of this stepper. After calling this method it is safe to use all * `do_step` method without explicitly initializing the stepper. */ /** * \fn velocity_verlet::initialize( System system , const CoorIn &qin , const VelocityIn &pin , time_type t ) * \brief Initializes the internal state of the stepper. * * This method is equivalent to * \code * Acceleration a; * system( qin , pin , a , t ); * stepper.initialize( a ); * \endcode * * \param system The system function for the next calls of `do_step`. * \param qin The current coordinates of the ODE. * \param pin The current velocities of the ODE. * \param t The current time of the ODE. */ /** * \fn velocity_verlet::is_initialized() * \returns Returns if the stepper is initialized. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_VELOCITY_VERLET_HPP_DEFINED odeint/stepper/symplectic_rkn_sb3a_mclachlan.hpp 0000644 00000012415 15125237305 0016167 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/symplectic_rkn_sb3a_mclachlan.hpp [begin_description] Implementation of the symplectic MacLachlan stepper for separable Hamiltonian system. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky 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_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_MCLACHLAN_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_MCLACHLAN_HPP_INCLUDED #include <boost/numeric/odeint/stepper/base/symplectic_rkn_stepper_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP namespace detail { namespace symplectic_rkn_sb3a_mclachlan { /* exp( a1 t A ) exp( b1 t B ) exp( a2 t A ) exp( b2 t B ) exp( a3 t A ) exp( b3 t B ) exp( a3 t A ) exp( b2 t B ) exp( a2 t A ) exp( b1 t B ) exp( a1 t A ) */ template< class Value > struct coef_a_type : public boost::array< Value , 6 > { coef_a_type( void ) { (*this)[0] = static_cast< Value >( 0.40518861839525227722 ); (*this)[1] = static_cast< Value >( -0.28714404081652408900 ); (*this)[2] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ) - ( (*this)[0] + (*this)[1] ); (*this)[3] = (*this)[2]; (*this)[4] = (*this)[1]; (*this)[5] = (*this)[0]; } }; template< class Value > struct coef_b_type : public boost::array< Value , 6 > { coef_b_type( void ) { (*this)[0] = static_cast< Value >( -3 ) / static_cast< Value >( 73 ); (*this)[1] = static_cast< Value >( 17 ) / static_cast< Value >( 59 ); (*this)[2] = static_cast< Value >( 1 ) - static_cast< Value >( 2 ) * ( (*this)[0] + (*this)[1] ); (*this)[3] = (*this)[1]; (*this)[4] = (*this)[0]; (*this)[5] = static_cast< Value >( 0 ); } }; } // namespace symplectic_rkn_sb3a_mclachlan } // namespace detail #endif // DOXYGEN_SKIP template< class Coor , class Momentum = Coor , class Value = double , class CoorDeriv = Coor , class MomentumDeriv = Coor , class Time = Value , class Algebra = typename algebra_dispatcher< Coor >::algebra_type , class Operations = typename operations_dispatcher< Coor >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class symplectic_rkn_sb3a_mclachlan : public symplectic_nystroem_stepper_base < 6 , 4 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > #else class symplectic_rkn_sb3a_mclachlan : public symplectic_nystroem_stepper_base #endif { public: #ifndef DOXYGEN_SKIP typedef symplectic_nystroem_stepper_base < 6 , 4 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::value_type value_type; symplectic_rkn_sb3a_mclachlan( const algebra_type &algebra = algebra_type() ) : stepper_base_type( detail::symplectic_rkn_sb3a_mclachlan::coef_a_type< value_type >() , detail::symplectic_rkn_sb3a_mclachlan::coef_b_type< value_type >() , algebra ) { } }; /************* DOXYGEN ***********/ /** * \class symplectic_rkn_sb3a_mclachlan * \brief Implement of the symmetric B3A method of Runge-Kutta-Nystroem method of sixth order. * * The method is of fourth order and has six stages. It is described HERE. This method cannot be used * with multiprecision types since the coefficients are not defined analytically. * * ToDo Add reference to the paper. * * \tparam Order The order of the stepper. * \tparam Coor The type representing the coordinates q. * \tparam Momentum The type representing the coordinates p. * \tparam Value The basic value type. Should be something like float, double or a high-precision type. * \tparam CoorDeriv The type representing the time derivative of the coordinate dq/dt. * \tparam MomemtnumDeriv The type representing the time derivative of the momentum dp/dt. * \tparam Time The type representing the time t. * \tparam Algebra The algebra. * \tparam Operations The operations. * \tparam Resizer The resizer policy. */ /** * \fn symplectic_rkn_sb3a_mclachlan::symplectic_rkn_sb3a_mclachlan( const algebra_type &algebra ) * \brief Constructs the symplectic_rkn_sb3a_mclachlan. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_MCLACHLAN_HPP_INCLUDED odeint/stepper/dense_output_runge_kutta.hpp 0000644 00000034376 15125237305 0015367 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp [begin_description] Implementation of the Dense-output stepper for all steppers. Note, that this class does not computes the result but serves as an interface. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED #include <utility> #include <stdexcept> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> namespace boost { namespace numeric { namespace odeint { template< class Stepper , class StepperCategory = typename Stepper::stepper_category > class dense_output_runge_kutta; /** * \brief The class representing dense-output Runge-Kutta steppers. * \note In this stepper, the initialize method has to be called before using * the do_step method. * * The dense-output functionality allows to interpolate the solution between * subsequent integration points using intermediate results obtained during the * computation. This version works based on a normal stepper without step-size * control. * * * \tparam Stepper The stepper type of the underlying algorithm. */ template< class Stepper > class dense_output_runge_kutta< Stepper , stepper_tag > { public: /* * We do not need all typedefs. */ typedef Stepper stepper_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::algebra_type algebra_type; typedef typename stepper_type::operations_type operations_type; typedef typename stepper_type::resizer_type resizer_type; typedef dense_output_stepper_tag stepper_category; typedef dense_output_runge_kutta< Stepper > dense_output_stepper_type; /** * \brief Constructs the dense_output_runge_kutta class. An instance of the * underlying stepper can be provided. * \param stepper An instance of the underlying stepper. */ dense_output_runge_kutta( const stepper_type &stepper = stepper_type() ) : m_stepper( stepper ) , m_resizer() , m_x1() , m_x2() , m_current_state_x1( true ) , m_t() , m_t_old() , m_dt() { } /** * \brief Initializes the stepper. Has to be called before do_step can be * used to set the initial conditions and the step size. * \param x0 The initial state of the ODE which should be solved. * \param t0 The initial time, at which the step should be performed. * \param dt0 The step size. */ template< class StateType > void initialize( const StateType &x0 , time_type t0 , time_type dt0 ) { m_resizer.adjust_size( x0 , detail::bind( &dense_output_stepper_type::template resize_impl< StateType > , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::copy( x0 , get_current_state() ); m_t = t0; m_dt = dt0; } /** * \brief Does one time step. * \note initialize has to be called before using this method to set the * initial conditions x,t and the stepsize. * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \return Pair with start and end time of the integration step. */ template< class System > std::pair< time_type , time_type > do_step( System system ) { m_stepper.do_step( system , get_current_state() , m_t , get_old_state() , m_dt ); m_t_old = m_t; m_t += m_dt; toggle_current_state(); return std::make_pair( m_t_old , m_t ); } /* * The next two overloads are needed to solve the forwarding problem */ /** * \brief Calculates the solution at an intermediate point. * \param t The time at which the solution should be calculated, has to be * in the current time interval. * \param x The output variable where the result is written into. */ template< class StateOut > void calc_state( time_type t , StateOut &x ) const { if( t == current_time() ) { boost::numeric::odeint::copy( get_current_state() , x ); } m_stepper.calc_state( x , t , get_old_state() , m_t_old , get_current_state() , m_t ); } /** * \brief Calculates the solution at an intermediate point. Solves the forwarding problem * \param t The time at which the solution should be calculated, has to be * in the current time interval. * \param x The output variable where the result is written into, can be a boost range. */ template< class StateOut > void calc_state( time_type t , const StateOut &x ) const { m_stepper.calc_state( x , t , get_old_state() , m_t_old , get_current_state() , m_t ); } /** * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); m_stepper.stepper().resize( x ); } /** * \brief Returns the current state of the solution. * \return The current state of the solution x(t). */ const state_type& current_state( void ) const { return get_current_state(); } /** * \brief Returns the current time of the solution. * \return The current time of the solution t. */ time_type current_time( void ) const { return m_t; } /** * \brief Returns the last state of the solution. * \return The last state of the solution x(t-dt). */ const state_type& previous_state( void ) const { return get_old_state(); } /** * \brief Returns the last time of the solution. * \return The last time of the solution t-dt. */ time_type previous_time( void ) const { return m_t_old; } /** * \brief Returns the current time step. * \return dt. */ time_type current_time_step( void ) const { return m_dt; } private: state_type& get_current_state( void ) { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } const state_type& get_current_state( void ) const { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } state_type& get_old_state( void ) { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } const state_type& get_old_state( void ) const { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } void toggle_current_state( void ) { m_current_state_x1 = ! m_current_state_x1; } template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x2 , x , typename is_resizeable<state_type>::type() ); return resized; } stepper_type m_stepper; resizer_type m_resizer; wrapped_state_type m_x1 , m_x2; bool m_current_state_x1; // if true, the current state is m_x1 time_type m_t , m_t_old , m_dt; }; /** * \brief The class representing dense-output Runge-Kutta steppers with FSAL property. * * The interface is the same as for dense_output_runge_kutta< Stepper , stepper_tag >. * This class provides dense output functionality based on methods with step size controlled * * * \tparam Stepper The stepper type of the underlying algorithm. */ template< class Stepper > class dense_output_runge_kutta< Stepper , explicit_controlled_stepper_fsal_tag > { public: /* * We do not need all typedefs. */ typedef Stepper controlled_stepper_type; typedef typename controlled_stepper_type::stepper_type stepper_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::algebra_type algebra_type; typedef typename stepper_type::operations_type operations_type; typedef typename stepper_type::resizer_type resizer_type; typedef dense_output_stepper_tag stepper_category; typedef dense_output_runge_kutta< Stepper > dense_output_stepper_type; dense_output_runge_kutta( const controlled_stepper_type &stepper = controlled_stepper_type() ) : m_stepper( stepper ) , m_resizer() , m_current_state_x1( true ) , m_x1() , m_x2() , m_dxdt1() , m_dxdt2() , m_t() , m_t_old() , m_dt() , m_is_deriv_initialized( false ) { } template< class StateType > void initialize( const StateType &x0 , time_type t0 , time_type dt0 ) { m_resizer.adjust_size( x0 , detail::bind( &dense_output_stepper_type::template resize< StateType > , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::copy( x0 , get_current_state() ); m_t = t0; m_dt = dt0; m_is_deriv_initialized = false; } template< class System > std::pair< time_type , time_type > do_step( System system ) { if( !m_is_deriv_initialized ) { typename odeint::unwrap_reference< System >::type &sys = system; sys( get_current_state() , get_current_deriv() , m_t ); m_is_deriv_initialized = true; } failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails controlled_step_result res = fail; m_t_old = m_t; do { res = m_stepper.try_step( system , get_current_state() , get_current_deriv() , m_t , get_old_state() , get_old_deriv() , m_dt ); fail_checker(); // check for overflow of failed steps } while( res == fail ); toggle_current_state(); return std::make_pair( m_t_old , m_t ); } /* * The two overloads are needed in order to solve the forwarding problem. */ template< class StateOut > void calc_state( time_type t , StateOut &x ) const { m_stepper.stepper().calc_state( t , x , get_old_state() , get_old_deriv() , m_t_old , get_current_state() , get_current_deriv() , m_t ); } template< class StateOut > void calc_state( time_type t , const StateOut &x ) const { m_stepper.stepper().calc_state( t , x , get_old_state() , get_old_deriv() , m_t_old , get_current_state() , get_current_deriv() , m_t ); } template< class StateIn > bool resize( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x2 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdt1 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdt2 , x , typename is_resizeable<deriv_type>::type() ); return resized; } template< class StateType > void adjust_size( const StateType &x ) { resize( x ); m_stepper.stepper().resize( x ); } const state_type& current_state( void ) const { return get_current_state(); } time_type current_time( void ) const { return m_t; } const state_type& previous_state( void ) const { return get_old_state(); } time_type previous_time( void ) const { return m_t_old; } time_type current_time_step( void ) const { return m_dt; } private: state_type& get_current_state( void ) { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } const state_type& get_current_state( void ) const { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } state_type& get_old_state( void ) { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } const state_type& get_old_state( void ) const { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } deriv_type& get_current_deriv( void ) { return m_current_state_x1 ? m_dxdt1.m_v : m_dxdt2.m_v ; } const deriv_type& get_current_deriv( void ) const { return m_current_state_x1 ? m_dxdt1.m_v : m_dxdt2.m_v ; } deriv_type& get_old_deriv( void ) { return m_current_state_x1 ? m_dxdt2.m_v : m_dxdt1.m_v ; } const deriv_type& get_old_deriv( void ) const { return m_current_state_x1 ? m_dxdt2.m_v : m_dxdt1.m_v ; } void toggle_current_state( void ) { m_current_state_x1 = ! m_current_state_x1; } controlled_stepper_type m_stepper; resizer_type m_resizer; bool m_current_state_x1; wrapped_state_type m_x1 , m_x2; wrapped_deriv_type m_dxdt1 , m_dxdt2; time_type m_t , m_t_old , m_dt; bool m_is_deriv_initialized; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED odeint/stepper/symplectic_euler.hpp 0000644 00000007541 15125237305 0013603 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/symplectic_euler.hpp [begin_description] Implementation of the symplectic Euler for separable Hamiltonian systems. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky 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_ODEINT_STEPPER_SYMPLECTIC_EULER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_EULER_HPP_INCLUDED #include <boost/numeric/odeint/stepper/base/symplectic_rkn_stepper_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP namespace detail { namespace symplectic_euler_coef { template< class Value > struct coef_a_type : public boost::array< Value , 1 > { coef_a_type( void ) { (*this)[0] = static_cast< Value >( 1 ); } }; template< class Value > struct coef_b_type : public boost::array< Value , 1 > { coef_b_type( void ) { (*this)[0] = static_cast< Value >( 1 ); } }; } // namespace symplectic_euler_coef } // namespace detail #endif template< class Coor , class Momentum = Coor , class Value = double , class CoorDeriv = Coor , class MomentumDeriv = Coor , class Time = Value , class Algebra = typename algebra_dispatcher< Coor >::algebra_type , class Operations = typename operations_dispatcher< Coor >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class symplectic_euler : public symplectic_nystroem_stepper_base < 1 , 1 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > #else class symplectic_euler : public symplectic_nystroem_stepper_base #endif { public: #ifndef DOXYGEN_SKIP typedef symplectic_nystroem_stepper_base< 1 , 1 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::value_type value_type; symplectic_euler( const algebra_type &algebra = algebra_type() ) : stepper_base_type( detail::symplectic_euler_coef::coef_a_type< value_type >() , detail::symplectic_euler_coef::coef_b_type< value_type >() , algebra ) { } }; /*************** DOXYGEN ***************/ /** * \class symplectic_euler * \brief Implementation of the symplectic Euler method. * * The method is of first order and has one stage. It is described HERE. * * \tparam Order The order of the stepper. * \tparam Coor The type representing the coordinates q. * \tparam Momentum The type representing the coordinates p. * \tparam Value The basic value type. Should be something like float, double or a high-precision type. * \tparam CoorDeriv The type representing the time derivative of the coordinate dq/dt. * \tparam MomemtnumDeriv The type representing the time derivative of the momentum dp/dt. * \tparam Time The type representing the time t. * \tparam Algebra The algebra. * \tparam Operations The operations. * \tparam Resizer The resizer policy. */ /** * \fn symplectic_euler::symplectic_euler( const algebra_type &algebra ) * \brief Constructs the symplectic_euler. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_EULER_HPP_INCLUDED odeint/stepper/controlled_adams_bashforth_moulton.hpp 0000644 00000023540 15125237305 0017357 0 ustar 00 /* boost/numeric/odeint/stepper/detail/controlled_adams_bashforth_moulton.hpp [begin_description] Implemetation of an controlled adams bashforth moulton stepper. [end_description] Copyright 2017 Valentin Noah Hartmann 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_ODEINT_STEPPER_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <iostream> namespace boost { namespace numeric { namespace odeint { template< size_t MaxOrder, class State, class Value = double, class Algebra = typename algebra_dispatcher< State >::algebra_type > class default_order_adjuster { public: typedef State state_type; typedef Value value_type; typedef state_wrapper< state_type > wrapped_state_type; typedef Algebra algebra_type; default_order_adjuster( const algebra_type &algebra = algebra_type() ) : m_algebra( algebra ) {}; size_t adjust_order(size_t order, size_t init, boost::array<wrapped_state_type, 4> &xerr) { using std::abs; value_type errc = abs(m_algebra.norm_inf(xerr[2].m_v)); value_type errm1 = 3*errc; value_type errm2 = 3*errc; if(order > 2) { errm2 = abs(m_algebra.norm_inf(xerr[0].m_v)); } if(order >= 2) { errm1 = abs(m_algebra.norm_inf(xerr[1].m_v)); } size_t o_new = order; if(order == 2 && errm1 <= 0.5*errc) { o_new = order - 1; } else if(order > 2 && errm2 < errc && errm1 < errc) { o_new = order - 1; } if(init < order) { return order+1; } else if(o_new == order - 1) { return order-1; } else if(order <= MaxOrder) { value_type errp = abs(m_algebra.norm_inf(xerr[3].m_v)); if(order > 1 && errm1 < errc && errp) { return order-1; } else if(order < MaxOrder && errp < (0.5-0.25*order/MaxOrder) * errc) { return order+1; } } return order; }; private: algebra_type m_algebra; }; template< class ErrorStepper, class StepAdjuster = detail::pid_step_adjuster< typename ErrorStepper::state_type, typename ErrorStepper::value_type, typename ErrorStepper::deriv_type, typename ErrorStepper::time_type, typename ErrorStepper::algebra_type, typename ErrorStepper::operations_type, detail::H211PI >, class OrderAdjuster = default_order_adjuster< ErrorStepper::order_value, typename ErrorStepper::state_type, typename ErrorStepper::value_type, typename ErrorStepper::algebra_type >, class Resizer = initially_resizer > class controlled_adams_bashforth_moulton { public: typedef ErrorStepper stepper_type; static const typename stepper_type::order_type order_value = stepper_type::order_value; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::algebra_type algebra_type; typedef typename stepper_type::operations_type operations_type; typedef Resizer resizer_type; typedef StepAdjuster step_adjuster_type; typedef OrderAdjuster order_adjuster_type; typedef controlled_stepper_tag stepper_category; typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef boost::array< wrapped_state_type , 4 > error_storage_type; typedef typename stepper_type::coeff_type coeff_type; typedef controlled_adams_bashforth_moulton< ErrorStepper , StepAdjuster , OrderAdjuster , Resizer > controlled_stepper_type; controlled_adams_bashforth_moulton(step_adjuster_type step_adjuster = step_adjuster_type()) :m_stepper(), m_dxdt_resizer(), m_xerr_resizer(), m_xnew_resizer(), m_step_adjuster( step_adjuster ), m_order_adjuster() {}; template< class ExplicitStepper, class System > void initialize(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type dt) { m_stepper.initialize(stepper, system, inOut, t, dt); }; template< class System > void initialize(System system, state_type &inOut, time_type &t, time_type dt) { m_stepper.initialize(system, inOut, t, dt); }; template< class ExplicitStepper, class System > void initialize_controlled(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type &dt) { reset(); coeff_type &coeff = m_stepper.coeff(); m_dxdt_resizer.adjust_size( inOut , detail::bind( &controlled_stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); controlled_step_result res = fail; for( size_t i=0 ; i<order_value; ++i ) { do { res = stepper.try_step( system, inOut, t, dt ); } while(res != success); system( inOut , m_dxdt.m_v , t ); coeff.predict(t-dt, dt); coeff.do_step(m_dxdt.m_v); coeff.confirm(); if(coeff.m_eo < order_value) { ++coeff.m_eo; } } } template< class System > controlled_step_result try_step(System system, state_type & inOut, time_type &t, time_type &dt) { m_xnew_resizer.adjust_size( inOut , detail::bind( &controlled_stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); controlled_step_result res = try_step(system, inOut, t, m_xnew.m_v, dt); if(res == success) { boost::numeric::odeint::copy( m_xnew.m_v , inOut); } return res; }; template< class System > controlled_step_result try_step(System system, const state_type & in, time_type &t, state_type & out, time_type &dt) { m_xerr_resizer.adjust_size( in , detail::bind( &controlled_stepper_type::template resize_xerr_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); m_dxdt_resizer.adjust_size( in , detail::bind( &controlled_stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); m_stepper.do_step_impl(system, in, t, out, dt, m_xerr[2].m_v); coeff_type &coeff = m_stepper.coeff(); time_type dtPrev = dt; dt = m_step_adjuster.adjust_stepsize(coeff.m_eo, dt, m_xerr[2].m_v, out, m_stepper.dxdt() ); if(dt / dtPrev >= step_adjuster_type::threshold()) { system(out, m_dxdt.m_v, t+dtPrev); coeff.do_step(m_dxdt.m_v); coeff.confirm(); t += dtPrev; size_t eo = coeff.m_eo; // estimate errors for next step double factor = 1; algebra_type m_algebra; m_algebra.for_each2(m_xerr[2].m_v, coeff.phi[1][eo].m_v, typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo]))); if(eo > 1) { m_algebra.for_each2(m_xerr[1].m_v, coeff.phi[1][eo-1].m_v, typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo-1]))); } if(eo > 2) { m_algebra.for_each2(m_xerr[0].m_v, coeff.phi[1][eo-2].m_v, typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo-2]))); } if(eo < order_value && coeff.m_eo < coeff.m_steps_init-1) { m_algebra.for_each2(m_xerr[3].m_v, coeff.phi[1][eo+1].m_v, typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo+1]))); } // adjust order coeff.m_eo = m_order_adjuster.adjust_order(coeff.m_eo, coeff.m_steps_init-1, m_xerr); return success; } else { return fail; } }; void reset() { m_stepper.reset(); }; private: template< class StateType > bool resize_dxdt_impl( const StateType &x ) { return adjust_size_by_resizeability( m_dxdt, x, typename is_resizeable<deriv_type>::type() ); }; template< class StateType > bool resize_xerr_impl( const StateType &x ) { bool resized( false ); for(size_t i=0; i<m_xerr.size(); ++i) { resized |= adjust_size_by_resizeability( m_xerr[i], x, typename is_resizeable<state_type>::type() ); } return resized; }; template< class StateType > bool resize_xnew_impl( const StateType &x ) { return adjust_size_by_resizeability( m_xnew, x, typename is_resizeable<state_type>::type() ); }; stepper_type m_stepper; wrapped_deriv_type m_dxdt; error_storage_type m_xerr; wrapped_state_type m_xnew; resizer_type m_dxdt_resizer; resizer_type m_xerr_resizer; resizer_type m_xnew_resizer; step_adjuster_type m_step_adjuster; order_adjuster_type m_order_adjuster; }; } // odeint } // numeric } // boost #endif odeint/stepper/adams_moulton.hpp 0000644 00000013740 15125237305 0013073 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/adams_moulton.hpp [begin_description] Implementation of the Adams-Moulton method. This is method is not a real stepper, it is more a helper class which computes the corrector step in the Adams-Bashforth-Moulton method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2013 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_ADAMS_MOULTON_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_MOULTON_HPP_INCLUDED #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/runge_kutta4_classic.hpp> #include <boost/numeric/odeint/stepper/detail/adams_moulton_call_algebra.hpp> #include <boost/numeric/odeint/stepper/detail/adams_moulton_coefficients.hpp> #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp> namespace boost { namespace numeric { namespace odeint { /* * Static implicit Adams-Moulton multistep-solver without step size control and without dense output. */ template< size_t Steps , class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class adams_moulton { private: public : typedef State state_type; typedef state_wrapper< state_type > wrapped_state_type; typedef Value value_type; typedef Deriv deriv_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef adams_moulton< Steps , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type; static const size_t steps = Steps; typedef unsigned short order_type; static const order_type order_value = steps + 1; typedef detail::rotating_buffer< wrapped_deriv_type , steps > step_storage_type; adams_moulton( ) : m_coefficients() , m_dxdt() , m_resizer() , m_algebra_instance() , m_algebra( m_algebra_instance ) { } adams_moulton( algebra_type &algebra ) : m_coefficients() , m_dxdt() , m_resizer() , m_algebra_instance() , m_algebra( algebra ) { } adams_moulton& operator=( const adams_moulton &stepper ) { m_dxdt = stepper.m_dxdt; m_resizer = stepper.m_resizer; m_algebra = stepper.m_algebra; return *this; } order_type order( void ) const { return order_value; } /* * Version 1 : do_step( system , x , t , dt , buf ); * * solves the forwarding problem */ template< class System , class StateInOut , class StateIn , class ABBuf > void do_step( System system , StateInOut &x , StateIn const & pred , time_type t , time_type dt , const ABBuf &buf ) { do_step( system , x , pred , t , x , dt , buf ); } template< class System , class StateInOut , class StateIn , class ABBuf > void do_step( System system , const StateInOut &x , StateIn const & pred , time_type t , time_type dt , const ABBuf &buf ) { do_step( system , x , pred , t , x , dt , buf ); } /* * Version 2 : do_step( system , in , t , out , dt , buf ); * * solves the forwarding problem */ template< class System , class StateIn , class PredIn , class StateOut , class ABBuf > void do_step( System system , const StateIn &in , const PredIn &pred , time_type t , StateOut &out , time_type dt , const ABBuf &buf ) { do_step_impl( system , in , pred , t , out , dt , buf ); } template< class System , class StateIn , class PredIn , class StateOut , class ABBuf > void do_step( System system , const StateIn &in , const PredIn &pred , time_type t , const StateOut &out , time_type dt , const ABBuf &buf ) { do_step_impl( system , in , pred , t , out , dt , buf ); } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); } algebra_type& algebra() { return m_algebra; } const algebra_type& algebra() const { return m_algebra; } private: template< class System , class StateIn , class PredIn , class StateOut , class ABBuf > void do_step_impl( System system , const StateIn &in , const PredIn &pred , time_type t , StateOut &out , time_type dt , const ABBuf &buf ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); sys( pred , m_dxdt.m_v , t ); detail::adams_moulton_call_algebra< steps , algebra_type , operations_type >()( m_algebra , in , out , m_dxdt.m_v , buf , m_coefficients , dt ); } template< class StateIn > bool resize_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } const detail::adams_moulton_coefficients< value_type , steps > m_coefficients; wrapped_deriv_type m_dxdt; resizer_type m_resizer; protected: algebra_type m_algebra_instance; algebra_type &m_algebra; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_MOULTON_HPP_INCLUDED odeint/stepper/adams_bashforth.hpp 0000644 00000035640 15125237305 0013361 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/adams_bashforth.hpp [begin_description] Implementaton of the Adam-Bashforth method a multistep method used for the predictor step in the Adams-Bashforth-Moulton method. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky Copyright 2012 Christoph Koke Copyright 2013 Pascal Germroth 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_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED #include <boost/static_assert.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/runge_kutta4.hpp> #include <boost/numeric/odeint/stepper/extrapolation_stepper.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> #include <boost/numeric/odeint/stepper/detail/adams_bashforth_coefficients.hpp> #include <boost/numeric/odeint/stepper/detail/adams_bashforth_call_algebra.hpp> #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp> #include <boost/mpl/arithmetic.hpp> #include <boost/mpl/min_max.hpp> #include <boost/mpl/equal_to.hpp> namespace mpl = boost::mpl; namespace boost { namespace numeric { namespace odeint { using mpl::int_; /* if N >= 4, returns the smallest even number > N, otherwise returns 4 */ template < int N > struct order_helper : mpl::max< typename mpl::eval_if< mpl::equal_to< mpl::modulus< int_< N >, int_< 2 > >, int_< 0 > >, int_< N >, int_< N + 1 > >::type, int_< 4 > >::type { }; template< size_t Steps , class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer , class InitializingStepper = extrapolation_stepper< order_helper<Steps>::value, State, Value, Deriv, Time, Algebra, Operations, Resizer > > class adams_bashforth : public algebra_stepper_base< Algebra , Operations > { #ifndef DOXYGEN_SKIP BOOST_STATIC_ASSERT(( Steps > 0 )); BOOST_STATIC_ASSERT(( Steps < 9 )); #endif public : typedef State state_type; typedef state_wrapper< state_type > wrapped_state_type; typedef Value value_type; typedef Deriv deriv_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef Time time_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef InitializingStepper initializing_stepper_type; typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef typename algebra_stepper_base_type::operations_type operations_type; #ifndef DOXYGEN_SKIP typedef adams_bashforth< Steps , State , Value , Deriv , Time , Algebra , Operations , Resizer , InitializingStepper > stepper_type; #endif static const size_t steps = Steps; typedef unsigned short order_type; static const order_type order_value = steps; typedef detail::rotating_buffer< wrapped_deriv_type , steps > step_storage_type; order_type order( void ) const { return order_value; } adams_bashforth( const algebra_type &algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) , m_step_storage() , m_resizer() , m_coefficients() , m_steps_initialized( 0 ) , m_initializing_stepper() { } /* * Version 1 : do_step( system , x , t , dt ); * * solves the forwarding problem */ template< class System , class StateInOut > void do_step( System system , StateInOut &x , time_type t , time_type dt ) { do_step( system , x , t , x , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &x , time_type t , time_type dt ) { do_step( system , x , t , x , dt ); } /* * Version 2 : do_step( system , in , t , out , dt ); * * solves the forwarding problem */ template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { do_step_impl( system , in , t , out , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateOut. */ template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , const StateOut &out , time_type dt ) { do_step_impl( system , in , t , out , dt ); } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); } const step_storage_type& step_storage( void ) const { return m_step_storage; } step_storage_type& step_storage( void ) { return m_step_storage; } template< class ExplicitStepper , class System , class StateIn > void initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) { typename odeint::unwrap_reference< ExplicitStepper >::type &stepper = explicit_stepper; typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); for( size_t i=0 ; i+1<steps ; ++i ) { if( i != 0 ) m_step_storage.rotate(); sys( x , m_step_storage[0].m_v , t ); stepper.do_step_dxdt_impl( system, x, m_step_storage[0].m_v, t, dt ); t += dt; } m_steps_initialized = steps; } template< class System , class StateIn > void initialize( System system , StateIn &x , time_type &t , time_type dt ) { initialize( detail::ref( m_initializing_stepper ) , system , x , t , dt ); } void reset( void ) { m_steps_initialized = 0; } bool is_initialized( void ) const { return m_steps_initialized >= ( steps - 1 ); } const initializing_stepper_type& initializing_stepper( void ) const { return m_initializing_stepper; } initializing_stepper_type& initializing_stepper( void ) { return m_initializing_stepper; } private: template< class System , class StateIn , class StateOut > void do_step_impl( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { typename odeint::unwrap_reference< System >::type &sys = system; if( m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ) ) { m_steps_initialized = 0; } if( m_steps_initialized + 1 < steps ) { if( m_steps_initialized != 0 ) m_step_storage.rotate(); sys( in , m_step_storage[0].m_v , t ); m_initializing_stepper.do_step_dxdt_impl( system, in, m_step_storage[0].m_v, t, out, dt ); ++m_steps_initialized; } else { m_step_storage.rotate(); sys( in , m_step_storage[0].m_v , t ); detail::adams_bashforth_call_algebra< steps , algebra_type , operations_type >()( this->m_algebra , in , out , m_step_storage , m_coefficients , dt ); } } template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); for( size_t i=0 ; i<steps ; ++i ) { resized |= adjust_size_by_resizeability( m_step_storage[i] , x , typename is_resizeable<deriv_type>::type() ); } return resized; } step_storage_type m_step_storage; resizer_type m_resizer; detail::adams_bashforth_coefficients< value_type , steps > m_coefficients; size_t m_steps_initialized; initializing_stepper_type m_initializing_stepper; }; /***** DOXYGEN *****/ /** * \class adams_bashforth * \brief The Adams-Bashforth multistep algorithm. * * The Adams-Bashforth method is a multi-step algorithm with configurable step * number. The step number is specified as template parameter Steps and it * then uses the result from the previous Steps steps. See also * <a href="http://en.wikipedia.org/wiki/Linear_multistep_method">en.wikipedia.org/wiki/Linear_multistep_method</a>. * Currently, a maximum of Steps=8 is supported. * The method is explicit and fulfills the Stepper concept. Step size control * or continuous output are not provided. * * This class derives from algebra_base and inherits its interface via * CRTP (current recurring template pattern). For more details see * algebra_stepper_base. * * \tparam Steps The number of steps (maximal 8). * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. * \tparam InitializingStepper The stepper for the first two steps. */ /** * \fn adams_bashforth::adams_bashforth( const algebra_type &algebra ) * \brief Constructs the adams_bashforth class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored. */ /** * \fn order_type adams_bashforth::order( void ) const * \brief Returns the order of the algorithm, which is equal to the number of steps. * \return order of the method. */ /** * \fn void adams_bashforth::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn void adams_bashforth::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn void adams_bashforth::adjust_size( const StateType &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ /** * \fn const step_storage_type& adams_bashforth::step_storage( void ) const * \brief Returns the storage of intermediate results. * \return The storage of intermediate results. */ /** * \fn step_storage_type& adams_bashforth::step_storage( void ) * \brief Returns the storage of intermediate results. * \return The storage of intermediate results. */ /** * \fn void adams_bashforth::initialize( ExplicitStepper explicit_stepper , System system , StateIn &x , time_type &t , time_type dt ) * \brief Initialized the stepper. Does Steps-1 steps with the explicit_stepper to fill the buffer. * \param explicit_stepper the stepper used to fill the buffer of previous step results * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn void adams_bashforth::initialize( System system , StateIn &x , time_type &t , time_type dt ) * \brief Initialized the stepper. Does Steps-1 steps with an internal instance of InitializingStepper to fill the buffer. * \note The state x and time t are updated to the values after Steps-1 initial steps. * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The initial state of the ODE which should be solved, updated in this method. * \param t The initial value of the time, updated in this method. * \param dt The step size. */ /** * \fn void adams_bashforth::reset( void ) * \brief Resets the internal buffer of the stepper. */ /** * \fn bool adams_bashforth::is_initialized( void ) const * \brief Returns true if the stepper has been initialized. * \return bool true if stepper is initialized, false otherwise */ /** * \fn const initializing_stepper_type& adams_bashforth::initializing_stepper( void ) const * \brief Returns the internal initializing stepper instance. * \return initializing_stepper */ /** * \fn const initializing_stepper_type& adams_bashforth::initializing_stepper( void ) const * \brief Returns the internal initializing stepper instance. * \return initializing_stepper */ /** * \fn initializing_stepper_type& adams_bashforth::initializing_stepper( void ) * \brief Returns the internal initializing stepper instance. * \return initializing_stepper */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ADAMS_BASHFORTH_HPP_INCLUDED odeint/stepper/generation.hpp 0000644 00000002705 15125237305 0012363 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation.hpp [begin_description] Forward header for the factory functions. Includes all files from the generation directory. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_HPP_INCLUDED #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> #include <boost/numeric/odeint/stepper/generation/make_dense_output.hpp> #include <boost/numeric/odeint/stepper/generation/generation_controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/generation/generation_dense_output_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_cash_karp54_classic.hpp> #include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_cash_karp54.hpp> #include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_dopri5.hpp> #include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_fehlberg78.hpp> #include <boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/generation/generation_rosenbrock4.hpp> #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_HPP_INCLUDED odeint/stepper/rosenbrock4_controller.hpp 0000644 00000016172 15125237305 0014731 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/rosenbrock4_controller.hpp [begin_description] Controller for the Rosenbrock4 method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_ROSENBROCK4_CONTROLLER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_CONTROLLER_HPP_INCLUDED #include <boost/config.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4.hpp> namespace boost { namespace numeric { namespace odeint { template< class Stepper > class rosenbrock4_controller { private: public: typedef Stepper stepper_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_type::resizer_type resizer_type; typedef controlled_stepper_tag stepper_category; typedef rosenbrock4_controller< Stepper > controller_type; rosenbrock4_controller( value_type atol = 1.0e-6 , value_type rtol = 1.0e-6 , const stepper_type &stepper = stepper_type() ) : m_stepper( stepper ) , m_atol( atol ) , m_rtol( rtol ) , m_max_dt( static_cast<time_type>(0) ) , m_first_step( true ) , m_err_old( 0.0 ) , m_dt_old( 0.0 ) , m_last_rejected( false ) { } rosenbrock4_controller( value_type atol, value_type rtol, time_type max_dt, const stepper_type &stepper = stepper_type() ) : m_stepper( stepper ) , m_atol( atol ) , m_rtol( rtol ) , m_max_dt( max_dt ) , m_first_step( true ) , m_err_old( 0.0 ) , m_dt_old( 0.0 ) , m_last_rejected( false ) { } value_type error( const state_type &x , const state_type &xold , const state_type &xerr ) { BOOST_USING_STD_MAX(); using std::abs; using std::sqrt; const size_t n = x.size(); value_type err = 0.0 , sk = 0.0; for( size_t i=0 ; i<n ; ++i ) { sk = m_atol + m_rtol * max BOOST_PREVENT_MACRO_SUBSTITUTION ( abs( xold[i] ) , abs( x[i] ) ); err += xerr[i] * xerr[i] / sk / sk; } return sqrt( err / value_type( n ) ); } value_type last_error( void ) const { return m_err_old; } template< class System > boost::numeric::odeint::controlled_step_result try_step( System sys , state_type &x , time_type &t , time_type &dt ) { m_xnew_resizer.adjust_size( x , detail::bind( &controller_type::template resize_m_xnew< state_type > , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::controlled_step_result res = try_step( sys , x , t , m_xnew.m_v , dt ); if( res == success ) { boost::numeric::odeint::copy( m_xnew.m_v , x ); } return res; } template< class System > boost::numeric::odeint::controlled_step_result try_step( System sys , const state_type &x , time_type &t , state_type &xout , time_type &dt ) { if( m_max_dt != static_cast<time_type>(0) && detail::less_with_sign(m_max_dt, dt, dt) ) { // given step size is bigger then max_dt // set limit and return fail dt = m_max_dt; return fail; } BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; static const value_type safe = 0.9 , fac1 = 5.0 , fac2 = 1.0 / 6.0; m_xerr_resizer.adjust_size( x , detail::bind( &controller_type::template resize_m_xerr< state_type > , detail::ref( *this ) , detail::_1 ) ); m_stepper.do_step( sys , x , t , xout , dt , m_xerr.m_v ); value_type err = error( xout , x , m_xerr.m_v ); value_type fac = max BOOST_PREVENT_MACRO_SUBSTITUTION ( fac2 , min BOOST_PREVENT_MACRO_SUBSTITUTION ( fac1 , static_cast< value_type >( pow( err , 0.25 ) / safe ) ) ); value_type dt_new = dt / fac; if ( err <= 1.0 ) { if( m_first_step ) { m_first_step = false; } else { value_type fac_pred = ( m_dt_old / dt ) * pow( err * err / m_err_old , 0.25 ) / safe; fac_pred = max BOOST_PREVENT_MACRO_SUBSTITUTION ( fac2 , min BOOST_PREVENT_MACRO_SUBSTITUTION ( fac1 , fac_pred ) ); fac = max BOOST_PREVENT_MACRO_SUBSTITUTION ( fac , fac_pred ); dt_new = dt / fac; } m_dt_old = dt; m_err_old = max BOOST_PREVENT_MACRO_SUBSTITUTION ( static_cast< value_type >( 0.01 ) , err ); if( m_last_rejected ) dt_new = ( dt >= 0.0 ? min BOOST_PREVENT_MACRO_SUBSTITUTION ( dt_new , dt ) : max BOOST_PREVENT_MACRO_SUBSTITUTION ( dt_new , dt ) ); t += dt; // limit step size to max_dt if( m_max_dt != static_cast<time_type>(0) ) { dt = detail::min_abs(m_max_dt, dt_new); } else { dt = dt_new; } m_last_rejected = false; return success; } else { dt = dt_new; m_last_rejected = true; return fail; } } template< class StateType > void adjust_size( const StateType &x ) { resize_m_xerr( x ); resize_m_xnew( x ); } stepper_type& stepper( void ) { return m_stepper; } const stepper_type& stepper( void ) const { return m_stepper; } protected: template< class StateIn > bool resize_m_xerr( const StateIn &x ) { return adjust_size_by_resizeability( m_xerr , x , typename is_resizeable<state_type>::type() ); } template< class StateIn > bool resize_m_xnew( const StateIn &x ) { return adjust_size_by_resizeability( m_xnew , x , typename is_resizeable<state_type>::type() ); } stepper_type m_stepper; resizer_type m_xerr_resizer; resizer_type m_xnew_resizer; wrapped_state_type m_xerr; wrapped_state_type m_xnew; value_type m_atol , m_rtol; time_type m_max_dt; bool m_first_step; value_type m_err_old , m_dt_old; bool m_last_rejected; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_CONTROLLER_HPP_INCLUDED odeint/stepper/implicit_euler.hpp 0000644 00000012164 15125237305 0013236 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/implicit_euler.hpp [begin_description] Impementation of the implicit Euler method. Works with ublas::vector as state type. [end_description] Copyright 2010-2012 Mario Mulansky Copyright 2010-2012 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_IMPLICIT_EULER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_IMPLICIT_EULER_HPP_INCLUDED #include <utility> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/ublas_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/lu.hpp> namespace boost { namespace numeric { namespace odeint { template< class ValueType , class Resizer = initially_resizer > class implicit_euler { public: typedef ValueType value_type; typedef value_type time_type; typedef boost::numeric::ublas::vector< value_type > state_type; typedef state_wrapper< state_type > wrapped_state_type; typedef state_type deriv_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef boost::numeric::ublas::matrix< value_type > matrix_type; typedef state_wrapper< matrix_type > wrapped_matrix_type; typedef boost::numeric::ublas::permutation_matrix< size_t > pmatrix_type; typedef state_wrapper< pmatrix_type > wrapped_pmatrix_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef implicit_euler< ValueType , Resizer > stepper_type; implicit_euler( value_type epsilon = 1E-6 ) : m_epsilon( epsilon ) { } template< class System > void do_step( System system , state_type &x , time_type t , time_type dt ) { typedef typename odeint::unwrap_reference< System >::type system_type; typedef typename odeint::unwrap_reference< typename system_type::first_type >::type deriv_func_type; typedef typename odeint::unwrap_reference< typename system_type::second_type >::type jacobi_func_type; system_type &sys = system; deriv_func_type &deriv_func = sys.first; jacobi_func_type &jacobi_func = sys.second; m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl<state_type> , detail::ref( *this ) , detail::_1 ) ); for( size_t i=0 ; i<x.size() ; ++i ) m_pm.m_v[i] = i; t += dt; // apply first Newton step deriv_func( x , m_dxdt.m_v , t ); m_b.m_v = dt * m_dxdt.m_v; jacobi_func( x , m_jacobi.m_v , t ); m_jacobi.m_v *= dt; m_jacobi.m_v -= boost::numeric::ublas::identity_matrix< value_type >( x.size() ); solve( m_b.m_v , m_jacobi.m_v ); m_x.m_v = x - m_b.m_v; // iterate Newton until some precision is reached // ToDo: maybe we should apply only one Newton step -> linear implicit one-step scheme while( boost::numeric::ublas::norm_2( m_b.m_v ) > m_epsilon ) { deriv_func( m_x.m_v , m_dxdt.m_v , t ); m_b.m_v = x - m_x.m_v + dt*m_dxdt.m_v; // simplified version, only the first Jacobian is used // jacobi( m_x , m_jacobi , t ); // m_jacobi *= dt; // m_jacobi -= boost::numeric::ublas::identity_matrix< value_type >( x.size() ); solve( m_b.m_v , m_jacobi.m_v ); m_x.m_v -= m_b.m_v; } x = m_x.m_v; } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_x , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_b , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_jacobi , x , typename is_resizeable<matrix_type>::type() ); resized |= adjust_size_by_resizeability( m_pm , x , typename is_resizeable<pmatrix_type>::type() ); return resized; } void solve( state_type &x , matrix_type &m ) { int res = boost::numeric::ublas::lu_factorize( m , m_pm.m_v ); if( res != 0 ) std::exit(0); boost::numeric::ublas::lu_substitute( m , m_pm.m_v , x ); } private: value_type m_epsilon; resizer_type m_resizer; wrapped_deriv_type m_dxdt; wrapped_state_type m_x; wrapped_deriv_type m_b; wrapped_matrix_type m_jacobi; wrapped_pmatrix_type m_pm; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_IMPLICIT_EULER_HPP_INCLUDED odeint/stepper/runge_kutta_fehlberg78.hpp 0000644 00000035235 15125237305 0014601 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta_fehlberg87.hpp [begin_description] Implementation of the Runge-Kutta-Fehlberg stepper with the generic stepper. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2012-2013 Karsten Ahnert 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_ODEINT_STEPPER_RUNGE_KUTTA_FEHLBERG87_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_FEHLBERG87_HPP_INCLUDED #include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/generation/make_vector.hpp> #include <boost/numeric/odeint/stepper/explicit_error_generic_rk.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/array.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP template< class Value = double > struct rk78_coefficients_a1 : boost::array< Value , 1 > { rk78_coefficients_a1( void ) { (*this)[0] = static_cast< Value >( 2 )/static_cast< Value >( 27 ); } }; template< class Value = double > struct rk78_coefficients_a2 : boost::array< Value , 2 > { rk78_coefficients_a2( void ) { (*this)[0] = static_cast< Value >( 1 )/static_cast< Value >( 36 ); (*this)[1] = static_cast< Value >( 1 )/static_cast< Value >( 12 ); } }; template< class Value = double > struct rk78_coefficients_a3 : boost::array< Value , 3 > { rk78_coefficients_a3( void ) { (*this)[0] = static_cast< Value >( 1 )/static_cast< Value >( 24 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 1 )/static_cast< Value >( 8 ); } }; template< class Value = double > struct rk78_coefficients_a4 : boost::array< Value , 4 > { rk78_coefficients_a4( void ) { (*this)[0] = static_cast< Value >( 5 )/static_cast< Value >( 12 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( -25 )/static_cast< Value >( 16 ); (*this)[3] = static_cast< Value >( 25 )/static_cast< Value >( 16 ); } }; template< class Value = double > struct rk78_coefficients_a5 : boost::array< Value , 5 > { rk78_coefficients_a5( void ) { (*this)[0] = static_cast< Value >( 1 )/static_cast< Value >( 20 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 1 )/static_cast< Value >( 4 ); (*this)[4] = static_cast< Value >( 1 )/static_cast< Value >( 5 ); } }; template< class Value = double > struct rk78_coefficients_a6 : boost::array< Value , 6 > { rk78_coefficients_a6( void ) { (*this)[0] = static_cast< Value >( -25 )/static_cast< Value >( 108 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 125 )/static_cast< Value >( 108 ); (*this)[4] = static_cast< Value >( -65 )/static_cast< Value >( 27 ); (*this)[5] = static_cast< Value >( 125 )/static_cast< Value >( 54 ); } }; template< class Value = double > struct rk78_coefficients_a7 : boost::array< Value , 7 > { rk78_coefficients_a7( void ) { (*this)[0] = static_cast< Value >( 31 )/static_cast< Value >( 300 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 0 ); (*this)[4] = static_cast< Value >( 61 )/static_cast< Value >( 225 ); (*this)[5] = static_cast< Value >( -2 )/static_cast< Value >( 9 ); (*this)[6] = static_cast< Value >( 13 )/static_cast< Value >( 900 ); } }; template< class Value = double > struct rk78_coefficients_a8 : boost::array< Value , 8 > { rk78_coefficients_a8( void ) { (*this)[0] = static_cast< Value >( 2 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( -53 )/static_cast< Value >( 6 ); (*this)[4] = static_cast< Value >( 704 )/static_cast< Value >( 45 ); (*this)[5] = static_cast< Value >( -107 )/static_cast< Value >( 9 ); (*this)[6] = static_cast< Value >( 67 )/static_cast< Value >( 90 ); (*this)[7] = static_cast< Value >( 3 ); } }; template< class Value = double > struct rk78_coefficients_a9 : boost::array< Value , 9 > { rk78_coefficients_a9( void ) { (*this)[0] = static_cast< Value >( -91 )/static_cast< Value >( 108 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 23 )/static_cast< Value >( 108 ); (*this)[4] = static_cast< Value >( -976 )/static_cast< Value >( 135 ); (*this)[5] = static_cast< Value >( 311 )/static_cast< Value >( 54 ); (*this)[6] = static_cast< Value >( -19 )/static_cast< Value >( 60 ); (*this)[7] = static_cast< Value >( 17 )/static_cast< Value >( 6 ); (*this)[8] = static_cast< Value >( -1 )/static_cast< Value >( 12 ); } }; template< class Value = double > struct rk78_coefficients_a10 : boost::array< Value , 10 > { rk78_coefficients_a10( void ) { (*this)[0] = static_cast< Value >( 2383 )/static_cast< Value >( 4100 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( -341 )/static_cast< Value >( 164 ); (*this)[4] = static_cast< Value >( 4496 )/static_cast< Value >( 1025 ); (*this)[5] = static_cast< Value >( -301 )/static_cast< Value >( 82 ); (*this)[6] = static_cast< Value >( 2133 )/static_cast< Value >( 4100 ); (*this)[7] = static_cast< Value >( 45 )/static_cast< Value >( 82 ); (*this)[8] = static_cast< Value >( 45 )/static_cast< Value >( 164 ); (*this)[9] = static_cast< Value >( 18 )/static_cast< Value >( 41 ); } }; template< class Value = double > struct rk78_coefficients_a11 : boost::array< Value , 11 > { rk78_coefficients_a11( void ) { (*this)[0] = static_cast< Value >( 3 )/static_cast< Value >( 205 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 0 ); (*this)[4] = static_cast< Value >( 0 ); (*this)[5] = static_cast< Value >( -6 )/static_cast< Value >( 41 ); (*this)[6] = static_cast< Value >( -3 )/static_cast< Value >( 205 ); (*this)[7] = static_cast< Value >( -3 )/static_cast< Value >( 41 ); (*this)[8] = static_cast< Value >( 3 )/static_cast< Value >( 41 ); (*this)[9] = static_cast< Value >( 6 )/static_cast< Value >( 41 ); (*this)[10] = static_cast< Value >( 0 ); } }; template< class Value = double > struct rk78_coefficients_a12 : boost::array< Value , 12 > { rk78_coefficients_a12( void ) { (*this)[0] = static_cast< Value >( -1777 )/static_cast< Value >( 4100 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( -341 )/static_cast< Value >( 164 ); (*this)[4] = static_cast< Value >( 4496 )/static_cast< Value >( 1025 ); (*this)[5] = static_cast< Value >( -289 )/static_cast< Value >( 82 ); (*this)[6] = static_cast< Value >( 2193 )/static_cast< Value >( 4100 ); (*this)[7] = static_cast< Value >( 51 )/static_cast< Value >( 82 ); (*this)[8] = static_cast< Value >( 33 )/static_cast< Value >( 164 ); (*this)[9] = static_cast< Value >( 12 )/static_cast< Value >( 41 ); (*this)[10] = static_cast< Value >( 0 ); (*this)[11] = static_cast< Value >( 1 ); } }; template< class Value = double > struct rk78_coefficients_b : boost::array< Value , 13 > { rk78_coefficients_b( void ) { (*this)[0] = static_cast< Value >( 0 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 0 ); (*this)[4] = static_cast< Value >( 0 ); (*this)[5] = static_cast< Value >( 34 )/static_cast<Value>( 105 ); (*this)[6] = static_cast< Value >( 9 )/static_cast<Value>( 35 ); (*this)[7] = static_cast< Value >( 9 )/static_cast<Value>( 35 ); (*this)[8] = static_cast< Value >( 9 )/static_cast<Value>( 280 ); (*this)[9] = static_cast< Value >( 9 )/static_cast<Value>( 280 ); (*this)[10] = static_cast< Value >( 0 ); (*this)[11] = static_cast< Value >( 41 )/static_cast<Value>( 840 ); (*this)[12] = static_cast< Value >( 41 )/static_cast<Value>( 840 ); } }; template< class Value = double > struct rk78_coefficients_db : boost::array< Value , 13 > { rk78_coefficients_db( void ) { (*this)[0] = static_cast< Value >( 0 ) - static_cast< Value >( 41 )/static_cast<Value>( 840 ); (*this)[1] = static_cast< Value >( 0 ); (*this)[2] = static_cast< Value >( 0 ); (*this)[3] = static_cast< Value >( 0 ); (*this)[4] = static_cast< Value >( 0 ); (*this)[5] = static_cast< Value >( 0 ); (*this)[6] = static_cast< Value >( 0 ); (*this)[7] = static_cast< Value >( 0 ); (*this)[8] = static_cast< Value >( 0 ); (*this)[9] = static_cast< Value >( 0 ); (*this)[10] = static_cast< Value >( 0 ) - static_cast< Value >( 41 )/static_cast<Value>( 840 ); (*this)[11] = static_cast< Value >( 41 )/static_cast<Value>( 840 ); (*this)[12] = static_cast< Value >( 41 )/static_cast<Value>( 840 ); } }; template< class Value = double > struct rk78_coefficients_c : boost::array< Value , 13 > { rk78_coefficients_c( void ) { (*this)[0] = static_cast< Value >( 0 ); (*this)[1] = static_cast< Value >( 2 )/static_cast< Value >( 27 ); (*this)[2] = static_cast< Value >( 1 )/static_cast< Value >( 9 ); (*this)[3] = static_cast< Value >( 1 )/static_cast<Value>( 6 ); (*this)[4] = static_cast< Value >( 5 )/static_cast<Value>( 12 ); (*this)[5] = static_cast< Value >( 1 )/static_cast<Value>( 2 ); (*this)[6] = static_cast< Value >( 5 )/static_cast<Value>( 6 ); (*this)[7] = static_cast< Value >( 1 )/static_cast<Value>( 6 ); (*this)[8] = static_cast< Value >( 2 )/static_cast<Value>( 3 ); (*this)[9] = static_cast< Value >( 1 )/static_cast<Value>( 3 ); (*this)[10] = static_cast< Value >( 1 ); (*this)[11] = static_cast< Value >( 0 ); (*this)[12] = static_cast< Value >( 1 ); } }; #endif // DOXYGEN_SKIP template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class runge_kutta_fehlberg78 : public explicit_error_generic_rk< 13 , 8 , 8 , 7 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class runge_kutta_fehlberg78 : public explicit_error_generic_rk #endif { public: #ifndef DOXYGEN_SKIP typedef explicit_error_generic_rk< 13 , 8 , 8 , 7 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; #endif // DOXYGEN_SKIP runge_kutta_fehlberg78( const algebra_type &algebra = algebra_type() ) : stepper_base_type( boost::fusion::make_vector( rk78_coefficients_a1<Value>() , rk78_coefficients_a2<Value>() , rk78_coefficients_a3<Value>() , rk78_coefficients_a4<Value>() , rk78_coefficients_a5<Value>() , rk78_coefficients_a6<Value>() , rk78_coefficients_a7<Value>() , rk78_coefficients_a8<Value>() , rk78_coefficients_a9<Value>() , rk78_coefficients_a10<Value>() , rk78_coefficients_a11<Value>() , rk78_coefficients_a12<Value>() ) , rk78_coefficients_b<Value>() , rk78_coefficients_db<Value>() , rk78_coefficients_c<Value>() , algebra ) { } }; /************* DOXYGEN *************/ /** * \class runge_kutta_fehlberg78 * \brief The Runge-Kutta Fehlberg 78 method. * * The Runge-Kutta Fehlberg 78 method is a standard method for high-precision applications. * The method is explicit and fulfills the Error Stepper concept. Step size control * is provided but continuous output is not available for this method. * * This class derives from explicit_error_stepper_base and inherits its interface via CRTP (current recurring template pattern). * Furthermore, it derivs from explicit_error_generic_rk which is a generic Runge-Kutta algorithm with error estimation. * For more details see explicit_error_stepper_base and explicit_error_generic_rk. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta_fehlberg78::runge_kutta_fehlberg78( const algebra_type &algebra ) * \brief Constructs the runge_kutta_cash_fehlberg78 class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } } } #endif //BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_FEHLBERG87_HPP_INCLUDED odeint/stepper/generation/make_dense_output.hpp 0000644 00000005426 15125237305 0016101 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/make_dense_output.hpp [begin_description] Factory function to simplify the creation of dense output steppers from error steppers. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_MAKE_DENSE_OUTPUT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_MAKE_DENSE_OUTPUT_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { // default template for the dense output template< class Stepper > struct get_dense_output { }; // default dense output factory template< class Stepper , class DenseOutput > struct dense_output_factory { DenseOutput operator()( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , const Stepper &stepper ) { return DenseOutput( abs_error , rel_error , stepper ); } DenseOutput operator()( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , typename Stepper::time_type max_dt , const Stepper &stepper ) { return DenseOutput( abs_error , rel_error , max_dt , stepper ); } }; namespace result_of { template< class Stepper > struct make_dense_output { typedef typename get_dense_output< Stepper >::type type; }; } template< class Stepper > typename result_of::make_dense_output< Stepper >::type make_dense_output( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , const Stepper &stepper = Stepper() ) { typedef Stepper stepper_type; typedef typename result_of::make_dense_output< stepper_type >::type dense_output_type; typedef dense_output_factory< stepper_type , dense_output_type > factory_type; factory_type factory; return factory( abs_error , rel_error , stepper ); } template< class Stepper > typename result_of::make_dense_output< Stepper >::type make_dense_output( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , typename Stepper::time_type max_dt , const Stepper &stepper = Stepper() ) { typedef Stepper stepper_type; typedef typename result_of::make_dense_output< stepper_type >::type dense_output_type; typedef dense_output_factory< stepper_type , dense_output_type > factory_type; factory_type factory; return factory( abs_error , rel_error , max_dt, stepper ); } } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_MAKE_DENSE_OUTPUT_HPP_INCLUDED odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp 0000644 00000004321 15125237305 0023721 0 ustar 00 /* boost/numeric/odeint/stepper/detail/generation_controlled_adams_bashforth_moulton.hpp [begin_description] Spezialization of the generation functions for creation of the controlled adams bashforth moulton stepper. [end_description] Copyright 2017 Valentin Noah Hartmann 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 GENERATION_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #define GENERATION_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> namespace boost { namespace numeric { namespace odeint { template< size_t Steps, class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > struct get_controller< adaptive_adams_bashforth_moulton< Steps, State , Value , Deriv , Time , Algebra , Operations , Resizer > > { typedef adaptive_adams_bashforth_moulton<Steps, State, Value, Deriv, Time, Algebra, Operations, Resizer> stepper_type; typedef controlled_adams_bashforth_moulton< stepper_type > type; }; // controller factory for controlled_adams_bashforth_moulton template< class Stepper > struct controller_factory< Stepper , controlled_adams_bashforth_moulton< Stepper > > { typedef Stepper stepper_type; typedef controlled_adams_bashforth_moulton< stepper_type > controller_type; typedef typename controller_type::step_adjuster_type step_adjuster_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::value_type time_type; controller_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper ) { return controller_type(step_adjuster_type(abs_error, rel_error)); } controller_type operator()( value_type abs_error , value_type rel_error , time_type max_dt, const stepper_type &stepper ) { return controller_type( step_adjuster_type(abs_error, rel_error, max_dt)); } }; } } } #endif odeint/stepper/generation/generation_runge_kutta_cash_karp54_classic.hpp 0000644 00000003116 15125237305 0023010 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_runge_kutta_cash_karp54_classic.hpp [begin_description] Enable the factory functions for the controller and the dense output of the Runge-Kutta-Cash-Karp 54 method with the classical implementation. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_cash_karp54_classic.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> namespace boost { namespace numeric { namespace odeint { // Specializations for runge_kutta_cash_karp54 template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resize > struct get_controller< runge_kutta_cash_karp54_classic< State , Value , Deriv , Time , Algebra , Operations , Resize > > { typedef runge_kutta_cash_karp54_classic< State , Value , Deriv , Time , Algebra , Operations , Resize > stepper_type; typedef controlled_runge_kutta< stepper_type > type; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_CLASSIC_HPP_INCLUDED odeint/stepper/generation/generation_rosenbrock4.hpp 0000644 00000005012 15125237305 0017023 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_rosenbrock4.hpp [begin_description] Enable the factory functions for the controller and the dense output of the Rosenbrock4 method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_ROSENBROCK4_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_ROSENBROCK4_HPP_INCLUDED #include <boost/numeric/odeint/stepper/rosenbrock4.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4_controller.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp> namespace boost { namespace numeric { namespace odeint { template< class Value , class Coefficients , class Resize > struct get_controller< rosenbrock4< Value , Coefficients , Resize > > { typedef rosenbrock4< Value , Coefficients , Resize > stepper_type; typedef rosenbrock4_controller< stepper_type > type; }; template< class Value , class Coefficients , class Resize > struct get_dense_output< rosenbrock4< Value , Coefficients , Resize > > { typedef rosenbrock4< Value , Coefficients , Resize > stepper_type; typedef rosenbrock4_controller< stepper_type > controller_type; typedef rosenbrock4_dense_output< controller_type > type; }; // controller factory for controlled_runge_kutta template< class Stepper > struct dense_output_factory< Stepper , rosenbrock4_dense_output< rosenbrock4_controller< Stepper > > > { typedef Stepper stepper_type; typedef rosenbrock4_controller< stepper_type > controller_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::time_type time_type; typedef rosenbrock4_dense_output< controller_type > dense_output_type; dense_output_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper ) { return dense_output_type( controller_type( abs_error , rel_error , stepper ) ); } dense_output_type operator()( value_type abs_error , value_type rel_error , time_type max_dt, const stepper_type &stepper ) { return dense_output_type( controller_type( abs_error , rel_error , max_dt , stepper ) ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_ROSENBROCK4_HPP_INCLUDED odeint/stepper/generation/generation_controlled_runge_kutta.hpp 0000644 00000004050 15125237305 0021346 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_controlled_runge_kutta.hpp [begin_description] Specialization of the controller factory for the controlled_runge_kutta class. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> namespace boost { namespace numeric { namespace odeint { // controller factory for controlled_runge_kutta template< class Stepper > struct controller_factory< Stepper , controlled_runge_kutta< Stepper > > { typedef Stepper stepper_type; typedef controlled_runge_kutta< stepper_type > controller_type; typedef typename controller_type::error_checker_type error_checker_type; typedef typename controller_type::step_adjuster_type step_adjuster_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::value_type time_type; controller_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper ) { return controller_type( error_checker_type( abs_error , rel_error ) , step_adjuster_type() , stepper ); } controller_type operator()( value_type abs_error , value_type rel_error , time_type max_dt, const stepper_type &stepper ) { return controller_type( error_checker_type( abs_error , rel_error ) , step_adjuster_type(max_dt) , stepper ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED odeint/stepper/generation/generation_runge_kutta_dopri5.hpp 0000644 00000004010 15125237305 0020377 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_runge_kutta_dopri5.hpp [begin_description] Enable the factory functions for the controller and the dense output of the Runge-Kutta-Dormand-Prince5 method. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> #include <boost/numeric/odeint/stepper/generation/make_dense_output.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resize > struct get_controller< runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resize > > { typedef runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resize > stepper_type; typedef controlled_runge_kutta< stepper_type > type; }; template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resize > struct get_dense_output< runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resize > > { typedef runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resize > stepper_type; typedef controlled_runge_kutta< stepper_type > controller_type; typedef dense_output_runge_kutta< controller_type > type; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED odeint/stepper/generation/generation_runge_kutta_fehlberg78.hpp 0000644 00000002674 15125237305 0021150 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_runge_kutta_fehlberg78.hpp [begin_description] Enable the factory functions for the controller and the dense output of the Runge-Kutta-Fehlberg 78 method. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_FEHLBERG78_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_FEHLBERG78_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resize > struct get_controller< runge_kutta_fehlberg78< State , Value , Deriv , Time , Algebra , Operations , Resize > > { typedef runge_kutta_fehlberg78< State , Value , Deriv , Time , Algebra , Operations , Resize > stepper_type; typedef controlled_runge_kutta< stepper_type > type; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_FEHLBERG78_HPP_INCLUDED odeint/stepper/generation/generation_dense_output_runge_kutta.hpp 0000644 00000004470 15125237305 0021725 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_dense_output_runge_kutta.hpp [begin_description] Specialization of the controller factory for the dense_output_runge_kutta class. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/generation/make_dense_output.hpp> namespace boost { namespace numeric { namespace odeint { // controller factory for controlled_runge_kutta template< class Stepper > struct dense_output_factory< Stepper , dense_output_runge_kutta< controlled_runge_kutta< Stepper > > > { typedef Stepper stepper_type; typedef controlled_runge_kutta< stepper_type > controller_type; typedef typename controller_type::error_checker_type error_checker_type; typedef typename controller_type::step_adjuster_type step_adjuster_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::time_type time_type; typedef dense_output_runge_kutta< controller_type > dense_output_type; dense_output_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper ) { return dense_output_type( controller_type( error_checker_type( abs_error , rel_error ) , step_adjuster_type() , stepper ) ); } dense_output_type operator()( value_type abs_error , value_type rel_error , time_type max_dt , const stepper_type &stepper ) { return dense_output_type( controller_type( error_checker_type( abs_error , rel_error) , step_adjuster_type( max_dt ) , stepper ) ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_DENSE_OUTPUT_RUNGE_KUTTA_HPP_INCLUDED odeint/stepper/generation/make_controlled.hpp 0000644 00000005347 15125237305 0015532 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/make_controlled.hpp [begin_description] Factory function to simplify the creation of controlled steppers from error steppers. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_MAKE_CONTROLLED_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_MAKE_CONTROLLED_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { // default template for the controller template< class Stepper > struct get_controller { }; // default controller factory template< class Stepper , class Controller > struct controller_factory { Controller operator()( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , const Stepper &stepper ) { return Controller( abs_error , rel_error , stepper ); } Controller operator()( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , typename Stepper::time_type max_dt , const Stepper &stepper ) { return Controller( abs_error , rel_error , max_dt, stepper ); } }; namespace result_of { template< class Stepper > struct make_controlled { typedef typename get_controller< Stepper >::type type; }; } template< class Stepper > typename result_of::make_controlled< Stepper >::type make_controlled( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , const Stepper & stepper = Stepper() ) { typedef Stepper stepper_type; typedef typename result_of::make_controlled< stepper_type >::type controller_type; typedef controller_factory< stepper_type , controller_type > factory_type; factory_type factory; return factory( abs_error , rel_error , stepper ); } template< class Stepper > typename result_of::make_controlled< Stepper >::type make_controlled( typename Stepper::value_type abs_error , typename Stepper::value_type rel_error , typename Stepper::time_type max_dt , const Stepper & stepper = Stepper() ) { typedef Stepper stepper_type; typedef typename result_of::make_controlled< stepper_type >::type controller_type; typedef controller_factory< stepper_type , controller_type > factory_type; factory_type factory; return factory( abs_error , rel_error , max_dt, stepper ); } } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_MAKE_CONTROLLED_HPP_INCLUDED odeint/stepper/generation/generation_runge_kutta_cash_karp54.hpp 0000644 00000002763 15125237305 0021316 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/generation/generation_runge_kutta_cash_karp54.hpp [begin_description] Enable the factory functions for the controller and the dense output of the Runge-Kutta-Cash-Karp 54 method. [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp> #include <boost/numeric/odeint/stepper/generation/make_controlled.hpp> namespace boost { namespace numeric { namespace odeint { // Specializations for runge_kutta_cash_karp54 template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resize > struct get_controller< runge_kutta_cash_karp54< State , Value , Deriv , Time , Algebra , Operations , Resize > > { typedef runge_kutta_cash_karp54< State , Value , Deriv , Time , Algebra , Operations , Resize > stepper_type; typedef controlled_runge_kutta< stepper_type > type; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_GENERATION_GENERATION_RUNGE_KUTTA_CASH_KARP54_HPP_INCLUDED odeint/stepper/runge_kutta4.hpp 0000644 00000013344 15125237305 0012645 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta4.hpp [begin_description] Implementation of the classical Runge-Kutta stepper with the generic stepper. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert 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_ODEINT_STEPPER_RUNGE_KUTTA4_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA4_HPP_INCLUDED #include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/generation/make_vector.hpp> #include <boost/numeric/odeint/stepper/explicit_generic_rk.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/array.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP template< class Value = double > struct rk4_coefficients_a1 : boost::array< Value , 1 > { rk4_coefficients_a1( void ) { (*this)[0] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); } }; template< class Value = double > struct rk4_coefficients_a2 : boost::array< Value , 2 > { rk4_coefficients_a2( void ) { (*this)[0] = static_cast<Value>(0); (*this)[1] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); } }; template< class Value = double > struct rk4_coefficients_a3 : boost::array< Value , 3 > { rk4_coefficients_a3( void ) { (*this)[0] = static_cast<Value>(0); (*this)[1] = static_cast<Value>(0); (*this)[2] = static_cast<Value>(1); } }; template< class Value = double > struct rk4_coefficients_b : boost::array< Value , 4 > { rk4_coefficients_b( void ) { (*this)[0] = static_cast<Value>(1)/static_cast<Value>(6); (*this)[1] = static_cast<Value>(1)/static_cast<Value>(3); (*this)[2] = static_cast<Value>(1)/static_cast<Value>(3); (*this)[3] = static_cast<Value>(1)/static_cast<Value>(6); } }; template< class Value = double > struct rk4_coefficients_c : boost::array< Value , 4 > { rk4_coefficients_c( void ) { (*this)[0] = static_cast<Value>(0); (*this)[1] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); (*this)[2] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); (*this)[3] = static_cast<Value>(1); } }; #endif template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class runge_kutta4 : public explicit_generic_rk< 4 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class runge_kutta4 : public explicit_generic_rk #endif { public: #ifndef DOXYGEN_SKIP typedef explicit_generic_rk< 4 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_base_type::stepper_type stepper_type; #endif runge_kutta4( const algebra_type &algebra = algebra_type() ) : stepper_base_type( boost::fusion::make_vector( rk4_coefficients_a1<Value>() , rk4_coefficients_a2<Value>() , rk4_coefficients_a3<Value>() ) , rk4_coefficients_b<Value>() , rk4_coefficients_c<Value>() , algebra ) { } }; /** * \class runge_kutta4 * \brief The classical Runge-Kutta stepper of fourth order. * * The Runge-Kutta method of fourth order is one standard method for * solving ordinary differential equations and is widely used, see also * <a href="http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods">en.wikipedia.org/wiki/Runge-Kutta_methods</a> * The method is explicit and fulfills the Stepper concept. Step size control * or continuous output are not provided. * * This class derives from explicit_stepper_base and inherits its interface via CRTP (current recurring template pattern). * Furthermore, it derivs from explicit_generic_rk which is a generic Runge-Kutta algorithm. For more details see * explicit_stepper_base and explicit_generic_rk. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta4::runge_kutta4( const algebra_type &algebra = algebra_type() ) * \brief Constructs the runge_kutta4 class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA4_HPP_INCLUDED odeint/stepper/detail/pid_step_adjuster.hpp 0000644 00000012126 15125237305 0015200 0 ustar 00 /* boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp [begin_description] Implementation of the stepsize controller for the controlled adams bashforth moulton stepper. [end_description] Copyright 2017 Valentin Noah Hartmann 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_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_HPP_INCLUDED #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp> #include <boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <math.h> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Value = double, class Time = double > struct pid_op { public: typedef Value value_type; typedef Time time_type; const double beta1; const double beta2; const double beta3; const double alpha1; const double alpha2; const time_type dt1; const time_type dt2; const time_type dt3; const size_t m_steps; pid_op(const size_t steps, const double _dt1, const double _dt2, const double _dt3, const double b1 = 1, const double b2 = 0, const double b3 = 0, const double a1 = 0, const double a2 = 0) :beta1(b1), beta2(b2), beta3(b3), alpha1(a1), alpha2(a2), dt1(_dt1), dt2(_dt2), dt3(_dt3), m_steps(steps) {}; template<class T1, class T2, class T3, class T4> void operator()(T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { using std::abs; t1 = adapted_pow(abs(t2), -beta1/(m_steps + 1)) * adapted_pow(abs(t3), -beta2/(m_steps + 1)) * adapted_pow(abs(t4), -beta3/(m_steps + 1)) * adapted_pow(abs(dt1/dt2), -alpha1/(m_steps + 1))* adapted_pow(abs(dt2/dt3), -alpha2/(m_steps + 1)); t1 = 1/t1; }; template<class T1, class T2> void operator()(T1 &t1, const T2 &t2) { using std::abs; t1 = adapted_pow(abs(t2), -beta1/(m_steps + 1)); t1 = 1/t1; }; private: template<class T> inline value_type adapted_pow(T base, double exp) { if(exp == 0) { return 1; } else if (exp > 0) { return pow(base, exp); } else { return 1/pow(base, -exp); } }; }; template< class State, class Value = double, class Deriv = State, class Time = double, class Algebra = typename algebra_dispatcher< State >::algebra_type, class Operations = typename operations_dispatcher< Deriv >::operations_type, size_t Type = BASIC > struct pid_step_adjuster { public: static double threshold() { return 0.9; }; typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef rotating_buffer<state_type, 3> error_storage_type; typedef rotating_buffer<time_type, 3> time_storage_type; typedef pid_step_adjuster_coefficients<Type> coeff_type; pid_step_adjuster(double abs_tol = 1e-6, double rel_tol = 1e-6, time_type dtmax = 1.0) :m_dtmax(dtmax), m_error_storage(), m_dt_storage(), m_init(0), m_abs_tol(abs_tol), m_rel_tol(rel_tol) {}; time_type adjust_stepsize(const size_t steps, time_type dt, state_type &err, const state_type &x, const deriv_type &dxdt) { using std::abs; m_algebra.for_each3( err , x , dxdt , typename operations_type::template rel_error< value_type >( m_abs_tol , m_rel_tol , 1.0 , 1.0 * abs(get_unit_value( dt )) ) ); m_error_storage[0] = err; m_dt_storage[0] = dt; if(m_init >= 2) { m_algebra.for_each4(err, m_error_storage[0], m_error_storage[1], m_error_storage[2], pid_op<>(steps, m_dt_storage[0], m_dt_storage[1], m_dt_storage[2], m_coeff[0], m_coeff[1], m_coeff[2], m_coeff[3], m_coeff[4])); } else { m_algebra.for_each2(err, m_error_storage[0], pid_op<>(steps, m_dt_storage[0], m_dt_storage[1], m_dt_storage[2], 0.7)); } value_type ratio = 1 / m_algebra.norm_inf(err); value_type kappa = 1.0; ratio = 1.0 + kappa*atan((ratio - 1) / kappa); if(ratio*dt >= m_dtmax) { ratio = m_dtmax / dt; } if(ratio >= threshold()) { m_error_storage.rotate(); m_dt_storage.rotate(); ++m_init; } else { m_init = 0; } return dt * static_cast<time_type>(ratio); }; private: algebra_type m_algebra; time_type m_dtmax; error_storage_type m_error_storage; time_storage_type m_dt_storage; size_t m_init; double m_abs_tol; double m_rel_tol; coeff_type m_coeff; }; } // detail } // odeint } // numeric } // boost #endif odeint/stepper/detail/generic_rk_algorithm.hpp 0000644 00000020112 15125237305 0015640 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/generic_rk_algorithm.hpp [begin_description] Implementation of the generic Runge-Kutta method. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2012 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED #include <boost/static_assert.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/push_back.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/copy.hpp> #include <boost/mpl/size_t.hpp> #include <boost/fusion/algorithm.hpp> #include <boost/fusion/iterator.hpp> #include <boost/fusion/mpl.hpp> #include <boost/fusion/sequence.hpp> #include <boost/array.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_call_algebra.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_operations.hpp> #include <boost/numeric/odeint/util/bind.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class T , class Constant > struct array_wrapper { typedef const typename boost::array< T , Constant::value > type; }; template< class T , size_t i > struct stage { T c; boost::array< T , i > a; }; template< class T , class Constant > struct stage_wrapper { typedef stage< T , Constant::value > type; }; template< size_t StageCount, class Value , class Algebra , class Operations > class generic_rk_algorithm { public: typedef mpl::range_c< size_t , 1 , StageCount > stage_indices; typedef typename boost::fusion::result_of::as_vector < typename boost::mpl::copy < stage_indices , boost::mpl::inserter < boost::mpl::vector0< > , boost::mpl::push_back< boost::mpl::_1 , array_wrapper< Value , boost::mpl::_2 > > > >::type >::type coef_a_type; typedef boost::array< Value , StageCount > coef_b_type; typedef boost::array< Value , StageCount > coef_c_type; typedef typename boost::fusion::result_of::as_vector < typename boost::mpl::push_back < typename boost::mpl::copy < stage_indices, boost::mpl::inserter < boost::mpl::vector0<> , boost::mpl::push_back< boost::mpl::_1 , stage_wrapper< Value , boost::mpl::_2 > > > >::type , stage< Value , StageCount > >::type >::type stage_vector_base; struct stage_vector : public stage_vector_base { struct do_insertion { stage_vector_base &m_base; const coef_a_type &m_a; const coef_c_type &m_c; do_insertion( stage_vector_base &base , const coef_a_type &a , const coef_c_type &c ) : m_base( base ) , m_a( a ) , m_c( c ) { } template< class Index > void operator()( Index ) const { //boost::fusion::at< Index >( m_base ) = stage< double , Index::value+1 , intermediate_stage >( m_c[ Index::value ] , boost::fusion::at< Index >( m_a ) ); boost::fusion::at< Index >( m_base ).c = m_c[ Index::value ]; boost::fusion::at< Index >( m_base ).a = boost::fusion::at< Index >( m_a ); } }; struct print_butcher { const stage_vector_base &m_base; std::ostream &m_os; print_butcher( const stage_vector_base &base , std::ostream &os ) : m_base( base ) , m_os( os ) { } template<class Index> void operator()(Index) const { m_os << boost::fusion::at<Index>(m_base).c << " | "; for( size_t i=0 ; i<Index::value ; ++i ) m_os << boost::fusion::at<Index>(m_base).a[i] << " "; m_os << std::endl; } }; stage_vector( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c ) { typedef boost::mpl::range_c< size_t , 0 , StageCount-1 > indices; boost::mpl::for_each< indices >( do_insertion( *this , a , c ) ); boost::fusion::at_c< StageCount - 1 >( *this ).c = c[ StageCount - 1 ]; boost::fusion::at_c< StageCount - 1 >( *this ).a = b; } void print( std::ostream &os ) const { typedef boost::mpl::range_c< size_t , 0 , StageCount > indices; boost::mpl::for_each< indices >( print_butcher( *this , os ) ); } }; template< class System , class StateIn , class StateTemp , class DerivIn , class Deriv , class StateOut , class Time > struct calculate_stage { Algebra &algebra; System &system; const StateIn &x; StateTemp &x_tmp; StateOut &x_out; const DerivIn &dxdt; Deriv *F; Time t; Time dt; calculate_stage( Algebra &_algebra , System &_system , const StateIn &_x , const DerivIn &_dxdt , StateOut &_out , StateTemp &_x_tmp , Deriv *_F , Time _t , Time _dt ) : algebra( _algebra ) , system( _system ) , x( _x ) , x_tmp( _x_tmp ) , x_out( _out) , dxdt( _dxdt ) , F( _F ) , t( _t ) , dt( _dt ) {} template< typename T , size_t stage_number > void inline operator()( stage< T , stage_number > const &stage ) const //typename stage_fusion_wrapper< T , mpl::size_t< stage_number > , intermediate_stage >::type const &stage ) const { if( stage_number > 1 ) { #ifdef BOOST_MSVC #pragma warning( disable : 4307 34 ) #endif system( x_tmp , F[stage_number-2].m_v , t + stage.c * dt ); #ifdef BOOST_MSVC #pragma warning( default : 4307 34 ) #endif } //std::cout << stage_number-2 << ", t': " << t + stage.c * dt << std::endl; if( stage_number < StageCount ) detail::template generic_rk_call_algebra< stage_number , Algebra >()( algebra , x_tmp , x , dxdt , F , detail::generic_rk_scale_sum< stage_number , Operations , Value , Time >( stage.a , dt) ); // algebra_type::template for_eachn<stage_number>( x_tmp , x , dxdt , F , // typename operations_type::template scale_sumn< stage_number , time_type >( stage.a , dt ) ); else detail::template generic_rk_call_algebra< stage_number , Algebra >()( algebra , x_out , x , dxdt , F , detail::generic_rk_scale_sum< stage_number , Operations , Value , Time >( stage.a , dt ) ); // algebra_type::template for_eachn<stage_number>( x_out , x , dxdt , F , // typename operations_type::template scale_sumn< stage_number , time_type >( stage.a , dt ) ); } }; generic_rk_algorithm( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c ) : m_stages( a , b , c ) { } template< class System , class StateIn , class DerivIn , class Time , class StateOut , class StateTemp , class Deriv > void inline do_step( Algebra &algebra , System system , const StateIn &in , const DerivIn &dxdt , Time t , StateOut &out , Time dt , StateTemp &x_tmp , Deriv F[StageCount-1] ) const { typedef typename odeint::unwrap_reference< System >::type unwrapped_system_type; unwrapped_system_type &sys = system; boost::fusion::for_each( m_stages , calculate_stage< unwrapped_system_type , StateIn , StateTemp , DerivIn , Deriv , StateOut , Time > ( algebra , sys , in , dxdt , out , x_tmp , F , t , dt ) ); } private: stage_vector m_stages; }; } } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED odeint/stepper/detail/generic_rk_operations.hpp 0000644 00000023107 15125237305 0016044 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/generic_rk_operations.hpp [begin_description] Operations caller for the generic Runge Kutta method. [end_description] Copyright 2011 Mario Mulansky Copyright 2011-2012 Karsten Ahnert 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_ODEINT_STEPPER_DETAIL_GENERIC_RK_OPERATIONS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_OPERATIONS_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { namespace detail { template< size_t StageNumber , class Operations , class Fac , class Time > struct generic_rk_scale_sum; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 1 , Operations , Fac , Time > : public Operations::template scale_sum2< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,1> &a , Time dt ) : Operations::template scale_sum2< Fac , Time >( 1.0 , a[0]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 2 , Operations , Fac , Time > : public Operations::template scale_sum3< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,2> &a , Time dt ) : Operations::template scale_sum3< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 3 , Operations , Fac , Time > : public Operations::template scale_sum4< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,3> &a , Time dt ) : Operations::template scale_sum4< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 4 , Operations , Fac , Time > : public Operations::template scale_sum5< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,4> &a , Time dt ) : Operations::template scale_sum5< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 5 , Operations , Fac , Time > : public Operations::template scale_sum6< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,5> &a , Time dt ) : Operations::template scale_sum6< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 6 , Operations , Fac , Time > : public Operations::template scale_sum7< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,6> &a , Time dt ) : Operations::template scale_sum7< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 7 , Operations , Fac , Time > : public Operations::template scale_sum8< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,7> &a , Time dt ) : Operations::template scale_sum8< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 8 , Operations , Fac , Time > : public Operations::template scale_sum9< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,8> &a , Time dt ) : Operations::template scale_sum9< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 9 , Operations , Fac , Time > : public Operations::template scale_sum10< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,9> &a , Time dt ) : Operations::template scale_sum10< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 10 , Operations , Fac , Time > : public Operations::template scale_sum11< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,10> &a , Time dt ) : Operations::template scale_sum11< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt , a[9]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 11 , Operations , Fac , Time > : public Operations::template scale_sum12< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,11> &a , Time dt ) : Operations::template scale_sum12< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt , a[9]*dt , a[10]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 12 , Operations , Fac , Time > : public Operations::template scale_sum13< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,12> &a , Time dt ) : Operations::template scale_sum13< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt , a[9]*dt , a[10]*dt , a[11]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum< 13 , Operations , Fac , Time > : public Operations::template scale_sum14< Fac , Time > { generic_rk_scale_sum( const boost::array<Fac,13> &a , Time dt ) : Operations::template scale_sum14< Fac , Time >( 1.0 , a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt , a[9]*dt , a[10]*dt , a[11]*dt , a[12]*dt ) { } typedef void result_type; }; // for error estimates template< size_t StageNumber , class Operations , class Fac , class Time > struct generic_rk_scale_sum_err; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 1 , Operations , Fac , Time > : public Operations::template scale_sum1< Time > { generic_rk_scale_sum_err( const boost::array<Fac,1> &a , Time dt ) : Operations::template scale_sum1< Time >( a[0]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 2 , Operations , Fac , Time > : public Operations::template scale_sum2< Time > { generic_rk_scale_sum_err( const boost::array<Fac,2> &a , Time dt ) : Operations::template scale_sum2< Time >( a[0]*dt , a[1]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 3 , Operations , Fac , Time > : public Operations::template scale_sum3< Time > { generic_rk_scale_sum_err( const boost::array<Fac,3> &a , Time dt ) : Operations::template scale_sum3< Time >( a[0]*dt , a[1]*dt , a[2]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 4 , Operations , Fac , Time > : public Operations::template scale_sum4< Time > { generic_rk_scale_sum_err( const boost::array<Fac,4> &a , Time dt ) : Operations::template scale_sum4< Time >( a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 5 , Operations , Fac , Time > : public Operations::template scale_sum5< Fac > { generic_rk_scale_sum_err( const boost::array<Fac,5> &a , Time dt ) : Operations::template scale_sum5< Time >( a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt ) { } typedef void result_type; }; template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 6 , Operations , Fac , Time > : public Operations::template scale_sum6< Time > { generic_rk_scale_sum_err( const boost::array<Fac,6> &a , Time dt ) : Operations::template scale_sum6< Time >( a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt ) { } typedef void result_type; }; // for rk87 template< class Operations , class Fac , class Time > struct generic_rk_scale_sum_err< 13 , Operations , Fac , Time > : public Operations::template scale_sum13< Time > { generic_rk_scale_sum_err( const boost::array<Fac,13> &a , Time dt ) : Operations::template scale_sum13< Time >( a[0]*dt , a[1]*dt , a[2]*dt , a[3]*dt , a[4]*dt , a[5]*dt , a[6]*dt , a[7]*dt , a[8]*dt , a[9]*dt , a[10]*dt , a[11]*dt , a[12]*dt ) { } typedef void result_type; }; } } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_OPERATIONS_HPP_INCLUDED odeint/stepper/detail/generic_rk_call_algebra.hpp 0000644 00000024431 15125237305 0016252 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/generic_rk_call_algebra.hpp [begin_description] Algebra caller for the generic Runge-Kutta methods. [end_description] Copyright 2011-2012 Mario Mulansky Copyright 2011-2012 Karsten Ahnert 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_ODEINT_STEPPER_DETAIL_GENERIC_RK_CALL_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_CALL_ALGEBRA_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { namespace detail { template< size_t StageNumber , class Algebra > struct generic_rk_call_algebra; template< class Algebra > struct generic_rk_call_algebra< 1 , Algebra > { typedef Algebra algebra_type; template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( algebra_type &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 * /* s4_array */ , Op op ) const { algebra.for_each3( s1 , s2 , s3 , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( algebra_type &algebra , S1 &s1 , S2 &s2 , S4 * /* s4_array */ , Op op ) const { algebra.for_each2( s1 , s2 , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 2 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[1] , Op op ) const { algebra.for_each4( s1 , s2 , s3 , s4_array[0].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[1] , Op op ) const { algebra.for_each3( s1 , s2 , s4_array[0].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 3 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[2] , Op op ) const { algebra.for_each5( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[2] , Op op ) const { algebra.for_each4( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 4 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[3] , Op op ) const { algebra.for_each6( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[3] , Op op ) const { algebra.for_each5( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 5 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[4] , Op op ) const { algebra.for_each7( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[4] , Op op ) const { algebra.for_each6( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 6 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[5] , Op op ) const { algebra.for_each8( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[5] , Op op ) const { algebra.for_each7( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 7 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[6] , Op op ) const { algebra.for_each9( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[6] , Op op ) const { algebra.for_each8( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 8 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[7] , Op op ) const { algebra.for_each10( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[7] , Op op ) const { algebra.for_each9( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 9 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[8] , Op op ) const { algebra.for_each11( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[8] , Op op ) const { algebra.for_each10( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 10 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[9] , Op op ) const { algebra.for_each12( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[9] , Op op ) const { algebra.for_each11( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 11 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[10] , Op op ) const { algebra.for_each13( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[10] , Op op ) const { algebra.for_each12( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 12 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[11] , Op op ) const { algebra.for_each14( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , s4_array[10].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[11] , Op op ) const { algebra.for_each13( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , s4_array[10].m_v , op ); } }; template< class Algebra > struct generic_rk_call_algebra< 13 , Algebra > { template< class S1 , class S2 , class S3 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S3 &s3 , S4 s4_array[12] , Op op ) const { algebra.for_each15( s1 , s2 , s3 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , s4_array[10].m_v , s4_array[11].m_v , op ); } template< class S1 , class S2 , class S4 , class Op> void operator()( Algebra &algebra , S1 &s1 , S2 &s2 , S4 s4_array[12] , Op op ) const { algebra.for_each14( s1 , s2 , s4_array[0].m_v , s4_array[1].m_v , s4_array[2].m_v , s4_array[3].m_v , s4_array[4].m_v , s4_array[5].m_v , s4_array[6].m_v , s4_array[7].m_v , s4_array[8].m_v , s4_array[9].m_v , s4_array[10].m_v , s4_array[11].m_v , op ); } }; } } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_CALL_ALGEBRA_HPP_INCLUDED odeint/stepper/detail/adams_bashforth_call_algebra.hpp 0000644 00000015410 15125237305 0017264 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/adams_bashforth_call_algebra.hpp [begin_description] Algebra caller for the Adams Bashforth stepper. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_CALL_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_CALL_ALGEBRA_HPP_INCLUDED #include <boost/assert.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< size_t Step , class Algebra , class Operations > struct adams_bashforth_call_algebra; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 1 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each3( out , in , steps[0].m_v , typename Operations::template scale_sum2< value_type , Time >( 1.0 , dt * coef[0] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 2 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each4( out , in , steps[0].m_v , steps[1].m_v , typename Operations::template scale_sum3< value_type , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 3 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each5( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , typename Operations::template scale_sum4< value_type , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 4 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each6( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , typename Operations::template scale_sum5< value_type , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 5 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each7( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , typename Operations::template scale_sum6< value_type , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 6 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each8( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , steps[5].m_v , typename Operations::template scale_sum7< value_type , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 7 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { //BOOST_ASSERT( false ); // not implemented typedef typename Coefficients::value_type value_type; algebra.for_each9( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , steps[5].m_v , steps[6].m_v , typename Operations::template scale_sum8< value_type , Time , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] , dt * coef[6] ) ); } }; template< class Algebra , class Operations > struct adams_bashforth_call_algebra< 8 , Algebra , Operations > { template< class StateIn , class StateOut , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const StepStorage &steps , const Coefficients &coef , Time dt ) const { //BOOST_ASSERT( false ); // not implemented typedef typename Coefficients::value_type value_type; algebra.for_each10( out , in , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , steps[5].m_v , steps[6].m_v , steps[7].m_v , typename Operations::template scale_sum9< value_type , Time , Time , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] , dt * coef[6] , dt * coef[7] ) ); } }; } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_CALL_ALGEBRA_HPP_INCLUDED odeint/stepper/detail/adams_bashforth_coefficients.hpp 0000644 00000012641 15125237305 0017340 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/adams_bashforth_coefficients.hpp [begin_description] Definition of the coefficients for the Adams-Bashforth method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_COEFFICIENTS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_COEFFICIENTS_HPP_INCLUDED #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Value , size_t Steps > class adams_bashforth_coefficients ; template< class Value > class adams_bashforth_coefficients< Value , 1 > : public boost::array< Value , 1 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 1 >() { (*this)[0] = static_cast< Value >( 1 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 2 > : public boost::array< Value , 2 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 2 >() { (*this)[0] = static_cast< Value >( 3 ) / static_cast< Value >( 2 ); (*this)[1] = -static_cast< Value >( 1 ) / static_cast< Value >( 2 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 3 > : public boost::array< Value , 3 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 3 >() { (*this)[0] = static_cast< Value >( 23 ) / static_cast< Value >( 12 ); (*this)[1] = -static_cast< Value >( 4 ) / static_cast< Value >( 3 ); (*this)[2] = static_cast< Value >( 5 ) / static_cast< Value >( 12 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 4 > : public boost::array< Value , 4 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 4 >() { (*this)[0] = static_cast< Value >( 55 ) / static_cast< Value >( 24 ); (*this)[1] = -static_cast< Value >( 59 ) / static_cast< Value >( 24 ); (*this)[2] = static_cast< Value >( 37 ) / static_cast< Value >( 24 ); (*this)[3] = -static_cast< Value >( 3 ) / static_cast< Value >( 8 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 5 > : public boost::array< Value , 5 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 5 >() { (*this)[0] = static_cast< Value >( 1901 ) / static_cast< Value >( 720 ); (*this)[1] = -static_cast< Value >( 1387 ) / static_cast< Value >( 360 ); (*this)[2] = static_cast< Value >( 109 ) / static_cast< Value >( 30 ); (*this)[3] = -static_cast< Value >( 637 ) / static_cast< Value >( 360 ); (*this)[4] = static_cast< Value >( 251 ) / static_cast< Value >( 720 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 6 > : public boost::array< Value , 6 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 6 >() { (*this)[0] = static_cast< Value >( 4277 ) / static_cast< Value >( 1440 ); (*this)[1] = -static_cast< Value >( 2641 ) / static_cast< Value >( 480 ); (*this)[2] = static_cast< Value >( 4991 ) / static_cast< Value >( 720 ); (*this)[3] = -static_cast< Value >( 3649 ) / static_cast< Value >( 720 ); (*this)[4] = static_cast< Value >( 959 ) / static_cast< Value >( 480 ); (*this)[5] = -static_cast< Value >( 95 ) / static_cast< Value >( 288 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 7 > : public boost::array< Value , 7 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 7 >() { (*this)[0] = static_cast< Value >( 198721 ) / static_cast< Value >( 60480 ); (*this)[1] = -static_cast< Value >( 18637 ) / static_cast< Value >( 2520 ); (*this)[2] = static_cast< Value >( 235183 ) / static_cast< Value >( 20160 ); (*this)[3] = -static_cast< Value >( 10754 ) / static_cast< Value >( 945 ); (*this)[4] = static_cast< Value >( 135713 ) / static_cast< Value >( 20160 ); (*this)[5] = -static_cast< Value >( 5603 ) / static_cast< Value >( 2520 ); (*this)[6] = static_cast< Value >( 19087 ) / static_cast< Value >( 60480 ); } }; template< class Value > class adams_bashforth_coefficients< Value , 8 > : public boost::array< Value , 8 > { public: adams_bashforth_coefficients( void ) : boost::array< Value , 8 >() { (*this)[0] = static_cast< Value >( 16083 ) / static_cast< Value >( 4480 ); (*this)[1] = -static_cast< Value >( 1152169 ) / static_cast< Value >( 120960 ); (*this)[2] = static_cast< Value >( 242653 ) / static_cast< Value >( 13440 ); (*this)[3] = -static_cast< Value >( 296053 ) / static_cast< Value >( 13440 ); (*this)[4] = static_cast< Value >( 2102243 ) / static_cast< Value >( 120960 ); (*this)[5] = -static_cast< Value >( 115747 ) / static_cast< Value >( 13440 ); (*this)[6] = static_cast< Value >( 32863 ) / static_cast< Value >( 13440 ); (*this)[7] = -static_cast< Value >( 5257 ) / static_cast< Value >( 17280 ); } }; } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_BASHFORTH_COEFFICIENTS_HPP_INCLUDED odeint/stepper/detail/adams_moulton_coefficients.hpp 0000644 00000012501 15125237305 0017050 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/adams_moulton_coefficients.hpp [begin_description] Coefficients for the Adams Moulton method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_COEFFICIENTS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_COEFFICIENTS_HPP_INCLUDED #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Value , size_t Steps > class adams_moulton_coefficients ; template< class Value > class adams_moulton_coefficients< Value , 1 > : public boost::array< Value , 1 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 1 >() { (*this)[0] = static_cast< Value >( 1 ); } }; template< class Value > class adams_moulton_coefficients< Value , 2 > : public boost::array< Value , 2 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 2 >() { (*this)[0] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); (*this)[1] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ); } }; template< class Value > class adams_moulton_coefficients< Value , 3 > : public boost::array< Value , 3 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 3 >() { (*this)[0] = static_cast< Value >( 5 ) / static_cast< Value >( 12 ); (*this)[1] = static_cast< Value >( 2 ) / static_cast< Value >( 3 ); (*this)[2] = -static_cast< Value >( 1 ) / static_cast< Value >( 12 ); } }; template< class Value > class adams_moulton_coefficients< Value , 4 > : public boost::array< Value , 4 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 4 >() { (*this)[0] = static_cast< Value >( 3 ) / static_cast< Value >( 8 ); (*this)[1] = static_cast< Value >( 19 ) / static_cast< Value >( 24 ); (*this)[2] = -static_cast< Value >( 5 ) / static_cast< Value >( 24 ); (*this)[3] = static_cast< Value >( 1 ) / static_cast< Value >( 24 ); } }; template< class Value > class adams_moulton_coefficients< Value , 5 > : public boost::array< Value , 5 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 5 >() { (*this)[0] = static_cast< Value >( 251 ) / static_cast< Value >( 720 ); (*this)[1] = static_cast< Value >( 323 ) / static_cast< Value >( 360 ); (*this)[2] = -static_cast< Value >( 11 ) / static_cast< Value >( 30 ); (*this)[3] = static_cast< Value >( 53 ) / static_cast< Value >( 360 ); (*this)[4] = -static_cast< Value >( 19 ) / static_cast< Value >( 720 ); } }; template< class Value > class adams_moulton_coefficients< Value , 6 > : public boost::array< Value , 6 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 6 >() { (*this)[0] = static_cast< Value >( 95 ) / static_cast< Value >( 288 ); (*this)[1] = static_cast< Value >( 1427 ) / static_cast< Value >( 1440 ); (*this)[2] = -static_cast< Value >( 133 ) / static_cast< Value >( 240 ); (*this)[3] = static_cast< Value >( 241 ) / static_cast< Value >( 720 ); (*this)[4] = -static_cast< Value >( 173 ) / static_cast< Value >( 1440 ); (*this)[5] = static_cast< Value >( 3 ) / static_cast< Value >( 160 ); } }; template< class Value > class adams_moulton_coefficients< Value , 7 > : public boost::array< Value , 7 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 7 >() { (*this)[0] = static_cast< Value >( 19087 ) / static_cast< Value >( 60480 ); (*this)[1] = static_cast< Value >( 2713 ) / static_cast< Value >( 2520 ); (*this)[2] = -static_cast< Value >( 15487 ) / static_cast< Value >( 20160 ); (*this)[3] = static_cast< Value >( 586 ) / static_cast< Value >( 945 ); (*this)[4] = -static_cast< Value >( 6737 ) / static_cast< Value >( 20160 ); (*this)[5] = static_cast< Value >( 263 ) / static_cast< Value >( 2520 ); (*this)[6] = -static_cast< Value >( 863 ) / static_cast< Value >( 60480 ); } }; template< class Value > class adams_moulton_coefficients< Value , 8 > : public boost::array< Value , 8 > { public: adams_moulton_coefficients( void ) : boost::array< Value , 8 >() { (*this)[0] = static_cast< Value >( 5257 ) / static_cast< Value >( 17280 ); (*this)[1] = static_cast< Value >( 139849 ) / static_cast< Value >( 120960 ); (*this)[2] = -static_cast< Value >( 4511 ) / static_cast< Value >( 4480 ); (*this)[3] = static_cast< Value >( 123133 ) / static_cast< Value >( 120960 ); (*this)[4] = -static_cast< Value >( 88547 ) / static_cast< Value >( 120960 ); (*this)[5] = static_cast< Value >( 1537 ) / static_cast< Value >( 4480 ); (*this)[6] = -static_cast< Value >( 11351 ) / static_cast< Value >( 120960 ); (*this)[7] = static_cast< Value >( 275 ) / static_cast< Value >( 24192 ); } }; } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_COEFFICIENTS_HPP_INCLUDED odeint/stepper/detail/adaptive_adams_coefficients.hpp 0000644 00000013476 15125237305 0017164 0 ustar 00 /* boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp [begin_description] Calculation of the coefficients for the adaptive adams stepper. [end_description] Copyright 2017 Valentin Noah Hartmann 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_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< size_t Steps, class Deriv, class Value = double, class Time = double, class Algebra = typename algebra_dispatcher< Deriv >::algebra_type, class Operations = typename operations_dispatcher< Deriv >::operations_type, class Resizer = initially_resizer > class adaptive_adams_coefficients { public: static const size_t steps = Steps; typedef unsigned short order_type; static const order_type order_value = steps; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef rotating_buffer< time_type , steps+1 > time_storage_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; typedef adaptive_adams_coefficients< Steps , Deriv , Value , Time , Algebra , Operations , Resizer > aac_type; adaptive_adams_coefficients( const algebra_type &algebra = algebra_type()) :m_eo(1), m_steps_init(1), beta(), phi(), m_ns(0), m_time_storage(), m_algebra(algebra), m_phi_resizer() { for (size_t i=0; i<order_value+2; ++i) { c[i] = 1.0/(i+1); c[c_size+i] = 1.0/((i+1)*(i+2)); } g[0] = c[0]; g[1] = c[c_size]; beta[0][0] = 1; beta[1][0] = 1; gs[0] = 1.0; gs[1] = -1.0/2; gs[2] = -1.0/12; gs[3] = -1.0/24; gs[4] = -19.0/720; gs[5] = -3.0/160; gs[6] = -863.0/60480; gs[7] = -275.0/24192; gs[8] = -33953.0/3628800; gs[9] = 35.0/4436; gs[10] = 40.0/5891; gs[11] = 37.0/6250; gs[12] = 25.0/4771; gs[13] = 40.0/8547; }; void predict(time_type t, time_type dt) { using std::abs; m_time_storage[0] = t; if (abs(m_time_storage[0] - m_time_storage[1] - dt) > 1e-16 || m_eo >= m_ns) { m_ns = 0; } else if (m_ns < order_value + 2) { m_ns++; } for(size_t i=1+m_ns; i<m_eo+1 && i<m_steps_init; ++i) { time_type diff = m_time_storage[0] - m_time_storage[i]; beta[0][i] = beta[0][i-1]*(m_time_storage[0] + dt - m_time_storage[i-1])/diff; } for(size_t i=2+m_ns; i<m_eo+2 && i<m_steps_init+1; ++i) { time_type diff = m_time_storage[0] + dt - m_time_storage[i-1]; for(size_t j=0; j<m_eo+1-i+1; ++j) { c[c_size*i+j] = c[c_size*(i-1)+j] - c[c_size*(i-1)+j+1]*dt/diff; } g[i] = c[c_size*i]; } }; void do_step(const deriv_type &dxdt, const int o = 0) { m_phi_resizer.adjust_size( dxdt , detail::bind( &aac_type::template resize_phi_impl< deriv_type > , detail::ref( *this ) , detail::_1 ) ); phi[o][0].m_v = dxdt; for(size_t i=1; i<m_eo+3 && i<m_steps_init+2 && i<order_value+2; ++i) { if (o == 0) { this->m_algebra.for_each3(phi[o][i].m_v, phi[o][i-1].m_v, phi[o+1][i-1].m_v, typename Operations::template scale_sum2<value_type, value_type>(1.0, -beta[o][i-1])); } else { this->m_algebra.for_each2(phi[o][i].m_v, phi[o][i-1].m_v, typename Operations::template scale_sum1<value_type>(1.0)); } } }; void confirm() { beta.rotate(); phi.rotate(); m_time_storage.rotate(); if(m_steps_init < order_value+1) { ++m_steps_init; } }; void reset() { m_eo = 1; m_steps_init = 1; }; size_t m_eo; size_t m_steps_init; rotating_buffer<boost::array<value_type, order_value+1>, 2> beta; // beta[0] = beta(n) rotating_buffer<boost::array<wrapped_deriv_type, order_value+2>, 3> phi; // phi[0] = phi(n+1) boost::array<value_type, order_value + 2> g; boost::array<value_type, 14> gs; private: template< class StateType > bool resize_phi_impl( const StateType &x ) { bool resized( false ); for(size_t i=0; i<(order_value + 2); ++i) { resized |= adjust_size_by_resizeability( phi[0][i], x, typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( phi[1][i], x, typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( phi[2][i], x, typename is_resizeable<deriv_type>::type() ); } return resized; }; size_t m_ns; time_storage_type m_time_storage; static const size_t c_size = order_value + 2; boost::array<value_type, c_size*c_size> c; algebra_type m_algebra; resizer_type m_phi_resizer; }; } // detail } // odeint } // numeric } // boost #endif odeint/stepper/detail/adams_moulton_call_algebra.hpp 0000644 00000015510 15125237305 0017002 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/adams_moulton_call_algebra.hpp [begin_description] Algebra caller for the Adams Moulton method. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_CALL_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_CALL_ALGEBRA_HPP_INCLUDED #include <boost/assert.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< size_t Step , class Algebra , class Operations > struct adams_moulton_call_algebra; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 1 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage& /* steps */ , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each3( out , in , dxdt , typename Operations::template scale_sum2< value_type , Time >( 1.0 , dt * coef[0] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 2 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each4( out , in , dxdt , steps[0].m_v , typename Operations::template scale_sum3< value_type , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 3 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each5( out , in , dxdt , steps[0].m_v , steps[1].m_v , typename Operations::template scale_sum4< value_type , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 4 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each6( out , in , dxdt , steps[0].m_v , steps[1].m_v , steps[2].m_v , typename Operations::template scale_sum5< value_type , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 5 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each7( out , in , dxdt , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , typename Operations::template scale_sum6< value_type , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 6 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each8( out , in , dxdt , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , typename Operations::template scale_sum7< value_type , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 7 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each9( out , in , dxdt , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , steps[5].m_v , typename Operations::template scale_sum8< value_type , Time , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] , dt * coef[6] ) ); } }; template< class Algebra , class Operations > struct adams_moulton_call_algebra< 8 , Algebra , Operations > { template< class StateIn , class StateOut , class DerivIn , class StepStorage , class Coefficients , class Time > void operator()( Algebra &algebra , const StateIn &in , StateOut &out , const DerivIn &dxdt , const StepStorage &steps , const Coefficients &coef , Time dt ) const { typedef typename Coefficients::value_type value_type; algebra.for_each10( out , in , dxdt , steps[0].m_v , steps[1].m_v , steps[2].m_v , steps[3].m_v , steps[4].m_v , steps[5].m_v , steps[6].m_v , typename Operations::template scale_sum9< value_type , Time , Time , Time , Time , Time , Time , Time >( 1.0 , dt * coef[0] , dt * coef[1] , dt * coef[2] , dt * coef[3] , dt * coef[4] , dt * coef[5] , dt * coef[6] , dt * coef[7] ) ); } }; } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAMS_MOULTON_CALL_ALGEBRA_HPP_INCLUDED odeint/stepper/detail/rotating_buffer.hpp 0000644 00000002776 15125237305 0014662 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/detail/rotating_buffer.hpp [begin_description] Implemetation of a rotating (cyclic) buffer for use in the Adam Bashforth stepper [end_description] Copyright 2011 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_STEPPER_DETAIL_ROTATING_BUFFER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ROTATING_BUFFER_HPP_INCLUDED #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class T , size_t N > class rotating_buffer { public: typedef T value_type; const static size_t dim = N; rotating_buffer( void ) : m_first( 0 ) { } size_t size( void ) const { return dim; } value_type& operator[]( size_t i ) { return m_data[ get_index( i ) ]; } const value_type& operator[]( size_t i ) const { return m_data[ get_index( i ) ]; } void rotate( void ) { if( m_first == 0 ) m_first = dim-1; else --m_first; } protected: value_type m_data[N]; private: size_t get_index( size_t i ) const { return ( ( i + m_first ) % dim ); } size_t m_first; }; } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ROTATING_BUFFER_HPP_INCLUDED odeint/stepper/detail/pid_step_adjuster_coefficients.hpp 0000644 00000007472 15125237305 0017731 0 ustar 00 /* boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp [begin_description] Coefficients for the PID stepsize controller. [end_description] Copyright 2017 Valentin Noah Hartmann 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_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_COEFFICIENTS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_COEFFICIENTS_HPP_INCLUDED #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { enum adjuster_type{ BASIC, H0211, H211b, H211PI, H0312, H312b, H312PID, H0321, H321 }; template<int Type> class pid_step_adjuster_coefficients; template<> class pid_step_adjuster_coefficients<BASIC> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0; (*this)[1] = 0.0; (*this)[2] = 0.0; (*this)[3] = 0.0; (*this)[4] = 0.0; } }; template<> class pid_step_adjuster_coefficients<H0211> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 2.0; (*this)[1] = 1.0 / 2.0; (*this)[2] = 0.0; (*this)[3] = 1.0 / 2.0; (*this)[4] = 0.0; } }; template<> class pid_step_adjuster_coefficients<H211b> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 5.0; (*this)[1] = 2.0 / 5.0; (*this)[2] = 0.0; (*this)[3] = 1.0 / 5.0; (*this)[4] = 0.0; } }; template<> class pid_step_adjuster_coefficients<H211PI> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 6.0; (*this)[1] = 2.0 / 6.0; (*this)[2] = 0.0; (*this)[3] = 0.0; (*this)[4] = 0.0; } }; template<> class pid_step_adjuster_coefficients<H0312> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 4.0; (*this)[1] = 2.0 / 2.0; (*this)[2] = 1.0 / 4.0; (*this)[3] = 3.0 / 4.0; (*this)[4] = 1.0 / 4.0; } }; template<> class pid_step_adjuster_coefficients<H312b> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 6.0; (*this)[1] = 2.0 / 6.0; (*this)[2] = 1.0 / 6.0; (*this)[3] = 3.0 / 6.0; (*this)[4] = 1.0 / 6.0; } }; template<> class pid_step_adjuster_coefficients<H312PID> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 18.0; (*this)[1] = 2.0 / 9.0; (*this)[2] = 1.0 / 18.0; (*this)[3] = 0.0; (*this)[4] = 0.0; } }; template<> class pid_step_adjuster_coefficients<H0321> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 5.0 / 4.0; (*this)[1] = 1.0 / 2.0; (*this)[2] = -3.0 / 4.0; (*this)[3] = -1.0 / 4.0; (*this)[4] = -3.0 / 4.0; } }; template<> class pid_step_adjuster_coefficients<H321> : public boost::array<double, 5> { public: pid_step_adjuster_coefficients() : boost::array<double, 5>() { (*this)[0] = 1.0 / 3.0; (*this)[1] = 1.0 / 18.0; (*this)[2] = -5.0 / 18.0; (*this)[3] = -5.0 / 16.0; (*this)[4] = -1.0 / 6.0; } }; } // detail } // odeint } // numeric } // boost #endif odeint/stepper/controlled_runge_kutta.hpp 0000644 00000112635 15125237305 0015011 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/controlled_runge_kutta.hpp [begin_description] The default controlled stepper which can be used with all explicit Runge-Kutta error steppers. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2015 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED #include <cmath> #include <boost/config.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> namespace boost { namespace numeric { namespace odeint { template < class Value , class Algebra , class Operations > class default_error_checker { public: typedef Value value_type; typedef Algebra algebra_type; typedef Operations operations_type; default_error_checker( value_type eps_abs = static_cast< value_type >( 1.0e-6 ) , value_type eps_rel = static_cast< value_type >( 1.0e-6 ) , value_type a_x = static_cast< value_type >( 1 ) , value_type a_dxdt = static_cast< value_type >( 1 )) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) , m_a_x( a_x ) , m_a_dxdt( a_dxdt ) { } template< class State , class Deriv , class Err, class Time > value_type error( const State &x_old , const Deriv &dxdt_old , Err &x_err , Time dt ) const { return error( algebra_type() , x_old , dxdt_old , x_err , dt ); } template< class State , class Deriv , class Err, class Time > value_type error( algebra_type &algebra , const State &x_old , const Deriv &dxdt_old , Err &x_err , Time dt ) const { using std::abs; // this overwrites x_err ! algebra.for_each3( x_err , x_old , dxdt_old , typename operations_type::template rel_error< value_type >( m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt * abs(get_unit_value( dt )) ) ); // value_type res = algebra.reduce( x_err , // typename operations_type::template maximum< value_type >() , static_cast< value_type >( 0 ) ); return algebra.norm_inf( x_err ); } private: value_type m_eps_abs; value_type m_eps_rel; value_type m_a_x; value_type m_a_dxdt; }; template< typename Value, typename Time > class default_step_adjuster { public: typedef Time time_type; typedef Value value_type; default_step_adjuster(const time_type max_dt=static_cast<time_type>(0)) : m_max_dt(max_dt) {} time_type decrease_step(time_type dt, const value_type error, const int error_order) const { // returns the decreased time step BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; dt *= max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( static_cast<value_type>(9) / static_cast<value_type>(10) * pow(error, static_cast<value_type>(-1) / (error_order - 1))), static_cast<value_type>( static_cast<value_type>(1) / static_cast<value_type> (5))); if(m_max_dt != static_cast<time_type >(0)) // limit to maximal stepsize even when decreasing dt = detail::min_abs(dt, m_max_dt); return dt; } time_type increase_step(time_type dt, value_type error, const int stepper_order) const { // returns the increased time step BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; // adjust the size if dt is smaller than max_dt (providede max_dt is not zero) if(error < 0.5) { // error should be > 0 error = max BOOST_PREVENT_MACRO_SUBSTITUTION ( static_cast<value_type>( pow( static_cast<value_type>(5.0) , -static_cast<value_type>(stepper_order) ) ) , error); // time_type dt_old = dt; unused variable warning //error too small - increase dt and keep the evolution and limit scaling factor to 5.0 dt *= static_cast<value_type>(9)/static_cast<value_type>(10) * pow(error, static_cast<value_type>(-1) / stepper_order); if(m_max_dt != static_cast<time_type >(0)) // limit to maximal stepsize dt = detail::min_abs(dt, m_max_dt); } return dt; } bool check_step_size_limit(const time_type dt) { if(m_max_dt != static_cast<time_type >(0)) return detail::less_eq_with_sign(dt, m_max_dt, dt); return true; } time_type get_max_dt() { return m_max_dt; } protected: time_type m_max_dt; }; /* * error stepper category dispatcher */ template< class ErrorStepper , class ErrorChecker = default_error_checker< typename ErrorStepper::value_type , typename ErrorStepper::algebra_type , typename ErrorStepper::operations_type > , class StepAdjuster = default_step_adjuster< typename ErrorStepper::value_type , typename ErrorStepper::time_type > , class Resizer = typename ErrorStepper::resizer_type , class ErrorStepperCategory = typename ErrorStepper::stepper_category > class controlled_runge_kutta ; /* * explicit stepper version * * this class introduces the following try_step overloads * try_step( sys , x , t , dt ) * try_step( sys , x , dxdt , t , dt ) * try_step( sys , in , t , out , dt ) * try_step( sys , in , dxdt , t , out , dt ) */ /** * \brief Implements step size control for Runge-Kutta steppers with error * estimation. * * This class implements the step size control for standard Runge-Kutta * steppers with error estimation. * * \tparam ErrorStepper The stepper type with error estimation, has to fulfill the ErrorStepper concept. * \tparam ErrorChecker The error checker * \tparam Resizer The resizer policy type. */ template< class ErrorStepper, class ErrorChecker, class StepAdjuster, class Resizer > class controlled_runge_kutta< ErrorStepper , ErrorChecker , StepAdjuster, Resizer , explicit_error_stepper_tag > { public: typedef ErrorStepper stepper_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::algebra_type algebra_type; typedef typename stepper_type::operations_type operations_type; typedef Resizer resizer_type; typedef ErrorChecker error_checker_type; typedef StepAdjuster step_adjuster_type; typedef explicit_controlled_stepper_tag stepper_category; #ifndef DOXYGEN_SKIP typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef controlled_runge_kutta< ErrorStepper , ErrorChecker , StepAdjuster , Resizer , explicit_error_stepper_tag > controlled_stepper_type; #endif //DOXYGEN_SKIP /** * \brief Constructs the controlled Runge-Kutta stepper. * \param error_checker An instance of the error checker. * \param stepper An instance of the underlying stepper. */ controlled_runge_kutta( const error_checker_type &error_checker = error_checker_type( ) , const step_adjuster_type &step_adjuster = step_adjuster_type() , const stepper_type &stepper = stepper_type( ) ) : m_stepper(stepper), m_error_checker(error_checker) , m_step_adjuster(step_adjuster) { } /* * Version 1 : try_step( sys , x , t , dt ) * * The overloads are needed to solve the forwarding problem */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut > controlled_step_result try_step( System system , StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t, dt ); } /** * \brief Tries to perform one step. Solves the forwarding problem and * allows for using boost range as state_type. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. Can be a boost range. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut > controlled_step_result try_step( System system , const StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t, dt ); } /* * Version 2 : try_step( sys , x , dxdt , t , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut , class DerivIn > controlled_step_result try_step( System system , StateInOut &x , const DerivIn &dxdt , time_type &t , time_type &dt ) { m_xnew_resizer.adjust_size( x , detail::bind( &controlled_runge_kutta::template resize_m_xnew_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); controlled_step_result res = try_step( system , x , dxdt , t , m_xnew.m_v , dt ); if( res == success ) { boost::numeric::odeint::copy( m_xnew.m_v , x ); } return res; } /* * Version 3 : try_step( sys , in , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ /** * \brief Tries to perform one step. * * \note This method is disabled if state_type=time_type to avoid ambiguity. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateIn , class StateOut > typename boost::disable_if< boost::is_same< StateIn , time_type > , controlled_step_result >::type try_step( System system , const StateIn &in , time_type &t , StateOut &out , time_type &dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_dxdt_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_dxdt_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); sys( in , m_dxdt.m_v , t ); return try_step( system , in , m_dxdt.m_v , t , out , dt ); } /* * Version 4 : try_step( sys , in , dxdt , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateIn , class DerivIn , class StateOut > controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt ) { unwrapped_step_adjuster &step_adjuster = m_step_adjuster; if( !step_adjuster.check_step_size_limit(dt) ) { // given dt was above step size limit - adjust and return fail; dt = step_adjuster.get_max_dt(); return fail; } m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); // do one step with error calculation m_stepper.do_step( system , in , dxdt , t , out , dt , m_xerr.m_v ); value_type max_rel_err = m_error_checker.error( m_stepper.algebra() , in , dxdt , m_xerr.m_v , dt ); if( max_rel_err > 1.0 ) { // error too big, decrease step size and reject this step dt = step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order()); return fail; } else { // otherwise, increase step size and accept t += dt; dt = step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order()); return success; } } /** * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ template< class StateType > void adjust_size( const StateType &x ) { resize_m_xerr_impl( x ); resize_m_dxdt_impl( x ); resize_m_xnew_impl( x ); m_stepper.adjust_size( x ); } /** * \brief Returns the instance of the underlying stepper. * \returns The instance of the underlying stepper. */ stepper_type& stepper( void ) { return m_stepper; } /** * \brief Returns the instance of the underlying stepper. * \returns The instance of the underlying stepper. */ const stepper_type& stepper( void ) const { return m_stepper; } private: template< class System , class StateInOut > controlled_step_result try_step_v1( System system , StateInOut &x , time_type &t , time_type &dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_dxdt_resizer.adjust_size( x , detail::bind( &controlled_runge_kutta::template resize_m_dxdt_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); sys( x , m_dxdt.m_v ,t ); return try_step( system , x , m_dxdt.m_v , t , dt ); } template< class StateIn > bool resize_m_xerr_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_xerr , x , typename is_resizeable<state_type>::type() ); } template< class StateIn > bool resize_m_dxdt_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } template< class StateIn > bool resize_m_xnew_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_xnew , x , typename is_resizeable<state_type>::type() ); } stepper_type m_stepper; error_checker_type m_error_checker; step_adjuster_type m_step_adjuster; typedef typename unwrap_reference< step_adjuster_type >::type unwrapped_step_adjuster; resizer_type m_dxdt_resizer; resizer_type m_xerr_resizer; resizer_type m_xnew_resizer; wrapped_deriv_type m_dxdt; wrapped_state_type m_xerr; wrapped_state_type m_xnew; }; /* * explicit stepper fsal version * * the class introduces the following try_step overloads * try_step( sys , x , t , dt ) * try_step( sys , in , t , out , dt ) * try_step( sys , x , dxdt , t , dt ) * try_step( sys , in , dxdt_in , t , out , dxdt_out , dt ) */ /** * \brief Implements step size control for Runge-Kutta FSAL steppers with * error estimation. * * This class implements the step size control for FSAL Runge-Kutta * steppers with error estimation. * * \tparam ErrorStepper The stepper type with error estimation, has to fulfill the ErrorStepper concept. * \tparam ErrorChecker The error checker * \tparam Resizer The resizer policy type. */ template< class ErrorStepper , class ErrorChecker , class StepAdjuster , class Resizer > class controlled_runge_kutta< ErrorStepper , ErrorChecker , StepAdjuster , Resizer , explicit_error_stepper_fsal_tag > { public: typedef ErrorStepper stepper_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::algebra_type algebra_type; typedef typename stepper_type::operations_type operations_type; typedef Resizer resizer_type; typedef ErrorChecker error_checker_type; typedef StepAdjuster step_adjuster_type; typedef explicit_controlled_stepper_fsal_tag stepper_category; #ifndef DOXYGEN_SKIP typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef controlled_runge_kutta< ErrorStepper , ErrorChecker , StepAdjuster , Resizer , explicit_error_stepper_tag > controlled_stepper_type; #endif // DOXYGEN_SKIP /** * \brief Constructs the controlled Runge-Kutta stepper. * \param error_checker An instance of the error checker. * \param stepper An instance of the underlying stepper. */ controlled_runge_kutta( const error_checker_type &error_checker = error_checker_type() , const step_adjuster_type &step_adjuster = step_adjuster_type() , const stepper_type &stepper = stepper_type() ) : m_stepper( stepper ) , m_error_checker( error_checker ) , m_step_adjuster(step_adjuster) , m_first_call( true ) { } /* * Version 1 : try_step( sys , x , t , dt ) * * The two overloads are needed in order to solve the forwarding problem */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut > controlled_step_result try_step( System system , StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t , dt ); } /** * \brief Tries to perform one step. Solves the forwarding problem and * allows for using boost range as state_type. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. Can be a boost range. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut > controlled_step_result try_step( System system , const StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t , dt ); } /* * Version 2 : try_step( sys , in , t , out , dt ); * * This version does not solve the forwarding problem, boost::range can not be used. * * The disabler is needed to solve ambiguous overloads */ /** * \brief Tries to perform one step. * * \note This method is disabled if state_type=time_type to avoid ambiguity. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateIn , class StateOut > typename boost::disable_if< boost::is_same< StateIn , time_type > , controlled_step_result >::type try_step( System system , const StateIn &in , time_type &t , StateOut &out , time_type &dt ) { if( m_dxdt_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_dxdt_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , in , t ); } return try_step( system , in , m_dxdt.m_v , t , out , dt ); } /* * Version 3 : try_step( sys , x , dxdt , t , dt ) * * This version does not solve the forwarding problem, boost::range can not be used. */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateInOut , class DerivInOut > controlled_step_result try_step( System system , StateInOut &x , DerivInOut &dxdt , time_type &t , time_type &dt ) { m_xnew_resizer.adjust_size( x , detail::bind( &controlled_runge_kutta::template resize_m_xnew_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); m_dxdt_new_resizer.adjust_size( x , detail::bind( &controlled_runge_kutta::template resize_m_dxdt_new_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); controlled_step_result res = try_step( system , x , dxdt , t , m_xnew.m_v , m_dxdtnew.m_v , dt ); if( res == success ) { boost::numeric::odeint::copy( m_xnew.m_v , x ); boost::numeric::odeint::copy( m_dxdtnew.m_v , dxdt ); } return res; } /* * Version 4 : try_step( sys , in , dxdt_in , t , out , dxdt_out , dt ) * * This version does not solve the forwarding problem, boost::range can not be used. */ /** * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ template< class System , class StateIn , class DerivIn , class StateOut , class DerivOut > controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type &t , StateOut &out , DerivOut &dxdt_out , time_type &dt ) { unwrapped_step_adjuster &step_adjuster = m_step_adjuster; if( !step_adjuster.check_step_size_limit(dt) ) { // given dt was above step size limit - adjust and return fail; dt = step_adjuster.get_max_dt(); return fail; } m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); //fsal: m_stepper.get_dxdt( dxdt ); //fsal: m_stepper.do_step( sys , x , dxdt , t , dt , m_x_err ); m_stepper.do_step( system , in , dxdt_in , t , out , dxdt_out , dt , m_xerr.m_v ); // this potentially overwrites m_x_err! (standard_error_checker does, at least) value_type max_rel_err = m_error_checker.error( m_stepper.algebra() , in , dxdt_in , m_xerr.m_v , dt ); if( max_rel_err > 1.0 ) { // error too big, decrease step size and reject this step dt = step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order()); return fail; } // otherwise, increase step size and accept t += dt; dt = step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order()); return success; } /** * \brief Resets the internal state of the underlying FSAL stepper. */ void reset( void ) { m_first_call = true; } /** * \brief Initializes the internal state storing an internal copy of the derivative. * * \param deriv The initial derivative of the ODE. */ template< class DerivIn > void initialize( const DerivIn &deriv ) { boost::numeric::odeint::copy( deriv , m_dxdt.m_v ); m_first_call = false; } /** * \brief Initializes the internal state storing an internal copy of the derivative. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The initial state of the ODE which should be solved. * \param t The initial time. */ template< class System , class StateIn > void initialize( System system , const StateIn &x , time_type t ) { typename odeint::unwrap_reference< System >::type &sys = system; sys( x , m_dxdt.m_v , t ); m_first_call = false; } /** * \brief Returns true if the stepper has been initialized, false otherwise. * * \return true, if the stepper has been initialized, false otherwise. */ bool is_initialized( void ) const { return ! m_first_call; } /** * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ template< class StateType > void adjust_size( const StateType &x ) { resize_m_xerr_impl( x ); resize_m_dxdt_impl( x ); resize_m_dxdt_new_impl( x ); resize_m_xnew_impl( x ); } /** * \brief Returns the instance of the underlying stepper. * \returns The instance of the underlying stepper. */ stepper_type& stepper( void ) { return m_stepper; } /** * \brief Returns the instance of the underlying stepper. * \returns The instance of the underlying stepper. */ const stepper_type& stepper( void ) const { return m_stepper; } private: template< class StateIn > bool resize_m_xerr_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_xerr , x , typename is_resizeable<state_type>::type() ); } template< class StateIn > bool resize_m_dxdt_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } template< class StateIn > bool resize_m_dxdt_new_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdtnew , x , typename is_resizeable<deriv_type>::type() ); } template< class StateIn > bool resize_m_xnew_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_xnew , x , typename is_resizeable<state_type>::type() ); } template< class System , class StateInOut > controlled_step_result try_step_v1( System system , StateInOut &x , time_type &t , time_type &dt ) { if( m_dxdt_resizer.adjust_size( x , detail::bind( &controlled_runge_kutta::template resize_m_dxdt_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , x , t ); } return try_step( system , x , m_dxdt.m_v , t , dt ); } stepper_type m_stepper; error_checker_type m_error_checker; step_adjuster_type m_step_adjuster; typedef typename unwrap_reference< step_adjuster_type >::type unwrapped_step_adjuster; resizer_type m_dxdt_resizer; resizer_type m_xerr_resizer; resizer_type m_xnew_resizer; resizer_type m_dxdt_new_resizer; wrapped_deriv_type m_dxdt; wrapped_state_type m_xerr; wrapped_state_type m_xnew; wrapped_deriv_type m_dxdtnew; bool m_first_call; }; /********** DOXYGEN **********/ /**** DEFAULT ERROR CHECKER ****/ /** * \class default_error_checker * \brief The default error checker to be used with Runge-Kutta error steppers * * This class provides the default mechanism to compare the error estimates * reported by Runge-Kutta error steppers with user defined error bounds. * It is used by the controlled_runge_kutta steppers. * * \tparam Value The value type. * \tparam Time The time type. * \tparam Algebra The algebra type. * \tparam Operations The operations type. */ /** * \fn default_error_checker( value_type eps_abs , value_type eps_rel , value_type a_x , value_type a_dxdt , * time_type max_dt) * \brief Constructs the error checker. * * The error is calculated as follows: ???? * * \param eps_abs Absolute tolerance level. * \param eps_rel Relative tolerance level. * \param a_x Factor for the weight of the state. * \param a_dxdt Factor for the weight of the derivative. * \param max_dt Maximum allowed step size. */ /** * \fn error( const State &x_old , const Deriv &dxdt_old , Err &x_err , time_type dt ) const * \brief Calculates the error level. * * If the returned error level is greater than 1, the estimated error was * larger than the permitted error bounds and the step should be repeated * with a smaller step size. * * \param x_old State at the beginning of the step. * \param dxdt_old Derivative at the beginning of the step. * \param x_err Error estimate. * \param dt Time step. * \return error */ /** * \fn error( algebra_type &algebra , const State &x_old , const Deriv &dxdt_old , Err &x_err , time_type dt ) const * \brief Calculates the error level using a given algebra. * * If the returned error level is greater than 1, the estimated error was * larger than the permitted error bounds and the step should be repeated * with a smaller step size. * * \param algebra The algebra used for calculation of the error. * \param x_old State at the beginning of the step. * \param dxdt_old Derivative at the beginning of the step. * \param x_err Error estimate. * \param dt Time step. * \return error */ /** * \fn time_type decrease_step(const time_type dt, const value_type error, const int error_order) * \brief Returns a decreased step size based on the given error and order * * Calculates a new smaller step size based on the given error and its order. * * \param dt The old step size. * \param error The computed error estimate. * \param error_order The error order of the stepper. * \return dt_new The new, reduced step size. */ /** * \fn time_type increase_step(const time_type dt, const value_type error, const int error_order) * \brief Returns an increased step size based on the given error and order. * * Calculates a new bigger step size based on the given error and its order. If max_dt != 0, the * new step size is limited to max_dt. * * \param dt The old step size. * \param error The computed error estimate. * \param error_order The order of the stepper. * \return dt_new The new, increased step size. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_RUNGE_KUTTA_HPP_INCLUDED odeint/stepper/adaptive_adams_bashforth_moulton.hpp 0000644 00000020167 15125237305 0017011 0 ustar 00 /* boost/numeric/odeint/stepper/detail/adaptive_adams_bashforth_moulton.hpp [begin_description] Implemetation of an adaptive adams bashforth moulton stepper. Used as the stepper for the controlled adams bashforth moulton stepper. [end_description] Copyright 2017 Valentin Noah Hartmann 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_ODEINT_STEPPER_ADAPTIVE_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ADAPTIVE_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED #include <boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp> namespace boost { namespace numeric { namespace odeint { template< size_t Steps, class State, class Value = double, class Deriv = State, class Time = Value, class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type, class Resizer = initially_resizer > class adaptive_adams_bashforth_moulton: public algebra_stepper_base< Algebra , Operations > { public: static const size_t steps = Steps; typedef unsigned short order_type; static const order_type order_value = steps; typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef typename algebra_stepper_base_type::operations_type operations_type; typedef Resizer resizer_type; typedef error_stepper_tag stepper_category; typedef detail::adaptive_adams_coefficients< Steps , Deriv , Value , Time , Algebra , Operations , Resizer > coeff_type; typedef adaptive_adams_bashforth_moulton< Steps , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type; order_type order() const { return order_value; }; order_type stepper_order() const { return order_value + 1; }; order_type error_order() const { return order_value; }; adaptive_adams_bashforth_moulton( const algebra_type &algebra = algebra_type() ) :algebra_stepper_base_type( algebra ), m_coeff(), m_dxdt_resizer(), m_xnew_resizer(), m_xerr_resizer() {}; template< class System > void do_step(System system, state_type &inOut, time_type t, time_type dt ) { m_xnew_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); do_step(system, inOut, t, m_xnew.m_v, dt, m_xerr.m_v); boost::numeric::odeint::copy( m_xnew.m_v , inOut); }; template< class System > void do_step(System system, const state_type &in, time_type t, state_type &out, time_type dt ) { do_step(system, in, t, out, dt, m_xerr.m_v); }; template< class System > void do_step(System system, state_type &inOut, time_type t, time_type dt, state_type &xerr) { m_xnew_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); do_step(system, inOut, t, m_xnew.m_v, dt, xerr); boost::numeric::odeint::copy( m_xnew.m_v , inOut); }; template< class System > void do_step(System system, const state_type &in, time_type t, state_type &out, time_type dt , state_type &xerr) { do_step_impl(system, in, t, out, dt, xerr); system(out, m_dxdt.m_v, t+dt); m_coeff.do_step(m_dxdt.m_v); m_coeff.confirm(); if(m_coeff.m_eo < order_value) { m_coeff.m_eo ++; } }; template< class ExplicitStepper, class System > void initialize(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type dt) { reset(); dt = dt/static_cast< time_type >(order_value); m_dxdt_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); system( inOut , m_dxdt.m_v , t ); for( size_t i=0 ; i<order_value; ++i ) { stepper.do_step_dxdt_impl( system, inOut, m_dxdt.m_v, t, dt ); system( inOut , m_dxdt.m_v , t + dt); m_coeff.predict(t, dt); m_coeff.do_step(m_dxdt.m_v); m_coeff.confirm(); t += dt; if(m_coeff.m_eo < order_value) { ++m_coeff.m_eo; } } }; template< class System > void initialize(System system, state_type &inOut, time_type &t, time_type dt) { reset(); dt = dt/static_cast< time_type >(order_value); for(size_t i=0; i<order_value; ++i) { this->do_step(system, inOut, t, dt); t += dt; }; }; template< class System > void do_step_impl(System system, const state_type & in, time_type t, state_type & out, time_type &dt, state_type &xerr) { size_t eO = m_coeff.m_eo; m_xerr_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_xerr_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); m_dxdt_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); m_coeff.predict(t, dt); if (m_coeff.m_steps_init == 1) { system(in, m_dxdt.m_v, t); m_coeff.do_step(m_dxdt.m_v, 1); } boost::numeric::odeint::copy( in , out ); for(size_t i=0; i<eO; ++i) { this->m_algebra.for_each3(out, out, m_coeff.phi[1][i].m_v, typename Operations::template scale_sum2<double, double>(1.0, dt*m_coeff.g[i]*m_coeff.beta[0][i])); } system(out, m_dxdt.m_v, t+dt); m_coeff.do_step(m_dxdt.m_v); this->m_algebra.for_each3(out, out, m_coeff.phi[0][eO].m_v, typename Operations::template scale_sum2<double, double>(1.0, dt*m_coeff.g[eO])); // error for current order this->m_algebra.for_each2(xerr, m_coeff.phi[0][eO].m_v, typename Operations::template scale_sum1<double>(dt*(m_coeff.g[eO]))); }; const coeff_type& coeff() const { return m_coeff; }; coeff_type & coeff() { return m_coeff; }; void reset() { m_coeff.reset(); }; const deriv_type & dxdt() const { return m_dxdt.m_v; }; private: template< class StateType > bool resize_dxdt_impl( const StateType &x ) { return adjust_size_by_resizeability( m_dxdt, x, typename is_resizeable<deriv_type>::type() ); }; template< class StateType > bool resize_xnew_impl( const StateType &x ) { return adjust_size_by_resizeability( m_xnew, x, typename is_resizeable<state_type>::type() ); }; template< class StateType > bool resize_xerr_impl( const StateType &x ) { return adjust_size_by_resizeability( m_xerr, x, typename is_resizeable<state_type>::type() ); }; coeff_type m_coeff; resizer_type m_dxdt_resizer; resizer_type m_xnew_resizer; resizer_type m_xerr_resizer; wrapped_deriv_type m_dxdt; wrapped_state_type m_xnew; wrapped_state_type m_xerr; }; } // odeint } // numeric } // boost #endif odeint/stepper/explicit_error_generic_rk.hpp 0000644 00000024724 15125237305 0015457 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/explicit_error_generic_rk.hpp [begin_description] Implementation of the generic Runge Kutta error stepper. Base class for many RK error steppers. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_EXPLICIT_ERROR_GENERIC_RK_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_EXPLICIT_ERROR_GENERIC_RK_HPP_INCLUDED #include <boost/numeric/odeint/stepper/base/explicit_error_stepper_base.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_algorithm.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_call_algebra.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_operations.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { template< size_t StageCount, size_t Order, size_t StepperOrder , size_t ErrorOrder , class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class explicit_error_generic_rk : public explicit_error_stepper_base< explicit_error_generic_rk< StageCount , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class explicit_error_generic_rk : public explicit_error_stepper_base #endif { public: #ifndef DOXYGEN_SKIP typedef explicit_error_stepper_base< explicit_error_generic_rk< StageCount , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_stepper_base< ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef explicit_error_generic_rk< StageCount , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type; #endif typedef detail::generic_rk_algorithm< StageCount , Value , Algebra , Operations > rk_algorithm_type; typedef typename rk_algorithm_type::coef_a_type coef_a_type; typedef typename rk_algorithm_type::coef_b_type coef_b_type; typedef typename rk_algorithm_type::coef_c_type coef_c_type; static const size_t stage_count = StageCount; private: public: // we use an explicit_generic_rk to do the normal rk step // and add a separate calculation of the error estimate afterwards explicit_error_generic_rk( const coef_a_type &a , const coef_b_type &b , const coef_b_type &b2 , const coef_c_type &c , const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) , m_rk_algorithm( a , b , c ) , m_b2( b2 ) { } template< class System , class StateIn , class DerivIn , class StateOut , class Err > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) { // normal step do_step_impl( system , in , dxdt , t , out , dt ); // additionally, perform the error calculation detail::template generic_rk_call_algebra< StageCount , algebra_type >()( stepper_base_type::m_algebra , xerr , dxdt , m_F , detail::generic_rk_scale_sum_err< StageCount , operations_type , value_type , time_type >( m_b2 , dt) ); } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); // actual calculation done in generic_rk.hpp m_rk_algorithm.do_step( stepper_base_type::m_algebra , system , in , dxdt , t , out , dt , m_x_tmp.m_v , m_F ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); resized |= adjust_size_by_resizeability( m_x_tmp , x , typename is_resizeable<state_type>::type() ); for( size_t i = 0 ; i < StageCount-1 ; ++i ) { resized |= adjust_size_by_resizeability( m_F[i] , x , typename is_resizeable<deriv_type>::type() ); } return resized; } rk_algorithm_type m_rk_algorithm; coef_b_type m_b2; resizer_type m_resizer; wrapped_state_type m_x_tmp; wrapped_deriv_type m_F[StageCount-1]; }; /********* DOXYGEN *********/ /** * \class explicit_error_generic_rk * \brief A generic implementation of explicit Runge-Kutta algorithms with error estimation. This class is as a * base class for all explicit Runge-Kutta steppers with error estimation. * * This class implements the explicit Runge-Kutta algorithms with error estimation in a generic way. * The Butcher tableau is passed to the stepper which constructs the stepper scheme with the help of a * template-metaprogramming algorithm. ToDo : Add example! * * This class derives explicit_error_stepper_base which provides the stepper interface. * * \tparam StageCount The number of stages of the Runge-Kutta algorithm. * \tparam Order The order of a stepper if the stepper is used without error estimation. * \tparam StepperOrder The order of a step if the stepper is used with error estimation. Usually Order and StepperOrder have * the same value. * \tparam ErrorOrder The order of the error step if the stepper is used with error estimation. * \tparam State The type representing the state of the ODE. * \tparam Value The floating point type which is used in the computations. * \tparam Time The type representing the independent variable - the time - of the ODE. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn explicit_error_generic_rk::explicit_error_generic_rk( const coef_a_type &a , const coef_b_type &b , const coef_b_type &b2 , const coef_c_type &c , const algebra_type &algebra ) * \brief Constructs the explicit_error_generik_rk class with the given parameters a, b, b2 and c. See examples section for details on the coefficients. * * \param a Triangular matrix of parameters b in the Butcher tableau. * \param b Last row of the butcher tableau. * \param b2 Parameters for lower-order evaluation to estimate the error. * \param c Parameters to calculate the time points in the Butcher tableau. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn explicit_error_generic_rk::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out-of-place, hence the input is in `in` and the output in `out`. Futhermore, an * estimation of the error is stored in `xerr`. `do_step_impl` is used by explicit_error_stepper_base. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. * \param xerr The result of the error estimation is written in xerr. */ /** * \fn explicit_error_generic_rk::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out-of-place, hence the input is in `in` and the output in `out`. * Access to this step functionality is provided by explicit_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn explicit_error_generic_rk::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_EXPLICIT_ERROR_GENERIC_RK_HPP_INCLUDED odeint/stepper/rosenbrock4_dense_output.hpp 0000644 00000012733 15125237305 0015263 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp [begin_description] Dense output for Rosenbrock 4. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2015 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_ROSENBROCK4_DENSE_OUTPUT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_DENSE_OUTPUT_HPP_INCLUDED #include <utility> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4_controller.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> namespace boost { namespace numeric { namespace odeint { template< class ControlledStepper > class rosenbrock4_dense_output { public: typedef ControlledStepper controlled_stepper_type; typedef typename unwrap_reference< controlled_stepper_type >::type unwrapped_controlled_stepper_type; typedef typename unwrapped_controlled_stepper_type::stepper_type stepper_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::state_type state_type; typedef typename stepper_type::wrapped_state_type wrapped_state_type; typedef typename stepper_type::time_type time_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_type::resizer_type resizer_type; typedef dense_output_stepper_tag stepper_category; typedef rosenbrock4_dense_output< ControlledStepper > dense_output_stepper_type; rosenbrock4_dense_output( const controlled_stepper_type &stepper = controlled_stepper_type() ) : m_stepper( stepper ) , m_x1() , m_x2() , m_current_state_x1( true ) , m_t() , m_t_old() , m_dt() { } template< class StateType > void initialize( const StateType &x0 , time_type t0 , time_type dt0 ) { m_resizer.adjust_size( x0 , detail::bind( &dense_output_stepper_type::template resize_impl< StateType > , detail::ref( *this ) , detail::_1 ) ); get_current_state() = x0; m_t = t0; m_dt = dt0; } template< class System > std::pair< time_type , time_type > do_step( System system ) { unwrapped_controlled_stepper_type &stepper = m_stepper; failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails controlled_step_result res = fail; m_t_old = m_t; do { res = stepper.try_step( system , get_current_state() , m_t , get_old_state() , m_dt ); fail_checker(); // check for overflow of failed steps } while( res == fail ); stepper.stepper().prepare_dense_output(); this->toggle_current_state(); return std::make_pair( m_t_old , m_t ); } /* * The two overloads are needed in order to solve the forwarding problem. */ template< class StateOut > void calc_state( time_type t , StateOut &x ) { unwrapped_controlled_stepper_type &stepper = m_stepper; stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t ); } template< class StateOut > void calc_state( time_type t , const StateOut &x ) { unwrapped_controlled_stepper_type &stepper = m_stepper; stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t ); } template< class StateType > void adjust_size( const StateType &x ) { unwrapped_controlled_stepper_type &stepper = m_stepper; stepper.adjust_size( x ); resize_impl( x ); } const state_type& current_state( void ) const { return get_current_state(); } time_type current_time( void ) const { return m_t; } const state_type& previous_state( void ) const { return get_old_state(); } time_type previous_time( void ) const { return m_t_old; } time_type current_time_step( void ) const { return m_dt; } private: state_type& get_current_state( void ) { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } const state_type& get_current_state( void ) const { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } state_type& get_old_state( void ) { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } const state_type& get_old_state( void ) const { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } void toggle_current_state( void ) { m_current_state_x1 = ! m_current_state_x1; } template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x2 , x , typename is_resizeable<state_type>::type() ); return resized; } controlled_stepper_type m_stepper; resizer_type m_resizer; wrapped_state_type m_x1 , m_x2; bool m_current_state_x1; time_type m_t , m_t_old , m_dt; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_ROSENBROCK4_DENSE_OUTPUT_HPP_INCLUDED odeint/stepper/extrapolation_stepper.hpp 0000644 00000025623 15125237305 0014667 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/extrapolation_stepper.hpp [begin_description] extrapolation stepper [end_description] Copyright 2009-2015 Mario Mulansky 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_ODEINT_STEPPER_EXTRAPOLATION_STEPPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_EXTRAPOLATION_STEPPER_HPP_INCLUDED #include <iostream> #include <algorithm> #include <boost/config.hpp> // for min/max guidelines #include <boost/static_assert.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/base/explicit_error_stepper_base.hpp> #include <boost/numeric/odeint/stepper/modified_midpoint.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { template < unsigned short Order, class State, class Value = double, class Deriv = State, class Time = Value, class Algebra = typename algebra_dispatcher< State >::algebra_type, class Operations = typename operations_dispatcher< State >::operations_type, class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class extrapolation_stepper : public explicit_error_stepper_base< extrapolation_stepper< Order, State, Value, Deriv, Time, Algebra, Operations, Resizer >, Order, Order, Order - 2, State, Value, Deriv, Time, Algebra, Operations, Resizer > #else class extrapolation_stepper : public explicit_error_stepper_base #endif { private: // check for Order being odd BOOST_STATIC_ASSERT_MSG( ( ( Order % 2 ) == 0 ) && ( Order > 2 ), "extrapolation_stepper requires even Order larger than 2" ); public: #ifndef DOXYGEN_SKIP typedef explicit_error_stepper_base< extrapolation_stepper< Order, State, Value, Deriv, Time, Algebra, Operations, Resizer >, Order, Order, Order - 2, State, Value, Deriv, Time, Algebra, Operations, Resizer > stepper_base_type; #else typedef explicit_error_stepper_base< extrapolation_stepper< ... >, ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef std::vector< value_type > value_vector; typedef std::vector< value_vector > value_matrix; typedef std::vector< size_t > int_vector; typedef std::vector< wrapped_state_type > state_table_type; typedef modified_midpoint< state_type, value_type, deriv_type, time_type, algebra_type, operations_type, resizer_type > midpoint_stepper_type; #endif // DOXYGEN_SKIP typedef unsigned short order_type; static const order_type order_value = stepper_base_type::order_value; static const order_type stepper_order_value = stepper_base_type::stepper_order_value; static const order_type error_order_value = stepper_base_type::error_order_value; const static size_t m_k_max = ( order_value - 2 ) / 2; extrapolation_stepper( const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ), m_interval_sequence( m_k_max + 1 ), m_coeff( m_k_max + 1 ), m_table( m_k_max ) { for ( unsigned short i = 0; i < m_k_max + 1; i++ ) { m_interval_sequence[i] = 2 * ( i + 1 ); m_coeff[i].resize( i ); for ( size_t k = 0; k < i; ++k ) { const value_type r = static_cast< value_type >( m_interval_sequence[i] ) / static_cast< value_type >( m_interval_sequence[k] ); m_coeff[i][k] = static_cast< value_type >( 1 ) / ( r * r - static_cast< value_type >( 1 ) ); // coefficients for extrapolation } } } template < class System, class StateIn, class DerivIn, class StateOut, class Err > void do_step_impl( System system, const StateIn &in, const DerivIn &dxdt, time_type t, StateOut &out, time_type dt, Err &xerr ) { // std::cout << "dt: " << dt << std::endl; // normal step do_step_impl( system, in, dxdt, t, out, dt ); static const value_type val1( 1.0 ); // additionally, perform the error calculation stepper_base_type::m_algebra.for_each3( xerr, out, m_table[0].m_v, typename operations_type::template scale_sum2< value_type, value_type >( val1, -val1 ) ); } template < class System, class StateInOut, class DerivIn, class Err > void do_step_impl_io( System system, StateInOut &inout, const DerivIn &dxdt, time_type t, time_type dt, Err &xerr ) { // normal step do_step_impl_io( system, inout, dxdt, t, dt ); static const value_type val1( 1.0 ); // additionally, perform the error calculation stepper_base_type::m_algebra.for_each3( xerr, inout, m_table[0].m_v, typename operations_type::template scale_sum2< value_type, value_type >( val1, -val1 ) ); } template < class System, class StateIn, class DerivIn, class StateOut > void do_step_impl( System system, const StateIn &in, const DerivIn &dxdt, time_type t, StateOut &out, time_type dt ) { m_resizer.adjust_size( in, detail::bind( &stepper_type::template resize_impl< StateIn >, detail::ref( *this ), detail::_1 ) ); size_t k = 0; m_midpoint.set_steps( m_interval_sequence[k] ); m_midpoint.do_step( system, in, dxdt, t, out, dt ); for ( k = 1; k <= m_k_max; ++k ) { m_midpoint.set_steps( m_interval_sequence[k] ); m_midpoint.do_step( system, in, dxdt, t, m_table[k - 1].m_v, dt ); extrapolate( k, m_table, m_coeff, out ); } } template < class System, class StateInOut, class DerivIn > void do_step_impl_io( System system, StateInOut &inout, const DerivIn &dxdt, time_type t, time_type dt ) { // special care for inout m_xout_resizer.adjust_size( inout, detail::bind( &stepper_type::template resize_m_xout< StateInOut >, detail::ref( *this ), detail::_1 ) ); do_step_impl( system, inout, dxdt, t, m_xout.m_v, dt ); boost::numeric::odeint::copy( m_xout.m_v, inout ); } template < class System, class StateInOut, class DerivIn > void do_step_dxdt_impl( System system, StateInOut &x, const DerivIn &dxdt, time_type t, time_type dt ) { do_step_impl_io( system , x , dxdt , t , dt ); } template < class System, class StateIn, class DerivIn, class StateOut > void do_step_dxdt_impl( System system, const StateIn &in, const DerivIn &dxdt, time_type t, StateOut &out, time_type dt ) { do_step_impl( system , in , dxdt , t , out , dt ); } template < class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); m_midpoint.adjust_size( x ); } private: template < class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); for ( size_t i = 0; i < m_k_max; ++i ) resized |= adjust_size_by_resizeability( m_table[i], x, typename is_resizeable< state_type >::type() ); return resized; } template < class StateIn > bool resize_m_xout( const StateIn &x ) { return adjust_size_by_resizeability( m_xout, x, typename is_resizeable< state_type >::type() ); } template < class StateInOut > void extrapolate( size_t k, state_table_type &table, const value_matrix &coeff, StateInOut &xest ) /* polynomial extrapolation, see http://www.nr.com/webnotes/nr3web21.pdf uses the obtained intermediate results to extrapolate to dt->0 */ { static const value_type val1 = static_cast< value_type >( 1.0 ); for ( int j = k - 1; j > 0; --j ) { stepper_base_type::m_algebra.for_each3( table[j - 1].m_v, table[j].m_v, table[j - 1].m_v, typename operations_type::template scale_sum2< value_type, value_type >( val1 + coeff[k][j], -coeff[k][j] ) ); } stepper_base_type::m_algebra.for_each3( xest, table[0].m_v, xest, typename operations_type::template scale_sum2< value_type, value_type >( val1 + coeff[k][0], -coeff[k][0] ) ); } private: midpoint_stepper_type m_midpoint; resizer_type m_resizer; resizer_type m_xout_resizer; int_vector m_interval_sequence; // stores the successive interval counts value_matrix m_coeff; wrapped_state_type m_xout; state_table_type m_table; // sequence of states for extrapolation }; /******** DOXYGEN *******/ /** * \class extrapolation_stepper * \brief Extrapolation stepper with configurable order, and error estimation. * * The extrapolation stepper is a stepper with error estimation and configurable * order. The order is given as template parameter and needs to be an _odd_ * number. The stepper is based on several executions of the modified midpoint * method and a Richardson extrapolation. This is essentially the same technique * as for bulirsch_stoer, but without the variable order. * * \note The Order parameter has to be an even number greater 2. */ } } } #endif odeint/stepper/symplectic_rkn_sb3a_m4_mclachlan.hpp 0000644 00000012000 15125237305 0016555 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/symplectic_rkn_sb3a_m4_mclachlan.hpp [begin_description] tba. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_M4_MCLACHLAN_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_M4_MCLACHLAN_HPP_DEFINED #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { #ifndef DOXYGEN_SKIP namespace detail { namespace symplectic_rkn_sb3a_m4_mclachlan { /* exp( a1 t A ) exp( b1 t B ) exp( a2 t A ) exp( b2 t B ) exp( a3 t A ) exp( b2 t B ) exp( a2 t A ) exp( b1 t B ) exp( a1 t A ) */ template< class Value > struct coef_a_type : public boost::array< Value , 5 > { coef_a_type( void ) { using std::sqrt; Value z = sqrt( static_cast< Value >( 7 ) / static_cast< Value >( 8 ) ) / static_cast< Value >( 3 ); (*this)[0] = static_cast< Value >( 1 ) / static_cast< Value >( 2 ) - z ; (*this)[1] = static_cast< Value >( -1 ) / static_cast< Value >( 3 ) + z ; (*this)[2] = static_cast< Value >( 2 ) / static_cast< Value >( 3 ); (*this)[3] = (*this)[1]; (*this)[4] = (*this)[0]; } }; template< class Value > struct coef_b_type : public boost::array< Value , 5 > { coef_b_type( void ) { (*this)[0] = static_cast< Value >( 1 ); (*this)[1] = static_cast< Value >( -1 ) / static_cast< Value >( 2 ); (*this)[2] = (*this)[1]; (*this)[3] = (*this)[0]; (*this)[4] = static_cast< Value >( 0 ); } }; } // namespace symplectic_rkn_sb3a_m4_mclachlan } // namespace detail #endif // DOXYGEN_SKIP template< class Coor , class Momentum = Coor , class Value = double , class CoorDeriv = Coor , class MomentumDeriv = Coor , class Time = Value , class Algebra = typename algebra_dispatcher< Coor >::algebra_type , class Operations = typename operations_dispatcher< Coor >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class symplectic_rkn_sb3a_m4_mclachlan : public symplectic_nystroem_stepper_base < 5 , 4 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > #else class symplectic_rkn_sb3a_m4_mclachlan : public symplectic_nystroem_stepper_base #endif { public: #ifndef DOXYGEN_SKIP typedef symplectic_nystroem_stepper_base < 5 , 4 , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > stepper_base_type; #endif typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::value_type value_type; symplectic_rkn_sb3a_m4_mclachlan( const algebra_type &algebra = algebra_type() ) : stepper_base_type( detail::symplectic_rkn_sb3a_m4_mclachlan::coef_a_type< value_type >() , detail::symplectic_rkn_sb3a_m4_mclachlan::coef_b_type< value_type >() , algebra ) { } }; /***************** DOXYGEN ***************/ /** * \class symplectic_rkn_sb3a_m4_mclachlan * \brief Implementation of the symmetric B3A Runge-Kutta Nystroem method of fifth order. * * The method is of fourth order and has five stages. It is described HERE. This method can be used * with multiprecision types since the coefficients are defined analytically. * * ToDo: add reference to paper. * * \tparam Order The order of the stepper. * \tparam Coor The type representing the coordinates q. * \tparam Momentum The type representing the coordinates p. * \tparam Value The basic value type. Should be something like float, double or a high-precision type. * \tparam CoorDeriv The type representing the time derivative of the coordinate dq/dt. * \tparam MomemtnumDeriv The type representing the time derivative of the momentum dp/dt. * \tparam Time The type representing the time t. * \tparam Algebra The algebra. * \tparam Operations The operations. * \tparam Resizer The resizer policy. */ /** * \fn symplectic_rkn_sb3a_m4_mclachlan::symplectic_rkn_sb3a_m4_mclachlan( const algebra_type &algebra ) * \brief Constructs the symplectic_rkn_sb3a_m4_mclachlan. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_SYMPLECTIC_RKN_SB3A_M4_MCLACHLAN_HPP_DEFINED odeint/stepper/runge_kutta_dopri5.hpp 0000644 00000051754 15125237305 0014052 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp [begin_description] Implementation of the Dormand-Prince 5(4) method. This stepper can also be used with the dense-output controlled stepper. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2013 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/same_instance.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class runge_kutta_dopri5 #ifndef DOXYGEN_SKIP : public explicit_error_stepper_fsal_base< runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else : public explicit_error_stepper_fsal_base #endif { public : #ifndef DOXYGEN_SKIP typedef explicit_error_stepper_fsal_base< runge_kutta_dopri5< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 5 , 5 , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_error_stepper_fsal_base< runge_kutta_dopri5< ... > , ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; #endif // DOXYGEN_SKIP runge_kutta_dopri5( const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) { } template< class System , class StateIn , class DerivIn , class StateOut , class DerivOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt ) { const value_type a2 = static_cast<value_type> ( 1 ) / static_cast<value_type>( 5 ); const value_type a3 = static_cast<value_type> ( 3 ) / static_cast<value_type> ( 10 ); const value_type a4 = static_cast<value_type> ( 4 ) / static_cast<value_type> ( 5 ); const value_type a5 = static_cast<value_type> ( 8 )/static_cast<value_type> ( 9 ); const value_type b21 = static_cast<value_type> ( 1 ) / static_cast<value_type> ( 5 ); const value_type b31 = static_cast<value_type> ( 3 ) / static_cast<value_type>( 40 ); const value_type b32 = static_cast<value_type> ( 9 ) / static_cast<value_type>( 40 ); const value_type b41 = static_cast<value_type> ( 44 ) / static_cast<value_type> ( 45 ); const value_type b42 = static_cast<value_type> ( -56 ) / static_cast<value_type> ( 15 ); const value_type b43 = static_cast<value_type> ( 32 ) / static_cast<value_type> ( 9 ); const value_type b51 = static_cast<value_type> ( 19372 ) / static_cast<value_type>( 6561 ); const value_type b52 = static_cast<value_type> ( -25360 ) / static_cast<value_type> ( 2187 ); const value_type b53 = static_cast<value_type> ( 64448 ) / static_cast<value_type>( 6561 ); const value_type b54 = static_cast<value_type> ( -212 ) / static_cast<value_type>( 729 ); const value_type b61 = static_cast<value_type> ( 9017 ) / static_cast<value_type>( 3168 ); const value_type b62 = static_cast<value_type> ( -355 ) / static_cast<value_type>( 33 ); const value_type b63 = static_cast<value_type> ( 46732 ) / static_cast<value_type>( 5247 ); const value_type b64 = static_cast<value_type> ( 49 ) / static_cast<value_type>( 176 ); const value_type b65 = static_cast<value_type> ( -5103 ) / static_cast<value_type>( 18656 ); const value_type c1 = static_cast<value_type> ( 35 ) / static_cast<value_type>( 384 ); const value_type c3 = static_cast<value_type> ( 500 ) / static_cast<value_type>( 1113 ); const value_type c4 = static_cast<value_type> ( 125 ) / static_cast<value_type>( 192 ); const value_type c5 = static_cast<value_type> ( -2187 ) / static_cast<value_type>( 6784 ); const value_type c6 = static_cast<value_type> ( 11 ) / static_cast<value_type>( 84 ); typename odeint::unwrap_reference< System >::type &sys = system; m_k_x_tmp_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_k_x_tmp_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); //m_x_tmp = x + dt*b21*dxdt stepper_base_type::m_algebra.for_each3( m_x_tmp.m_v , in , dxdt_in , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , dt*b21 ) ); sys( m_x_tmp.m_v , m_k2.m_v , t + dt*a2 ); // m_x_tmp = x + dt*b31*dxdt + dt*b32*m_k2 stepper_base_type::m_algebra.for_each4( m_x_tmp.m_v , in , dxdt_in , m_k2.m_v , typename operations_type::template scale_sum3< value_type , time_type , time_type >( 1.0 , dt*b31 , dt*b32 )); sys( m_x_tmp.m_v , m_k3.m_v , t + dt*a3 ); // m_x_tmp = x + dt * (b41*dxdt + b42*m_k2 + b43*m_k3) stepper_base_type::m_algebra.for_each5( m_x_tmp.m_v , in , dxdt_in , m_k2.m_v , m_k3.m_v , typename operations_type::template scale_sum4< value_type , time_type , time_type , time_type >( 1.0 , dt*b41 , dt*b42 , dt*b43 )); sys( m_x_tmp.m_v, m_k4.m_v , t + dt*a4 ); stepper_base_type::m_algebra.for_each6( m_x_tmp.m_v , in , dxdt_in , m_k2.m_v , m_k3.m_v , m_k4.m_v , typename operations_type::template scale_sum5< value_type , time_type , time_type , time_type , time_type >( 1.0 , dt*b51 , dt*b52 , dt*b53 , dt*b54 )); sys( m_x_tmp.m_v , m_k5.m_v , t + dt*a5 ); stepper_base_type::m_algebra.for_each7( m_x_tmp.m_v , in , dxdt_in , m_k2.m_v , m_k3.m_v , m_k4.m_v , m_k5.m_v , typename operations_type::template scale_sum6< value_type , time_type , time_type , time_type , time_type , time_type >( 1.0 , dt*b61 , dt*b62 , dt*b63 , dt*b64 , dt*b65 )); sys( m_x_tmp.m_v , m_k6.m_v , t + dt ); stepper_base_type::m_algebra.for_each7( out , in , dxdt_in , m_k3.m_v , m_k4.m_v , m_k5.m_v , m_k6.m_v , typename operations_type::template scale_sum6< value_type , time_type , time_type , time_type , time_type , time_type >( 1.0 , dt*c1 , dt*c3 , dt*c4 , dt*c5 , dt*c6 )); // the new derivative sys( out , dxdt_out , t + dt ); } template< class System , class StateIn , class DerivIn , class StateOut , class DerivOut , class Err > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt , Err &xerr ) { const value_type c1 = static_cast<value_type> ( 35 ) / static_cast<value_type>( 384 ); const value_type c3 = static_cast<value_type> ( 500 ) / static_cast<value_type>( 1113 ); const value_type c4 = static_cast<value_type> ( 125 ) / static_cast<value_type>( 192 ); const value_type c5 = static_cast<value_type> ( -2187 ) / static_cast<value_type>( 6784 ); const value_type c6 = static_cast<value_type> ( 11 ) / static_cast<value_type>( 84 ); const value_type dc1 = c1 - static_cast<value_type> ( 5179 ) / static_cast<value_type>( 57600 ); const value_type dc3 = c3 - static_cast<value_type> ( 7571 ) / static_cast<value_type>( 16695 ); const value_type dc4 = c4 - static_cast<value_type> ( 393 ) / static_cast<value_type>( 640 ); const value_type dc5 = c5 - static_cast<value_type> ( -92097 ) / static_cast<value_type>( 339200 ); const value_type dc6 = c6 - static_cast<value_type> ( 187 ) / static_cast<value_type>( 2100 ); const value_type dc7 = static_cast<value_type>( -1 ) / static_cast<value_type> ( 40 ); /* ToDo: copy only if &dxdt_in == &dxdt_out ? */ if( same_instance( dxdt_in , dxdt_out ) ) { m_dxdt_tmp_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_dxdt_tmp_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::copy( dxdt_in , m_dxdt_tmp.m_v ); do_step_impl( system , in , dxdt_in , t , out , dxdt_out , dt ); //error estimate stepper_base_type::m_algebra.for_each7( xerr , m_dxdt_tmp.m_v , m_k3.m_v , m_k4.m_v , m_k5.m_v , m_k6.m_v , dxdt_out , typename operations_type::template scale_sum6< time_type , time_type , time_type , time_type , time_type , time_type >( dt*dc1 , dt*dc3 , dt*dc4 , dt*dc5 , dt*dc6 , dt*dc7 ) ); } else { do_step_impl( system , in , dxdt_in , t , out , dxdt_out , dt ); //error estimate stepper_base_type::m_algebra.for_each7( xerr , dxdt_in , m_k3.m_v , m_k4.m_v , m_k5.m_v , m_k6.m_v , dxdt_out , typename operations_type::template scale_sum6< time_type , time_type , time_type , time_type , time_type , time_type >( dt*dc1 , dt*dc3 , dt*dc4 , dt*dc5 , dt*dc6 , dt*dc7 ) ); } } /* * Calculates Dense-Output for Dopri5 * * See Hairer, Norsett, Wanner: Solving Ordinary Differential Equations, Nonstiff Problems. I, p.191/192 * * y(t+theta) = y(t) + h * sum_i^7 b_i(theta) * k_i * * A = theta^2 * ( 3 - 2 theta ) * B = theta^2 * ( theta - 1 ) * C = theta^2 * ( theta - 1 )^2 * D = theta * ( theta - 1 )^2 * * b_1( theta ) = A * b_1 - C * X1( theta ) + D * b_2( theta ) = 0 * b_3( theta ) = A * b_3 + C * X3( theta ) * b_4( theta ) = A * b_4 - C * X4( theta ) * b_5( theta ) = A * b_5 + C * X5( theta ) * b_6( theta ) = A * b_6 - C * X6( theta ) * b_7( theta ) = B + C * X7( theta ) * * An alternative Method is described in: * * www-m2.ma.tum.de/homepages/simeon/numerik3/kap3.ps */ template< class StateOut , class StateIn1 , class DerivIn1 , class StateIn2 , class DerivIn2 > void calc_state( time_type t , StateOut &x , const StateIn1 &x_old , const DerivIn1 &deriv_old , time_type t_old , const StateIn2 & /* x_new */ , const DerivIn2 &deriv_new , time_type t_new ) const { const value_type b1 = static_cast<value_type> ( 35 ) / static_cast<value_type>( 384 ); const value_type b3 = static_cast<value_type> ( 500 ) / static_cast<value_type>( 1113 ); const value_type b4 = static_cast<value_type> ( 125 ) / static_cast<value_type>( 192 ); const value_type b5 = static_cast<value_type> ( -2187 ) / static_cast<value_type>( 6784 ); const value_type b6 = static_cast<value_type> ( 11 ) / static_cast<value_type>( 84 ); const time_type dt = ( t_new - t_old ); const value_type theta = ( t - t_old ) / dt; const value_type X1 = static_cast< value_type >( 5 ) * ( static_cast< value_type >( 2558722523LL ) - static_cast< value_type >( 31403016 ) * theta ) / static_cast< value_type >( 11282082432LL ); const value_type X3 = static_cast< value_type >( 100 ) * ( static_cast< value_type >( 882725551 ) - static_cast< value_type >( 15701508 ) * theta ) / static_cast< value_type >( 32700410799LL ); const value_type X4 = static_cast< value_type >( 25 ) * ( static_cast< value_type >( 443332067 ) - static_cast< value_type >( 31403016 ) * theta ) / static_cast< value_type >( 1880347072LL ) ; const value_type X5 = static_cast< value_type >( 32805 ) * ( static_cast< value_type >( 23143187 ) - static_cast< value_type >( 3489224 ) * theta ) / static_cast< value_type >( 199316789632LL ); const value_type X6 = static_cast< value_type >( 55 ) * ( static_cast< value_type >( 29972135 ) - static_cast< value_type >( 7076736 ) * theta ) / static_cast< value_type >( 822651844 ); const value_type X7 = static_cast< value_type >( 10 ) * ( static_cast< value_type >( 7414447 ) - static_cast< value_type >( 829305 ) * theta ) / static_cast< value_type >( 29380423 ); const value_type theta_m_1 = theta - static_cast< value_type >( 1 ); const value_type theta_sq = theta * theta; const value_type A = theta_sq * ( static_cast< value_type >( 3 ) - static_cast< value_type >( 2 ) * theta ); const value_type B = theta_sq * theta_m_1; const value_type C = theta_sq * theta_m_1 * theta_m_1; const value_type D = theta * theta_m_1 * theta_m_1; const value_type b1_theta = A * b1 - C * X1 + D; const value_type b3_theta = A * b3 + C * X3; const value_type b4_theta = A * b4 - C * X4; const value_type b5_theta = A * b5 + C * X5; const value_type b6_theta = A * b6 - C * X6; const value_type b7_theta = B + C * X7; // const state_type &k1 = *m_old_deriv; // const state_type &k3 = dopri5().m_k3; // const state_type &k4 = dopri5().m_k4; // const state_type &k5 = dopri5().m_k5; // const state_type &k6 = dopri5().m_k6; // const state_type &k7 = *m_current_deriv; stepper_base_type::m_algebra.for_each8( x , x_old , deriv_old , m_k3.m_v , m_k4.m_v , m_k5.m_v , m_k6.m_v , deriv_new , typename operations_type::template scale_sum7< value_type , time_type , time_type , time_type , time_type , time_type , time_type >( 1.0 , dt * b1_theta , dt * b3_theta , dt * b4_theta , dt * b5_theta , dt * b6_theta , dt * b7_theta ) ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_k_x_tmp_impl( x ); resize_dxdt_tmp_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_k_x_tmp_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x_tmp , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_k2 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k3 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k4 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k5 , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_k6 , x , typename is_resizeable<deriv_type>::type() ); return resized; } template< class StateIn > bool resize_dxdt_tmp_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt_tmp , x , typename is_resizeable<deriv_type>::type() ); } wrapped_state_type m_x_tmp; wrapped_deriv_type m_k2 , m_k3 , m_k4 , m_k5 , m_k6 ; wrapped_deriv_type m_dxdt_tmp; resizer_type m_k_x_tmp_resizer; resizer_type m_dxdt_tmp_resizer; }; /************* DOXYGEN ************/ /** * \class runge_kutta_dopri5 * \brief The Runge-Kutta Dormand-Prince 5 method. * * The Runge-Kutta Dormand-Prince 5 method is a very popular method for solving ODEs, see * <a href=""></a>. * The method is explicit and fulfills the Error Stepper concept. Step size control * is provided but continuous output is available which make this method favourable for many applications. * * This class derives from explicit_error_stepper_fsal_base and inherits its interface via CRTP (current recurring * template pattern). The method possesses the FSAL (first-same-as-last) property. See * explicit_error_stepper_fsal_base for more details. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta_dopri5::runge_kutta_dopri5( const algebra_type &algebra ) * \brief Constructs the runge_kutta_dopri5 class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn runge_kutta_dopri5::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt ) * \brief This method performs one step. The derivative `dxdt_in` of `in` at the time `t` is passed to the * method. The result is updated out-of-place, hence the input is in `in` and the output in `out`. Furthermore, * the derivative is update out-of-place, hence the input is assumed to be in `dxdt_in` and the output in * `dxdt_out`. * Access to this step functionality is provided by explicit_error_stepper_fsal_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt_in The derivative of x at t. dxdt_in is not modified by this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dxdt_out The result of the new derivative at time t+dt. * \param dt The step size. */ /** * \fn runge_kutta_dopri5::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt , Err &xerr ) * \brief This method performs one step. The derivative `dxdt_in` of `in` at the time `t` is passed to the * method. The result is updated out-of-place, hence the input is in `in` and the output in `out`. Furthermore, * the derivative is update out-of-place, hence the input is assumed to be in `dxdt_in` and the output in * `dxdt_out`. * Access to this step functionality is provided by explicit_error_stepper_fsal_base and * `do_step_impl` should not be called directly. * An estimation of the error is calculated. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt_in The derivative of x at t. dxdt_in is not modified by this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dxdt_out The result of the new derivative at time t+dt. * \param dt The step size. * \param xerr An estimation of the error. */ /** * \fn runge_kutta_dopri5::calc_state( time_type t , StateOut &x , const StateIn1 &x_old , const DerivIn1 &deriv_old , time_type t_old , const StateIn2 & , const DerivIn2 &deriv_new , time_type t_new ) const * \brief This method is used for continuous output and it calculates the state `x` at a time `t` from the * knowledge of two states `old_state` and `current_state` at time points `t_old` and `t_new`. It also uses * internal variables to calculate the result. Hence this method must be called after two successful `do_step` * calls. */ /** * \fn runge_kutta_dopri5::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA_DOPRI5_HPP_INCLUDED odeint/stepper/modified_midpoint.hpp 0000644 00000024506 15125237305 0013716 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/modified_midpoint.hpp [begin_description] Modified midpoint method for the use in Burlish-Stoer stepper. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED #include <vector> #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/copy.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class modified_midpoint : public explicit_stepper_base< modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 2 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class modified_midpoint : public explicit_stepper_base #endif { public : typedef explicit_stepper_base< modified_midpoint< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 2 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; typedef typename stepper_base_type::stepper_type stepper_type; modified_midpoint( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) , m_steps( steps ) { } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { static const value_type val1 = static_cast< value_type >( 1 ); static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 ); m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); const time_type h = dt / static_cast<value_type>( m_steps ); const time_type h2 = static_cast<value_type>(2) * h; typename odeint::unwrap_reference< System >::type &sys = system; time_type th = t + h; // m_x1 = x + h*dxdt stepper_base_type::m_algebra.for_each3( m_x1.m_v , in , dxdt , typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) ); sys( m_x1.m_v , m_dxdt.m_v , th ); boost::numeric::odeint::copy( in , m_x0.m_v ); unsigned short i = 1; while( i != m_steps ) { // general step //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp stepper_base_type::m_algebra.for_each3( m_x1.m_v , m_x0.m_v , m_dxdt.m_v , typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) ); th += h; sys( m_x1.m_v , m_dxdt.m_v , th); i++; } // last step // x = 0.5*( m_x0 + m_x1 + h*m_dxdt ) stepper_base_type::m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , m_dxdt.m_v , typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) ); } void set_steps( unsigned short steps ) { m_steps = steps; } unsigned short steps( void ) const { return m_steps; } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); return resized; } unsigned short m_steps; resizer_type m_resizer; wrapped_state_type m_x0; wrapped_state_type m_x1; wrapped_deriv_type m_dxdt; }; /* Modified midpoint which stores derivatives and state at dt/2 in some external storage for later usage in dense output calculation * This Stepper is for use in Bulirsch Stoer only. It DOES NOT meet any stepper concept. */ template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class modified_midpoint_dense_out { public : typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef modified_midpoint_dense_out< State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type; typedef std::vector< wrapped_deriv_type > deriv_table_type; modified_midpoint_dense_out( unsigned short steps = 2 , const algebra_type &algebra = algebra_type() ) : m_algebra( algebra ) , m_steps( steps ) { } /* * performs a modified midpoint step with m_steps intermediate points * stores approximation for x(t+dt/2) in x_mp and all evaluated function results in derivs * */ template< class System , class StateIn , class DerivIn , class StateOut > void do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , state_type &x_mp , deriv_table_type &derivs ) { static const value_type val1 = static_cast< value_type >( 1 ); static const value_type val05 = static_cast< value_type >( 1 ) / static_cast< value_type >( 2 ); m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize< StateIn > , detail::ref( *this ) , detail::_1 ) ); const time_type h = dt / static_cast<value_type>( m_steps ); const time_type h2 = static_cast<value_type>( 2 ) * h; typename odeint::unwrap_reference< System >::type &sys = system; time_type th = t + h; // m_x1 = x + h*dxdt m_algebra.for_each3( m_x1.m_v , in , dxdt , typename operations_type::template scale_sum2< value_type , time_type >( val1 , h ) ); if( m_steps == 2 ) // result of first step already gives approximation at the center of the interval boost::numeric::odeint::copy( m_x1.m_v , x_mp ); sys( m_x1.m_v , derivs[0].m_v , th ); boost::numeric::odeint::copy( in , m_x0.m_v ); unsigned short i = 1; while( i != m_steps ) { // general step //tmp = m_x1; m_x1 = m_x0 + h2*m_dxdt; m_x0 = tmp m_algebra.for_each3( m_x1.m_v , m_x0.m_v , derivs[i-1].m_v , typename operations_type::template scale_sum_swap2< value_type , time_type >( val1 , h2 ) ); if( i == m_steps/2-1 ) // save approximation at the center of the interval boost::numeric::odeint::copy( m_x1.m_v , x_mp ); th += h; sys( m_x1.m_v , derivs[i].m_v , th); i++; } // last step // x = 0.5*( m_x0 + m_x1 + h*m_dxdt ) m_algebra.for_each4( out , m_x0.m_v , m_x1.m_v , derivs[m_steps-1].m_v , typename operations_type::template scale_sum3< value_type , value_type , time_type >( val05 , val05 , val05*h ) ); } void set_steps( unsigned short steps ) { m_steps = steps; } unsigned short steps( void ) const { return m_steps; } template< class StateIn > bool resize( const StateIn &x ) { bool resized( false ); resized |= adjust_size_by_resizeability( m_x0 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); return resized; } template< class StateIn > void adjust_size( const StateIn &x ) { resize( x ); } private: algebra_type m_algebra; unsigned short m_steps; resizer_type m_resizer; wrapped_state_type m_x0; wrapped_state_type m_x1; }; /********** DOXYGEN ***********/ /** * \class modified_midpoint * * Implementation of the modified midpoint method with a configurable * number of intermediate steps. This class is used by the Bulirsch-Stoer * algorithm and is not meant for direct usage. */ /** * \class modified_midpoint_dense_out * * Implementation of the modified midpoint method with a configurable * number of intermediate steps. This class is used by the dense output * Bulirsch-Stoer algorithm and is not meant for direct usage. * \note This stepper is for internal use only and does not meet * any stepper concept. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_MODIFIED_MIDPOINT_HPP_INCLUDED odeint/stepper/base/explicit_error_stepper_fsal_base.hpp 0000644 00000071050 15125237305 0017734 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp [begin_description] Base class for all explicit first-same-as-last Runge Kutta steppers. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2012 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_FSAL_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_FSAL_BASE_HPP_INCLUDED #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> namespace boost { namespace numeric { namespace odeint { /* * base class for explicit stepper and error steppers with the fsal property * models the stepper AND the error stepper fsal concept * * this class provides the following do_step overloads * do_step( sys , x , t , dt ) * do_step( sys , x , dxdt , t , dt ) * do_step( sys , in , t , out , dt ) * do_step( sys , in , dxdt_in , t , out , dxdt_out , dt ) * do_step( sys , x , t , dt , xerr ) * do_step( sys , x , dxdt , t , dt , xerr ) * do_step( sys , in , t , out , dt , xerr ) * do_step( sys , in , dxdt_in , t , out , dxdt_out , dt , xerr ) */ template< class Stepper , unsigned short Order , unsigned short StepperOrder , unsigned short ErrorOrder , class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > class explicit_error_stepper_fsal_base : public algebra_stepper_base< Algebra , Operations > { public: typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Resizer resizer_type; typedef Stepper stepper_type; typedef explicit_error_stepper_fsal_tag stepper_category; #ifndef DOXYGEN_SKIP typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef explicit_error_stepper_fsal_base< Stepper , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > internal_stepper_base_type; #endif typedef unsigned short order_type; static const order_type order_value = Order; static const order_type stepper_order_value = StepperOrder; static const order_type error_order_value = ErrorOrder; explicit_error_stepper_fsal_base( const algebra_type &algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) , m_first_call( true ) { } order_type order( void ) const { return order_value; } order_type stepper_order( void ) const { return stepper_order_value; } order_type error_order( void ) const { return error_order_value; } /* * version 1 : do_step( sys , x , t , dt ) * * the two overloads are needed in order to solve the forwarding problem */ template< class System , class StateInOut > void do_step( System system , StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /* * version 2 : do_step( sys , x , dxdt , t , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateInOut , class DerivInOut > typename boost::disable_if< boost::is_same< StateInOut , time_type > , void >::type do_step( System system , StateInOut &x , DerivInOut &dxdt , time_type t , time_type dt ) { m_first_call = true; this->stepper().do_step_impl( system , x , dxdt , t , x , dxdt , dt ); } /* * named Version 2: do_step_dxdt_impl( sys , in , dxdt , t , dt ) * * this version is needed when this stepper is used for initializing * multistep stepper like adams-bashforth. Hence we provide an explicitely * named version that is not disabled. Meant for internal use only. */ template< class System , class StateInOut , class DerivInOut > void do_step_dxdt_impl( System system , StateInOut &x , DerivInOut &dxdt , time_type t , time_type dt ) { m_first_call = true; this->stepper().do_step_impl( system , x , dxdt , t , x , dxdt , dt ); } /* * version 3 : do_step( sys , in , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not * be used. * * the disable is needed to avoid ambiguous overloads if * state_type = time_type */ template< class System , class StateIn , class StateOut > typename boost::disable_if< boost::is_same< StateIn , time_type > , void >::type do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { if( m_resizer.adjust_size( in , detail::bind( &internal_stepper_base_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , in , t ); } this->stepper().do_step_impl( system , in , m_dxdt.m_v , t , out , m_dxdt.m_v , dt ); } /* * version 4 : do_step( sys , in , dxdt_in , t , out , dxdt_out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System, class StateIn, class DerivIn, class StateOut, class DerivOut > void do_step( System system, const StateIn &in, const DerivIn &dxdt_in, time_type t, StateOut &out, DerivOut &dxdt_out, time_type dt ) { m_first_call = true; this->stepper().do_step_impl( system, in, dxdt_in, t, out, dxdt_out, dt ); } /* * version 5 : do_step( sys , x , t , dt , xerr ) * * the two overloads are needed in order to solve the forwarding problem */ template< class System , class StateInOut , class Err > void do_step( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) { do_step_v5( system , x , t , dt , xerr ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut , class Err > void do_step( System system , const StateInOut &x , time_type t , time_type dt , Err &xerr ) { do_step_v5( system , x , t , dt , xerr ); } /* * version 6 : do_step( sys , x , dxdt , t , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateInOut , class DerivInOut , class Err > typename boost::disable_if< boost::is_same< StateInOut , time_type > , void >::type do_step( System system , StateInOut &x , DerivInOut &dxdt , time_type t , time_type dt , Err &xerr ) { m_first_call = true; this->stepper().do_step_impl( system , x , dxdt , t , x , dxdt , dt , xerr ); } /* * version 7 : do_step( sys , in , t , out , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class StateOut , class Err > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt , Err &xerr ) { if( m_resizer.adjust_size( in , detail::bind( &internal_stepper_base_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , in , t ); } this->stepper().do_step_impl( system , in , m_dxdt.m_v , t , out , m_dxdt.m_v , dt , xerr ); } /* * version 8 : do_step( sys , in , dxdt_in , t , out , dxdt_out , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class DerivIn , class StateOut , class DerivOut , class Err > void do_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt , Err &xerr ) { m_first_call = true; this->stepper().do_step_impl( system , in , dxdt_in , t , out , dxdt_out , dt , xerr ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); } void reset( void ) { m_first_call = true; } template< class DerivIn > void initialize( const DerivIn &deriv ) { boost::numeric::odeint::copy( deriv , m_dxdt.m_v ); m_first_call = false; } template< class System , class StateIn > void initialize( System system , const StateIn &x , time_type t ) { typename odeint::unwrap_reference< System >::type &sys = system; sys( x , m_dxdt.m_v , t ); m_first_call = false; } bool is_initialized( void ) const { return ! m_first_call; } private: template< class System , class StateInOut > void do_step_v1( System system , StateInOut &x , time_type t , time_type dt ) { if( m_resizer.adjust_size( x , detail::bind( &internal_stepper_base_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , x , t ); } this->stepper().do_step_impl( system , x , m_dxdt.m_v , t , x , m_dxdt.m_v , dt ); } template< class System , class StateInOut , class Err > void do_step_v5( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) { if( m_resizer.adjust_size( x , detail::bind( &internal_stepper_base_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ) || m_first_call ) { initialize( system , x , t ); } this->stepper().do_step_impl( system , x , m_dxdt.m_v , t , x , m_dxdt.m_v , dt , xerr ); } template< class StateIn > bool resize_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } stepper_type& stepper( void ) { return *static_cast< stepper_type* >( this ); } const stepper_type& stepper( void ) const { return *static_cast< const stepper_type* >( this ); } resizer_type m_resizer; bool m_first_call; protected: wrapped_deriv_type m_dxdt; }; /******* DOXYGEN *******/ /** * \class explicit_error_stepper_fsal_base * \brief Base class for explicit steppers with error estimation and stepper fulfilling the FSAL (first-same-as-last) * property. This class can be used with controlled steppers for step size control. * * This class serves as the base class for all explicit steppers with algebra and operations and which fulfill the FSAL * property. In contrast to explicit_stepper_base it also estimates the error and can be used in a controlled stepper * to provide step size control. * * The FSAL property means that the derivative of the system at t+dt is already used in the current step going from * t to t +dt. Therefore, some more do_steps method can be introduced and the controlled steppers can explicitly make use * of this property. * * \note This stepper provides `do_step` methods with and without error estimation. It has therefore three orders, * one for the order of a step if the error is not estimated. The other two orders are the orders of the step and * the error step if the error estimation is performed. * * explicit_error_stepper_fsal_base is used as the interface in a CRTP (currently recurring template * pattern). In order to work correctly the parent class needs to have a method * `do_step_impl( system , in , dxdt_in , t , out , dxdt_out , dt , xerr )`. * explicit_error_stepper_fsal_base derives from algebra_stepper_base. * * This class can have an intrinsic state depending on the explicit usage of the `do_step` method. This means that some * `do_step` methods are expected to be called in order. For example the `do_step( sys , x , t , dt , xerr )` will keep track * of the derivative of `x` which is the internal state. The first call of this method is recognized such that one * does not explicitly initialize the internal state, so it is safe to use this method like * * \code * stepper_type stepper; * stepper.do_step( sys , x , t , dt , xerr ); * stepper.do_step( sys , x , t , dt , xerr ); * stepper.do_step( sys , x , t , dt , xerr ); * \endcode * * But it is unsafe to call this method with different system functions after each other. Do do so, one must initialize the * internal state with the `initialize` method or reset the internal state with the `reset` method. * * explicit_error_stepper_fsal_base provides several overloaded `do_step` methods, see the list below. Only two of them are needed * to fulfill the Error Stepper concept. The other ones are for convenience and for better performance. Some of them * simply update the state out-of-place, while other expect that the first derivative at `t` is passed to the stepper. * * - `do_step( sys , x , t , dt )` - The classical `do_step` method needed to fulfill the Error Stepper concept. The * state is updated in-place. A type modelling a Boost.Range can be used for x. * - `do_step( sys , x , dxdt , t , dt )` - This method updates the state x and the derivative dxdt in-place. It is expected * that dxdt has the value of the derivative of x at time t. * - `do_step( sys , in , t , out , dt )` - This method updates the state out-of-place, hence the result of the step * is stored in `out`. * - `do_step( sys , in , dxdt_in , t , out , dxdt_out , dt )` - This method updates the state and the derivative * out-of-place. It expects that the derivative at the point `t` is explicitly passed in `dxdt_in`. * - `do_step( sys , x , t , dt , xerr )` - This `do_step` method is needed to fulfill the Error Stepper concept. The * state is updated in-place and an error estimate is calculated. A type modelling a Boost.Range can be used for x. * - `do_step( sys , x , dxdt , t , dt , xerr )` - This method updates the state and the derivative in-place. It is assumed * that the dxdt has the value of the derivative of x at time t. An error estimate is calculated. * - `do_step( sys , in , t , out , dt , xerr )` - This method updates the state out-of-place and estimates the error * during the step. * - `do_step( sys , in , dxdt_in , t , out , dxdt_out , dt , xerr )` - This methods updates the state and the derivative * out-of-place and estimates the error during the step. It is assumed the dxdt_in is derivative of in at time t. * * \note The system is always passed as value, which might result in poor performance if it contains data. In this * case it can be used with `boost::ref` or `std::ref`, for example `stepper.do_step( boost::ref( sys ) , x , t , dt );` * * \note The time `t` is not advanced by the stepper. This has to done manually, or by the appropriate `integrate` * routines or `iterator`s. * * \tparam Stepper The stepper on which this class should work. It is used via CRTP, hence explicit_stepper_base * provides the interface for the Stepper. * \tparam Order The order of a stepper if the stepper is used without error estimation. * \tparam StepperOrder The order of a step if the stepper is used with error estimation. Usually Order and StepperOrder have * the same value. * \tparam ErrorOrder The order of the error step if the stepper is used with error estimation. * \tparam State The state type for the stepper. * \tparam Value The value type for the stepper. This should be a floating point type, like float, * double, or a multiprecision type. It must not necessary be the value_type of the State. For example * the State can be a `vector< complex< double > >` in this case the Value must be double. * The default value is double. * \tparam Deriv The type representing time derivatives of the state type. It is usually the same type as the * state type, only if used with Boost.Units both types differ. * \tparam Time The type representing the time. Usually the same type as the value type. When Boost.Units is * used, this type has usually a unit. * \tparam Algebra The algebra type which must fulfill the Algebra Concept. * \tparam Operations The type for the operations which must fulfill the Operations Concept. * \tparam Resizer The resizer policy class. */ /** * \fn explicit_error_stepper_fsal_base::explicit_error_stepper_fsal_base( const algebra_type &algebra ) * \brief Constructs a explicit_stepper_fsal_base class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn explicit_error_stepper_fsal_base::order( void ) const * \return Returns the order of the stepper if it used without error estimation. */ /** * \fn explicit_error_stepper_fsal_base::stepper_order( void ) const * \return Returns the order of a step if the stepper is used without error estimation. */ /** * \fn explicit_error_stepper_fsal_base::error_order( void ) const * \return Returns the order of an error step if the stepper is used without error estimation. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * \note This method uses the internal state of the stepper. * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , StateInOut &x , DerivInOut &dxdt , time_type t , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. Additionally to the other methods * the derivative of x is also passed to this method. Therefore, dxdt must be evaluated initially: * * \code * ode( x , dxdt , t ); * for( ... ) * { * stepper.do_step( ode , x , dxdt , t , dt ); * t += dt; * } * \endcode * * \note This method does NOT use the initial state, since the first derivative is explicitly passed to this method. * * The result is updated in place in x as well as the derivative dxdt. This method is disabled if * Time and StateInOut are of the same type. In this case the method could not be distinguished from other `do_step` * versions. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param dxdt The derivative of x at t. After calling `do_step` dxdt is updated to the new value. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * This method is disabled if StateIn and Time are the same type. In this case the method can not be distinguished from * other `do_step` variants. * * \note This method uses the internal state of the stepper. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the derivative of x at t is passed to the stepper and updated by the stepper to its new value at * t+dt. * * \note This method does not solve the forwarding problem. * * \note This method does NOT use the internal state of the stepper. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt_in The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dxdt_out The updated derivative of `out` at `t+dt`. * \param dt The step size. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper and estimates the error. The state of the ODE * is updated in-place. * * * \note This method uses the internal state of the stepper. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. x is updated by this method. * \param t The value of the time, at which the step should be performed. * \param dt The step size. * \param xerr The estimation of the error is stored in xerr. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , StateInOut &x , DerivInOut &dxdt , time_type t , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. Additionally to the other method * the derivative of x is also passed to this method and updated by this method. * * \note This method does NOT use the internal state of the stepper. * * The result is updated in place in x. This method is disabled if Time and Deriv are of the same type. In this * case the method could not be distinguished from other `do_step` versions. This method is disabled if StateInOut and * Time are of the same type. * * \note This method does NOT use the internal state of the stepper. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param dxdt The derivative of x at t. After calling `do_step` this value is updated to the new value at `t+dt`. * \param t The value of the time, at which the step should be performed. * \param dt The step size. * \param xerr The error estimate is stored in xerr. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the error is estimated. * * \note This method uses the internal state of the stepper. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. * \param xerr The error estimate. */ /** * \fn explicit_error_stepper_fsal_base::do_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type t , StateOut &out , DerivOut &dxdt_out , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the derivative of x at t is passed to the stepper and the error is estimated. * * \note This method does NOT use the internal state of the stepper. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt_in The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dxdt_out The new derivative at `t+dt` is written into this variable. * \param dt The step size. * \param xerr The error estimate. */ /** * \fn explicit_error_stepper_fsal_base::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ /** * \fn explicit_error_stepper_fsal_base::reset( void ) * \brief Resets the internal state of this stepper. After calling this method it is safe to use all * `do_step` method without explicitly initializing the stepper. */ /** * \fn explicit_error_stepper_fsal_base::initialize( const DerivIn &deriv ) * \brief Initializes the internal state of the stepper. * \param deriv The derivative of x. The next call of `do_step` expects that the derivative of `x` passed to `do_step` * has the value of `deriv`. */ /** * \fn explicit_error_stepper_fsal_base::initialize( System system , const StateIn &x , time_type t ) * \brief Initializes the internal state of the stepper. * * This method is equivalent to * \code * Deriv dxdt; * system( x , dxdt , t ); * stepper.initialize( dxdt ); * \endcode * * \param system The system function for the next calls of `do_step`. * \param x The current state of the ODE. * \param t The current time of the ODE. */ /** * \fn explicit_error_stepper_fsal_base::is_initialized( void ) const * \brief Returns if the stepper is already initialized. If the stepper is not initialized, the first * call of `do_step` will initialize the state of the stepper. If the stepper is already initialized * the system function can not be safely exchanged between consecutive `do_step` calls. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_FSAL_BASE_HPP_INCLUDED odeint/stepper/base/algebra_stepper_base.hpp 0000644 00000004726 15125237305 0015300 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp [begin_description] Base class for all steppers with an algebra and operations. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_STEPPER_BASE_ALGEBRA_STEPPER_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_ALGEBRA_STEPPER_BASE_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { template< class Algebra , class Operations > class algebra_stepper_base { public: typedef Algebra algebra_type; typedef Operations operations_type; algebra_stepper_base( const algebra_type &algebra = algebra_type() ) : m_algebra( algebra ) { } algebra_type& algebra() { return m_algebra; } const algebra_type& algebra() const { return m_algebra; } protected: algebra_type m_algebra; }; /******* DOXYGEN *******/ /** * \class algebra_stepper_base * \brief Base class for all steppers with algebra and operations. * * This class serves a base class for all steppers with algebra and operations. It holds the * algebra and provides access to the algebra. The operations are not instantiated, since they are * static classes inside the operations class. * * \tparam Algebra The type of the algebra. Must fulfill the Algebra Concept, at least partially to work * with the stepper. * \tparam Operations The type of the operations. Must fulfill the Operations Concept, at least partially * to work with the stepper. */ /** * \fn algebra_stepper_base::algebra_stepper_base( const algebra_type &algebra = algebra_type() ) * \brief Constructs a algebra_stepper_base and creates the algebra. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra The algebra_stepper_base stores and uses a copy of algebra. */ /** * \fn algebra_type& algebra_stepper_base::algebra() * \return A reference to the algebra which is held by this class. */ /** * \fn const algebra_type& algebra_stepper_base::algebra() const * \return A const reference to the algebra which is held by this class. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_BASE_ALGEBRA_STEPPER_BASE_HPP_INCLUDED odeint/stepper/base/explicit_stepper_base.hpp 0000644 00000040051 15125237305 0015513 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp [begin_description] Base class for all explicit Runge Kutta steppers. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2012 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BASE_EXPLICIT_STEPPER_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_STEPPER_BASE_HPP_INCLUDED #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> namespace boost { namespace numeric { namespace odeint { /* * base class for explicit steppers * models the stepper concept * * this class provides the following overloads * do_step( sys , x , t , dt ) * do_step( sys , in , t , out , dt ) * do_step( sys , x , dxdt_in , t , dt ) * do_step( sys , in , dxdt_in , t , out , dt ) */ template< class Stepper , unsigned short Order , class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > class explicit_stepper_base : public algebra_stepper_base< Algebra , Operations > { public: #ifndef DOXYGEN_SKIP typedef explicit_stepper_base< Stepper , Order , State , Value , Deriv , Time , Algebra , Operations , Resizer > internal_stepper_base_type; #endif // DOXYGEN_SKIP typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Resizer resizer_type; typedef Stepper stepper_type; typedef stepper_tag stepper_category; typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef typename algebra_stepper_base_type::operations_type operations_type; typedef unsigned short order_type; #ifndef DOXYGEN_SKIP typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; #endif // DOXYGEN_SKIP static const order_type order_value = Order; explicit_stepper_base( const algebra_type &algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) { } /** * \return Returns the order of the stepper. */ order_type order( void ) const { return order_value; } /* * Version 1 : do_step( sys , x , t , dt ) * * the two overloads are needed in order to solve the forwarding problem */ template< class System , class StateInOut > void do_step( System system , StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /* * Version 2 : do_step( sys , x , dxdt , t , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateInOut , class DerivIn > typename boost::disable_if< boost::is_same< DerivIn , time_type > , void >::type do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt ) { this->stepper().do_step_impl( system , x , dxdt , t , x , dt ); } /* * named Version 2: do_step_dxdt_impl( sys , in , dxdt , t , dt ) * * this version is needed when this stepper is used for initializing * multistep stepper like adams-bashforth. Hence we provide an explicitely * named version that is not disabled. Meant for internal use only. */ template < class System, class StateInOut, class DerivIn > void do_step_dxdt_impl( System system, StateInOut &x, const DerivIn &dxdt, time_type t, time_type dt ) { this->stepper().do_step_impl( system , x , dxdt , t , x , dt ); } /* * Version 3 : do_step( sys , in , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( in , detail::bind( &internal_stepper_base_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); sys( in , m_dxdt.m_v ,t ); this->stepper().do_step_impl( system , in , m_dxdt.m_v , t , out , dt ); } /* * Version 4 : do_step( sys , in , dxdt , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class DerivIn , class StateOut > void do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { this->stepper().do_step_impl( system , in , dxdt , t , out , dt ); } /* * named Version 4: do_step_dxdt_impl( sys , in , dxdt , t , out, dt ) * * this version is needed when this stepper is used for initializing * multistep stepper like adams-bashforth. Hence we provide an explicitely * named version. Meant for internal use only. */ template < class System, class StateIn, class DerivIn, class StateOut > void do_step_dxdt_impl( System system, const StateIn &in, const DerivIn &dxdt, time_type t, StateOut &out, time_type dt ) { this->stepper().do_step_impl( system , in , dxdt , t , out , dt ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); } private: stepper_type& stepper( void ) { return *static_cast< stepper_type* >( this ); } const stepper_type& stepper( void ) const { return *static_cast< const stepper_type* >( this ); } template< class StateIn > bool resize_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } template< class System , class StateInOut > void do_step_v1( System system , StateInOut &x , time_type t , time_type dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( x , detail::bind( &internal_stepper_base_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) ); sys( x , m_dxdt.m_v ,t ); this->stepper().do_step_impl( system , x , m_dxdt.m_v , t , x , dt ); } resizer_type m_resizer; protected: wrapped_deriv_type m_dxdt; }; /******* DOXYGEN *********/ /** * \class explicit_stepper_base * \brief Base class for explicit steppers without step size control and without dense output. * * This class serves as the base class for all explicit steppers with algebra and operations. * Step size control and error estimation as well as dense output are not provided. explicit_stepper_base * is used as the interface in a CRTP (currently recurring template pattern). In order to work * correctly the parent class needs to have a method `do_step_impl( system , in , dxdt_in , t , out , dt )`. * This is method is used by explicit_stepper_base. explicit_stepper_base derives from * algebra_stepper_base. An example how this class can be used is * * \code * template< class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > * class custom_euler : public explicit_stepper_base< 1 , State , Value , Deriv , Time , Algebra , Operations , Resizer > * { * public: * * typedef explicit_stepper_base< 1 , State , Value , Deriv , Time , Algebra , Operations , Resizer > base_type; * * custom_euler( const Algebra &algebra = Algebra() ) { } * * template< class Sys , class StateIn , class DerivIn , class StateOut > * void do_step_impl( Sys sys , const StateIn &in , const DerivIn &dxdt , Time t , StateOut &out , Time dt ) * { * m_algebra.for_each3( out , in , dxdt , Operations::scale_sum2< Value , Time >( 1.0 , dt ); * } * * template< class State > * void adjust_size( const State &x ) * { * base_type::adjust_size( x ); * } * }; * \endcode * * For the Stepper concept only the `do_step( sys , x , t , dt )` needs to be implemented. But this class * provides additional `do_step` variants since the stepper is explicit. These methods can be used to increase * the performance in some situation, for example if one needs to analyze `dxdt` during each step. In this case * one can use * * \code * sys( x , dxdt , t ); * stepper.do_step( sys , x , dxdt , t , dt ); // the value of dxdt is used here * t += dt; * \endcode * * In detail explicit_stepper_base provides the following `do_step` variants * - `do_step( sys , x , t , dt )` - The classical `do_step` method needed to fulfill the Stepper concept. The state is updated in-place. * A type modelling a Boost.Range can be used for x. * - `do_step( sys , in , t , out , dt )` - This method updates the state out-of-place, hence the result of the step is stored in `out`. * - `do_step( sys , x , dxdt , t , dt )` - This method updates the state in-place, but the derivative at the point `t` must be * explicitly passed in `dxdt`. For an example see the code snippet above. * - `do_step( sys , in , dxdt , t , out , dt )` - This method update the state out-of-place and expects that the derivative at the point * `t` is explicitly passed in `dxdt`. It is a combination of the two `do_step` methods above. * * \note The system is always passed as value, which might result in poor performance if it contains data. In this case it can be used with `boost::ref` * or `std::ref`, for example `stepper.do_step( boost::ref( sys ) , x , t , dt );` * * \note The time `t` is not advanced by the stepper. This has to done manually, or by the appropriate `integrate` routines or `iterator`s. * * \tparam Stepper The stepper on which this class should work. It is used via CRTP, hence explicit_stepper_base * provides the interface for the Stepper. * \tparam Order The order of the stepper. * \tparam State The state type for the stepper. * \tparam Value The value type for the stepper. This should be a floating point type, like float, * double, or a multiprecision type. It must not necessary be the value_type of the State. For example * the State can be a `vector< complex< double > >` in this case the Value must be double. * The default value is double. * \tparam Deriv The type representing time derivatives of the state type. It is usually the same type as the * state type, only if used with Boost.Units both types differ. * \tparam Time The type representing the time. Usually the same type as the value type. When Boost.Units is * used, this type has usually a unit. * \tparam Algebra The algebra type which must fulfill the Algebra Concept. * \tparam Operations The type for the operations which must fulfill the Operations Concept. * \tparam Resizer The resizer policy class. */ /** * \fn explicit_stepper_base::explicit_stepper_base( const algebra_type &algebra ) * \brief Constructs a explicit_stepper_base class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn explicit_stepper_base::order_type order( void ) const * \return Returns the order of the stepper. */ /** * \fn explicit_stepper_base::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn explicit_stepper_base::do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt ) * \brief The method performs one step. Additionally to the other method * the derivative of x is also passed to this method. It is supposed to be used in the following way: * * \code * sys( x , dxdt , t ); * stepper.do_step( sys , x , dxdt , t , dt ); * \endcode * * The result is updated in place in x. This method is disabled if Time and Deriv are of the same type. In this * case the method could not be distinguished from other `do_step` versions. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn void explicit_stepper_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step. The state of the ODE is updated out-of-place. * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn void explicit_stepper_base::do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step. The state of the ODE is updated out-of-place. * Furthermore, the derivative of x at t is passed to the stepper. * It is supposed to be used in the following way: * * \code * sys( in , dxdt , t ); * stepper.do_step( sys , in , dxdt , t , out , dt ); * \endcode * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn void explicit_stepper_base::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_STEPPER_BASE_HPP_INCLUDED odeint/stepper/base/symplectic_rkn_stepper_base.hpp 0000644 00000046502 15125237305 0016727 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/base/symplectic_rkn_stepper_base.hpp [begin_description] Base class for symplectic Runge-Kutta-Nystrom steppers. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BASE_SYMPLECTIC_RKN_STEPPER_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_SYMPLECTIC_RKN_STEPPER_BASE_HPP_INCLUDED #include <boost/array.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/is_pair.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> namespace boost { namespace numeric { namespace odeint { template< size_t NumOfStages , unsigned short Order , class Coor , class Momentum , class Value , class CoorDeriv , class MomentumDeriv , class Time , class Algebra , class Operations , class Resizer > class symplectic_nystroem_stepper_base : public algebra_stepper_base< Algebra , Operations > { public: typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef typename algebra_stepper_base_type::operations_type operations_type; const static size_t num_of_stages = NumOfStages; typedef Coor coor_type; typedef Momentum momentum_type; typedef std::pair< coor_type , momentum_type > state_type; typedef CoorDeriv coor_deriv_type; typedef state_wrapper< coor_deriv_type> wrapped_coor_deriv_type; typedef MomentumDeriv momentum_deriv_type; typedef state_wrapper< momentum_deriv_type > wrapped_momentum_deriv_type; typedef std::pair< coor_deriv_type , momentum_deriv_type > deriv_type; typedef Value value_type; typedef Time time_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; #ifndef DOXYGEN_SKIP typedef symplectic_nystroem_stepper_base< NumOfStages , Order , Coor , Momentum , Value , CoorDeriv , MomentumDeriv , Time , Algebra , Operations , Resizer > internal_stepper_base_type; #endif typedef unsigned short order_type; static const order_type order_value = Order; typedef boost::array< value_type , num_of_stages > coef_type; symplectic_nystroem_stepper_base( const coef_type &coef_a , const coef_type &coef_b , const algebra_type &algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) , m_coef_a( coef_a ) , m_coef_b( coef_b ) , m_dqdt_resizer() , m_dpdt_resizer() , m_dqdt() , m_dpdt() { } order_type order( void ) const { return order_value; } /* * Version 1 : do_step( system , x , t , dt ) * * This version does not solve the forwarding problem, boost.range can not be used. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &state , time_type t , time_type dt ) { typedef typename odeint::unwrap_reference< System >::type system_type; do_step_impl( system , state , t , state , dt , typename is_pair< system_type >::type() ); } /** * \brief Same function as above. It differs only in a different const specifier in order * to solve the forwarding problem, can be used with Boost.Range. */ template< class System , class StateInOut > void do_step( System system , StateInOut &state , time_type t , time_type dt ) { typedef typename odeint::unwrap_reference< System >::type system_type; do_step_impl( system , state , t , state , dt , typename is_pair< system_type >::type() ); } /* * Version 2 : do_step( system , q , p , t , dt ); * * For Convenience * * The two overloads are needed in order to solve the forwarding problem. */ template< class System , class CoorInOut , class MomentumInOut > void do_step( System system , CoorInOut &q , MomentumInOut &p , time_type t , time_type dt ) { do_step( system , std::make_pair( detail::ref( q ) , detail::ref( p ) ) , t , dt ); } /** * \brief Same function as do_step( system , q , p , t , dt ). It differs only in a different const specifier in order * to solve the forwarding problem, can be called with Boost.Range. */ template< class System , class CoorInOut , class MomentumInOut > void do_step( System system , const CoorInOut &q , const MomentumInOut &p , time_type t , time_type dt ) { do_step( system , std::make_pair( detail::ref( q ) , detail::ref( p ) ) , t , dt ); } /* * Version 3 : do_step( system , in , t , out , dt ) * * The forwarding problem is not solved in this version */ template< class System , class StateIn , class StateOut > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { typedef typename odeint::unwrap_reference< System >::type system_type; do_step_impl( system , in , t , out , dt , typename is_pair< system_type >::type() ); } template< class StateType > void adjust_size( const StateType &x ) { resize_dqdt( x ); resize_dpdt( x ); } /** \brief Returns the coefficients a. */ const coef_type& coef_a( void ) const { return m_coef_a; } /** \brief Returns the coefficients b. */ const coef_type& coef_b( void ) const { return m_coef_b; } private: // stepper for systems with function for dq/dt = f(p) and dp/dt = -f(q) template< class System , class StateIn , class StateOut > void do_step_impl( System system , const StateIn &in , time_type /* t */ , StateOut &out , time_type dt , boost::mpl::true_ ) { typedef typename odeint::unwrap_reference< System >::type system_type; typedef typename odeint::unwrap_reference< typename system_type::first_type >::type coor_deriv_func_type; typedef typename odeint::unwrap_reference< typename system_type::second_type >::type momentum_deriv_func_type; system_type &sys = system; coor_deriv_func_type &coor_func = sys.first; momentum_deriv_func_type &momentum_func = sys.second; typedef typename odeint::unwrap_reference< StateIn >::type state_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type; const state_in_type &state_in = in; const coor_in_type &coor_in = state_in.first; const momentum_in_type &momentum_in = state_in.second; typedef typename odeint::unwrap_reference< StateOut >::type state_out_type; typedef typename odeint::unwrap_reference< typename state_out_type::first_type >::type coor_out_type; typedef typename odeint::unwrap_reference< typename state_out_type::second_type >::type momentum_out_type; state_out_type &state_out = out; coor_out_type &coor_out = state_out.first; momentum_out_type &momentum_out = state_out.second; m_dqdt_resizer.adjust_size( coor_in , detail::bind( &internal_stepper_base_type::template resize_dqdt< coor_in_type > , detail::ref( *this ) , detail::_1 ) ); m_dpdt_resizer.adjust_size( momentum_in , detail::bind( &internal_stepper_base_type::template resize_dpdt< momentum_in_type > , detail::ref( *this ) , detail::_1 ) ); // ToDo: check sizes? for( size_t l=0 ; l<num_of_stages ; ++l ) { if( l == 0 ) { coor_func( momentum_in , m_dqdt.m_v ); this->m_algebra.for_each3( coor_out , coor_in , m_dqdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) ); momentum_func( coor_out , m_dpdt.m_v ); this->m_algebra.for_each3( momentum_out , momentum_in , m_dpdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) ); } else { coor_func( momentum_out , m_dqdt.m_v ); this->m_algebra.for_each3( coor_out , coor_out , m_dqdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) ); momentum_func( coor_out , m_dpdt.m_v ); this->m_algebra.for_each3( momentum_out , momentum_out , m_dpdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) ); } } } // stepper for systems with only function dp /dt = -f(q), dq/dt = p, time not required but still expected for compatibility reasons template< class System , class StateIn , class StateOut > void do_step_impl( System system , const StateIn &in , time_type /* t */ , StateOut &out , time_type dt , boost::mpl::false_ ) { typedef typename odeint::unwrap_reference< System >::type momentum_deriv_func_type; momentum_deriv_func_type &momentum_func = system; typedef typename odeint::unwrap_reference< StateIn >::type state_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::first_type >::type coor_in_type; typedef typename odeint::unwrap_reference< typename state_in_type::second_type >::type momentum_in_type; const state_in_type &state_in = in; const coor_in_type &coor_in = state_in.first; const momentum_in_type &momentum_in = state_in.second; typedef typename odeint::unwrap_reference< StateOut >::type state_out_type; typedef typename odeint::unwrap_reference< typename state_out_type::first_type >::type coor_out_type; typedef typename odeint::unwrap_reference< typename state_out_type::second_type >::type momentum_out_type; state_out_type &state_out = out; coor_out_type &coor_out = state_out.first; momentum_out_type &momentum_out = state_out.second; // m_dqdt not required when called with momentum_func only - don't resize // m_dqdt_resizer.adjust_size( coor_in , detail::bind( &internal_stepper_base_type::template resize_dqdt< coor_in_type > , detail::ref( *this ) , detail::_1 ) ); m_dpdt_resizer.adjust_size( momentum_in , detail::bind( &internal_stepper_base_type::template resize_dpdt< momentum_in_type > , detail::ref( *this ) , detail::_1 ) ); // ToDo: check sizes? // step 0 this->m_algebra.for_each3( coor_out , coor_in , momentum_in , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[0] * dt ) ); momentum_func( coor_out , m_dpdt.m_v ); this->m_algebra.for_each3( momentum_out , momentum_in , m_dpdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[0] * dt ) ); for( size_t l=1 ; l<num_of_stages ; ++l ) { this->m_algebra.for_each3( coor_out , coor_out , momentum_out , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_a[l] * dt ) ); momentum_func( coor_out , m_dpdt.m_v ); this->m_algebra.for_each3( momentum_out , momentum_out , m_dpdt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( 1.0 , m_coef_b[l] * dt ) ); } } template< class StateIn > bool resize_dqdt( const StateIn &x ) { return adjust_size_by_resizeability( m_dqdt , x , typename is_resizeable<coor_deriv_type>::type() ); } template< class StateIn > bool resize_dpdt( const StateIn &x ) { return adjust_size_by_resizeability( m_dpdt , x , typename is_resizeable<momentum_deriv_type>::type() ); } const coef_type m_coef_a; const coef_type m_coef_b; resizer_type m_dqdt_resizer; resizer_type m_dpdt_resizer; wrapped_coor_deriv_type m_dqdt; wrapped_momentum_deriv_type m_dpdt; }; /********* DOXYGEN *********/ /** * \class symplectic_nystroem_stepper_base * \brief Base class for all symplectic steppers of Nystroem type. * * This class is the base class for the symplectic Runge-Kutta-Nystroem steppers. Symplectic steppers are usually * used to solve Hamiltonian systems and they conserve the phase space volume, see * <a href="http://en.wikipedia.org/wiki/Symplectic_integrator">en.wikipedia.org/wiki/Symplectic_integrator</a>. * Furthermore, the energy is conserved * in average. In detail this class of steppers can be used to solve separable Hamiltonian systems which can be written * in the form H(q,p) = H1(p) + H2(q). q is usually called the coordinate, while p is the momentum. The equations of motion * are dq/dt = dH1/dp, dp/dt = -dH2/dq. * * ToDo : add formula for solver and explanation of the coefficients * * symplectic_nystroem_stepper_base uses odeints algebra and operation system. Step size and error estimation are not * provided for this class of solvers. It derives from algebra_stepper_base. Several `do_step` variants are provided: * * - `do_step( sys , x , t , dt )` - The classical `do_step` method. The sys can be either a pair of function objects * for the coordinate or the momentum part or one function object for the momentum part. `x` is a pair of coordinate * and momentum. The state is updated in-place. * - `do_step( sys , q , p , t , dt )` - This method is similar to the method above with the difference that the coordinate * and the momentum are passed explicitly and not packed into a pair. * - `do_step( sys , x_in , t , x_out , dt )` - This method transforms the state out-of-place. `x_in` and `x_out` are here pairs * of coordinate and momentum. * * \tparam NumOfStages Number of stages. * \tparam Order The order of the stepper. * \tparam Coor The type representing the coordinates q. * \tparam Momentum The type representing the coordinates p. * \tparam Value The basic value type. Should be something like float, double or a high-precision type. * \tparam CoorDeriv The type representing the time derivative of the coordinate dq/dt. * \tparam MomemtnumDeriv The type representing the time derivative of the momentum dp/dt. * \tparam Time The type representing the time t. * \tparam Algebra The algebra. * \tparam Operations The operations. * \tparam Resizer The resizer policy. */ /** * \fn symplectic_nystroem_stepper_base::symplectic_nystroem_stepper_base( const coef_type &coef_a , const coef_type &coef_b , const algebra_type &algebra ) * \brief Constructs a symplectic_nystroem_stepper_base class. The parameters of the specific Nystroem method and the * algebra have to be passed. * \param coef_a The coefficients a. * \param coef_b The coefficients b. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn symplectic_nystroem_stepper_base::order( void ) const * \return Returns the order of the stepper. */ /** * \fn symplectic_nystroem_stepper_base::do_step( System system , const StateInOut &state , time_type t , time_type dt ) * \brief This method performs one step. The system can be either a pair of two function object * describing the momentum part and the coordinate part or one function object describing only * the momentum part. In this case the coordinate is assumed to be trivial dq/dt = p. The state * is updated in-place. * * \note boost::ref or std::ref can be used for the system as well as for the state. So, it is correct * to write `stepper.do_step( make_pair( std::ref( fq ) , std::ref( fp ) ) , make_pair( std::ref( q ) , std::ref( p ) ) , t , dt )`. * * \note This method solves the forwarding problem. * * \param system The system, can be represented as a pair of two function object or one function object. See above. * \param state The state of the ODE. It is a pair of Coor and Momentum. The state is updated in-place, therefore, the * new value of the state will be written into this variable. * \param t The time of the ODE. It is not advanced by this method. * \param dt The time step. */ /** * \fn symplectic_nystroem_stepper_base::do_step( System system , CoorInOut &q , MomentumInOut &p , time_type t , time_type dt ) * \brief This method performs one step. The system can be either a pair of two function object * describing the momentum part and the coordinate part or one function object describing only * the momentum part. In this case the coordinate is assumed to be trivial dq/dt = p. The state * is updated in-place. * * \note boost::ref or std::ref can be used for the system. So, it is correct * to write `stepper.do_step( make_pair( std::ref( fq ) , std::ref( fp ) ) , q , p , t , dt )`. * * \note This method solves the forwarding problem. * * \param system The system, can be represented as a pair of two function object or one function object. See above. * \param q The coordinate of the ODE. It is updated in-place. Therefore, the new value of the coordinate will be written * into this variable. * \param p The momentum of the ODE. It is updated in-place. Therefore, the new value of the momentum will be written info * this variable. * \param t The time of the ODE. It is not advanced by this method. * \param dt The time step. */ /** * \fn symplectic_nystroem_stepper_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The system can be either a pair of two function object * describing the momentum part and the coordinate part or one function object describing only * the momentum part. In this case the coordinate is assumed to be trivial dq/dt = p. The state * is updated out-of-place. * * \note boost::ref or std::ref can be used for the system. So, it is correct * to write `stepper.do_step( make_pair( std::ref( fq ) , std::ref( fp ) ) , x_in , t , x_out , dt )`. * * \note This method NOT solve the forwarding problem. * * \param system The system, can be represented as a pair of two function object or one function object. See above. * \param in The state of the ODE, which is a pair of coordinate and momentum. The state is updated out-of-place, therefore the * new value is written into out * \param t The time of the ODE. It is not advanced by this method. * \param out The new state of the ODE. * \param dt The time step. */ /** * \fn symplectic_nystroem_stepper_base::adjust_size( const StateType &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_BASE_SYMPLECTIC_RKN_STEPPER_BASE_HPP_INCLUDED odeint/stepper/base/explicit_error_stepper_base.hpp 0000644 00000061514 15125237305 0016733 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/base/explicit_error_stepper_base.hpp [begin_description] Base class for all explicit Runge Kutta stepper which are also error steppers. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2012 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_BASE_HPP_INCLUDED #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp> namespace boost { namespace numeric { namespace odeint { /* * base class for explicit stepper and error steppers * models the stepper AND the error stepper concept * * this class provides the following do_step variants: * do_step( sys , x , t , dt ) * do_step( sys , x , dxdt , t , dt ) * do_step( sys , in , t , out , dt ) * do_step( sys , in , dxdt , t , out , dt ) * do_step( sys , x , t , dt , xerr ) * do_step( sys , x , dxdt , t , dt , xerr ) * do_step( sys , in , t , out , dt , xerr ) * do_step( sys , in , dxdt , t , out , dt , xerr ) */ template< class Stepper , unsigned short Order , unsigned short StepperOrder , unsigned short ErrorOrder , class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > class explicit_error_stepper_base : public algebra_stepper_base< Algebra , Operations > { public: typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type; typedef typename algebra_stepper_base_type::algebra_type algebra_type; typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Resizer resizer_type; typedef Stepper stepper_type; typedef explicit_error_stepper_tag stepper_category; #ifndef DOXYGEN_SKIP typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef explicit_error_stepper_base< Stepper , Order , StepperOrder , ErrorOrder , State , Value , Deriv , Time , Algebra , Operations , Resizer > internal_stepper_base_type; #endif typedef unsigned short order_type; static const order_type order_value = Order; static const order_type stepper_order_value = StepperOrder; static const order_type error_order_value = ErrorOrder; explicit_error_stepper_base( const algebra_type &algebra = algebra_type() ) : algebra_stepper_base_type( algebra ) { } order_type order( void ) const { return order_value; } order_type stepper_order( void ) const { return stepper_order_value; } order_type error_order( void ) const { return error_order_value; } /* * Version 1 : do_step( sys , x , t , dt ) * * the two overloads are needed in order to solve the forwarding problem */ template< class System , class StateInOut > void do_step( System system , StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut > void do_step( System system , const StateInOut &x , time_type t , time_type dt ) { do_step_v1( system , x , t , dt ); } /* * Version 2 : do_step( sys , x , dxdt , t , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateInOut , class DerivIn > typename boost::disable_if< boost::is_same< DerivIn , time_type > , void >::type do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt ) { this->stepper().do_step_impl( system , x , dxdt , t , x , dt ); } /* * named Version 2: do_step_dxdt_impl( sys , in , dxdt , t , dt ) * * this version is needed when this stepper is used for initializing * multistep stepper like adams-bashforth. Hence we provide an explicitely * named version that is not disabled. Meant for internal use only. */ template < class System, class StateInOut, class DerivIn > void do_step_dxdt_impl( System system, StateInOut &x, const DerivIn &dxdt, time_type t, time_type dt ) { this->stepper().do_step_impl( system , x , dxdt , t , x , dt ); } /* * Version 3 : do_step( sys , in , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateIn , class StateOut > typename boost::disable_if< boost::is_same< StateIn , time_type > , void >::type do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( in , detail::bind( &internal_stepper_base_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); sys( in , m_dxdt.m_v ,t ); this->stepper().do_step_impl( system , in , m_dxdt.m_v , t , out , dt ); } /* * Version 4 :do_step( sys , in , dxdt , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateIn , class DerivIn , class StateOut > typename boost::disable_if< boost::is_same< DerivIn , time_type > , void >::type do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { this->stepper().do_step_impl( system , in , dxdt , t , out , dt ); } /* * named Version 4: do_step_dxdt_impl( sys , in , dxdt , t , out, dt ) * * this version is needed when this stepper is used for initializing * multistep stepper like adams-bashforth. Hence we provide an explicitely * named version that is not disabled. Meant for internal use only. */ template < class System, class StateIn, class DerivIn, class StateOut > void do_step_dxdt_impl( System system, const StateIn &in, const DerivIn &dxdt, time_type t, StateOut &out, time_type dt ) { this->stepper().do_step_impl( system , in , dxdt , t , out , dt ); } /* * Version 5 :do_step( sys , x , t , dt , xerr ) * * the two overloads are needed in order to solve the forwarding problem */ template< class System , class StateInOut , class Err > void do_step( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) { do_step_v5( system , x , t , dt , xerr ); } /** * \brief Second version to solve the forwarding problem, can be called with Boost.Range as StateInOut. */ template< class System , class StateInOut , class Err > void do_step( System system , const StateInOut &x , time_type t , time_type dt , Err &xerr ) { do_step_v5( system , x , t , dt , xerr ); } /* * Version 6 :do_step( sys , x , dxdt , t , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used * * the disable is needed to avoid ambiguous overloads if state_type = time_type */ template< class System , class StateInOut , class DerivIn , class Err > typename boost::disable_if< boost::is_same< DerivIn , time_type > , void >::type do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt , Err &xerr ) { this->stepper().do_step_impl( system , x , dxdt , t , x , dt , xerr ); } /* * Version 7 : do_step( sys , in , t , out , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class StateOut , class Err > void do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt , Err &xerr ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( in , detail::bind( &internal_stepper_base_type::template resize_impl<StateIn> , detail::ref( *this ) , detail::_1 ) ); sys( in , m_dxdt.m_v ,t ); this->stepper().do_step_impl( system , in , m_dxdt.m_v , t , out , dt , xerr ); } /* * Version 8 : do_step( sys , in , dxdt , t , out , dt , xerr ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class DerivIn , class StateOut , class Err > void do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) { this->stepper().do_step_impl( system , in , dxdt , t , out , dt , xerr ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); } private: template< class System , class StateInOut > void do_step_v1( System system , StateInOut &x , time_type t , time_type dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( x , detail::bind( &internal_stepper_base_type::template resize_impl<StateInOut> , detail::ref( *this ) , detail::_1 ) ); sys( x , m_dxdt.m_v , t ); this->stepper().do_step_impl( system , x , m_dxdt.m_v , t , x , dt ); } template< class System , class StateInOut , class Err > void do_step_v5( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) { typename odeint::unwrap_reference< System >::type &sys = system; m_resizer.adjust_size( x , detail::bind( &internal_stepper_base_type::template resize_impl<StateInOut> , detail::ref( *this ) , detail::_1 ) ); sys( x , m_dxdt.m_v ,t ); this->stepper().do_step_impl( system , x , m_dxdt.m_v , t , x , dt , xerr ); } template< class StateIn > bool resize_impl( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } stepper_type& stepper( void ) { return *static_cast< stepper_type* >( this ); } const stepper_type& stepper( void ) const { return *static_cast< const stepper_type* >( this ); } resizer_type m_resizer; protected: wrapped_deriv_type m_dxdt; }; /******** DOXYGEN *******/ /** * \class explicit_error_stepper_base * \brief Base class for explicit steppers with error estimation. This class can used with * controlled steppers for step size control. * * This class serves as the base class for all explicit steppers with algebra and operations. In contrast to * explicit_stepper_base it also estimates the error and can be used in a controlled stepper to provide * step size control. * * \note This stepper provides `do_step` methods with and without error estimation. It has therefore three orders, * one for the order of a step if the error is not estimated. The other two orders are the orders of the step and * the error step if the error estimation is performed. * * explicit_error_stepper_base is used as the interface in a CRTP (currently recurring template * pattern). In order to work correctly the parent class needs to have a method * `do_step_impl( system , in , dxdt_in , t , out , dt , xerr )`. * explicit_error_stepper_base derives from algebra_stepper_base. * * explicit_error_stepper_base provides several overloaded `do_step` methods, see the list below. Only two of them * are needed to fulfill the Error Stepper concept. The other ones are for convenience and for performance. Some * of them simply update the state out-of-place, while other expect that the first derivative at `t` is passed to the * stepper. * * - `do_step( sys , x , t , dt )` - The classical `do_step` method needed to fulfill the Error Stepper concept. The * state is updated in-place. A type modelling a Boost.Range can be used for x. * - `do_step( sys , x , dxdt , t , dt )` - This method updates the state in-place, but the derivative at the point `t` * must be explicitly passed in `dxdt`. * - `do_step( sys , in , t , out , dt )` - This method updates the state out-of-place, hence the result of the step * is stored in `out`. * - `do_step( sys , in , dxdt , t , out , dt )` - This method update the state out-of-place and expects that the * derivative at the point `t` is explicitly passed in `dxdt`. It is a combination of the two `do_step` methods * above. * - `do_step( sys , x , t , dt , xerr )` - This `do_step` method is needed to fulfill the Error Stepper concept. The * state is updated in-place and an error estimate is calculated. A type modelling a Boost.Range can be used for x. * - `do_step( sys , x , dxdt , t , dt , xerr )` - This method updates the state in-place, but the derivative at the * point `t` must be passed in `dxdt`. An error estimate is calculated. * - `do_step( sys , in , t , out , dt , xerr )` - This method updates the state out-of-place and estimates the error * during the step. * - `do_step( sys , in , dxdt , t , out , dt , xerr )` - This methods updates the state out-of-place and estimates * the error during the step. Furthermore, the derivative at `t` must be passed in `dxdt`. * * \note The system is always passed as value, which might result in poor performance if it contains data. In this * case it can be used with `boost::ref` or `std::ref`, for example `stepper.do_step( boost::ref( sys ) , x , t , dt );` * * \note The time `t` is not advanced by the stepper. This has to done manually, or by the appropriate `integrate` * routines or `iterator`s. * * \tparam Stepper The stepper on which this class should work. It is used via CRTP, hence explicit_stepper_base * provides the interface for the Stepper. * \tparam Order The order of a stepper if the stepper is used without error estimation. * \tparam StepperOrder The order of a step if the stepper is used with error estimation. Usually Order and StepperOrder have * the same value. * \tparam ErrorOrder The order of the error step if the stepper is used with error estimation. * \tparam State The state type for the stepper. * \tparam Value The value type for the stepper. This should be a floating point type, like float, * double, or a multiprecision type. It must not necessary be the value_type of the State. For example * the State can be a `vector< complex< double > >` in this case the Value must be double. * The default value is double. * \tparam Deriv The type representing time derivatives of the state type. It is usually the same type as the * state type, only if used with Boost.Units both types differ. * \tparam Time The type representing the time. Usually the same type as the value type. When Boost.Units is * used, this type has usually a unit. * \tparam Algebra The algebra type which must fulfill the Algebra Concept. * \tparam Operations The type for the operations which must fulfill the Operations Concept. * \tparam Resizer The resizer policy class. */ /** * \fn explicit_error_stepper_base::explicit_error_stepper_base( const algebra_type &algebra = algebra_type() ) * * \brief Constructs a explicit_error_stepper_base class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn explicit_error_stepper_base::order( void ) const * \return Returns the order of the stepper if it used without error estimation. */ /** * \fn explicit_error_stepper_base::stepper_order( void ) const * \return Returns the order of a step if the stepper is used without error estimation. */ /** * \fn explicit_error_stepper_base::error_order( void ) const * \return Returns the order of an error step if the stepper is used without error estimation. */ /** * \fn explicit_error_stepper_base::do_step( System system , StateInOut &x , time_type t , time_type dt ) * \brief This method performs one step. It transforms the result in-place. * * \param system The system function to solve, hence the r.h.s. of the ordinary differential equation. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn explicit_error_stepper_base::do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. Additionally to the other method * the derivative of x is also passed to this method. It is supposed to be used in the following way: * * \code * sys( x , dxdt , t ); * stepper.do_step( sys , x , dxdt , t , dt ); * \endcode * * The result is updated in place in x. This method is disabled if Time and Deriv are of the same type. In this * case the method could not be distinguished from other `do_step` versions. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param dt The step size. */ /** * \fn explicit_error_stepper_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * This method is disabled if StateIn and Time are the same type. In this case the method can not be distinguished from * other `do_step` variants. * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn explicit_error_stepper_base::do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the derivative of x at t is passed to the stepper. It is supposed to be used in the following way: * * \code * sys( in , dxdt , t ); * stepper.do_step( sys , in , dxdt , t , out , dt ); * \endcode * * This method is disabled if DerivIn and Time are of same type. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn explicit_error_stepper_base::do_step( System system , StateInOut &x , time_type t , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper and estimates the error. The state of the ODE * is updated in-place. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. x is updated by this method. * \param t The value of the time, at which the step should be performed. * \param dt The step size. * \param xerr The estimation of the error is stored in xerr. */ /** * \fn explicit_error_stepper_base::do_step( System system , StateInOut &x , const DerivIn &dxdt , time_type t , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. Additionally to the other method * the derivative of x is also passed to this method. It is supposed to be used in the following way: * * \code * sys( x , dxdt , t ); * stepper.do_step( sys , x , dxdt , t , dt , xerr ); * \endcode * * The result is updated in place in x. This method is disabled if Time and DerivIn are of the same type. In this * case the method could not be distinguished from other `do_step` versions. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param x The state of the ODE which should be solved. After calling do_step the result is updated in x. * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param dt The step size. * \param xerr The error estimate is stored in xerr. */ /** * \fn explicit_error_stepper_base::do_step( System system , const StateIn &in , time_type t , StateOut &out , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the error is estimated. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. * \param xerr The error estimate. */ /** * \fn explicit_error_stepper_base::do_step( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt , Err &xerr ) * \brief The method performs one step with the stepper passed by Stepper. The state of the ODE is updated out-of-place. * Furthermore, the derivative of x at t is passed to the stepper and the error is estimated. It is supposed to be used in the following way: * * \code * sys( in , dxdt , t ); * stepper.do_step( sys , in , dxdt , t , out , dt ); * \endcode * * This method is disabled if DerivIn and Time are of same type. * * \note This method does not solve the forwarding problem. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. * \param xerr The error estimate. */ /** * \fn explicit_error_stepper_base::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_BASE_EXPLICIT_ERROR_STEPPER_BASE_HPP_INCLUDED odeint/stepper/explicit_generic_rk.hpp 0000644 00000020453 15125237305 0014241 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/explicit_generic_rk.hpp [begin_description] Implementation of the generic Runge-Kutta steppers. This is the base class for many Runge-Kutta steppers. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_EXPLICIT_GENERIC_RK_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_EXPLICIT_GENERIC_RK_HPP_INCLUDED #include <boost/array.hpp> #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/stepper/detail/generic_rk_algorithm.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { //forward declarations #ifndef DOXYGEN_SKIP template< size_t StageCount, size_t Order, class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class explicit_generic_rk; struct stage_vector; template< class T , class Constant > struct array_wrapper { typedef const typename boost::array< T , Constant::value > type; }; template< class T , size_t i > struct stage { T c; boost::array< T , i > a; }; template< class T , class Constant > struct stage_wrapper { typedef stage< T , Constant::value > type; }; #endif template< size_t StageCount, size_t Order, class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer > #ifndef DOXYGEN_SKIP class explicit_generic_rk : public explicit_stepper_base< explicit_generic_rk< StageCount , Order , State , Value , Deriv , Time , Algebra , Operations , Resizer > , Order , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class explicit_generic_rk : public explicit_stepper_base #endif { public: #ifndef DOXYGEN_SKIP typedef explicit_stepper_base< explicit_generic_rk< StageCount , Order , State , Value , Deriv ,Time , Algebra , Operations , Resizer > , Order , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_stepper_base< ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef explicit_generic_rk< StageCount , Order , State , Value , Deriv ,Time , Algebra , Operations , Resizer > stepper_type; #endif typedef detail::generic_rk_algorithm< StageCount , Value , Algebra , Operations > rk_algorithm_type; typedef typename rk_algorithm_type::coef_a_type coef_a_type; typedef typename rk_algorithm_type::coef_b_type coef_b_type; typedef typename rk_algorithm_type::coef_c_type coef_c_type; #ifndef DOXYGEN_SKIP static const size_t stage_count = StageCount; #endif public: explicit_generic_rk( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c , const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) , m_rk_algorithm( a , b , c ) { } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); // actual calculation done in generic_rk.hpp m_rk_algorithm.do_step( stepper_base_type::m_algebra , system , in , dxdt , t , out , dt , m_x_tmp.m_v , m_F ); } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); resized |= adjust_size_by_resizeability( m_x_tmp , x , typename is_resizeable<state_type>::type() ); for( size_t i = 0 ; i < StageCount-1 ; ++i ) { resized |= adjust_size_by_resizeability( m_F[i] , x , typename is_resizeable<deriv_type>::type() ); } return resized; } rk_algorithm_type m_rk_algorithm; resizer_type m_resizer; wrapped_state_type m_x_tmp; wrapped_deriv_type m_F[StageCount-1]; }; /*********** DOXYGEN *************/ /** * \class explicit_generic_rk * \brief A generic implementation of explicit Runge-Kutta algorithms. This class is as a base class * for all explicit Runge-Kutta steppers. * * This class implements the explicit Runge-Kutta algorithms without error estimation in a generic way. * The Butcher tableau is passed to the stepper which constructs the stepper scheme with the help of a * template-metaprogramming algorithm. ToDo : Add example! * * This class derives explicit_stepper_base which provides the stepper interface. * * \tparam StageCount The number of stages of the Runge-Kutta algorithm. * \tparam Order The order of the stepper. * \tparam State The type representing the state of the ODE. * \tparam Value The floating point type which is used in the computations. * \tparam Time The type representing the independent variable - the time - of the ODE. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn explicit_generic_rk::explicit_generic_rk( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c , const algebra_type &algebra ) * \brief Constructs the explicit_generic_rk class. See examples section for details on the coefficients. * \param a Triangular matrix of parameters b in the Butcher tableau. * \param b Last row of the butcher tableau. * \param c Parameters to calculate the time points in the Butcher tableau. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn explicit_generic_rk::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out of place, hence the input is in `in` and the output in `out`. * Access to this step functionality is provided by explicit_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn explicit_generic_rk::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_EXPLICIT_GENERIC_RK_HPP_INCLUDED odeint/stepper/controlled_step_result.hpp 0000644 00000002104 15125237305 0015017 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/controlled_step_result.hpp [begin_description] Defines the result type for all controlled stepper. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_STEPPER_CONTROLLED_STEP_RESULT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_STEP_RESULT_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { /** * \enum controlled_step_result * * \brief Enum representing the return values of the controlled steppers. */ typedef enum { success , /**< The trial step was successful, hence the state and the time have been advanced. */ fail /**< The step was not successful and might possibly be repeated with a small step size. */ } controlled_step_result; } // namespace odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_STEP_RESULT_HPP_INCLUDED odeint/stepper/bulirsch_stoer_dense_out.hpp 0000644 00000102103 15125237305 0015315 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp [begin_description] Implementaiton of the Burlish-Stoer method with dense output [end_description] Copyright 2011-2015 Mario Mulansky Copyright 2011-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BULIRSCH_STOER_DENSE_OUT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BULIRSCH_STOER_DENSE_OUT_HPP_INCLUDED #include <iostream> #include <algorithm> #include <boost/config.hpp> // for min/max guidelines #include <boost/numeric/odeint/util/bind.hpp> #include <boost/math/special_functions/binomial.hpp> #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/modified_midpoint.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> #include <boost/type_traits.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class bulirsch_stoer_dense_out { public: typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; typedef dense_output_stepper_tag stepper_category; #ifndef DOXYGEN_SKIP typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef bulirsch_stoer_dense_out< State , Value , Deriv , Time , Algebra , Operations , Resizer > controlled_error_bs_type; typedef typename inverse_time< time_type >::type inv_time_type; typedef std::vector< value_type > value_vector; typedef std::vector< time_type > time_vector; typedef std::vector< inv_time_type > inv_time_vector; //should be 1/time_type for boost.units typedef std::vector< value_vector > value_matrix; typedef std::vector< size_t > int_vector; typedef std::vector< wrapped_state_type > state_vector_type; typedef std::vector< wrapped_deriv_type > deriv_vector_type; typedef std::vector< deriv_vector_type > deriv_table_type; #endif //DOXYGEN_SKIP const static size_t m_k_max = 8; bulirsch_stoer_dense_out( value_type eps_abs = 1E-6 , value_type eps_rel = 1E-6 , value_type factor_x = 1.0 , value_type factor_dxdt = 1.0 , time_type max_dt = static_cast<time_type>(0) , bool control_interpolation = false ) : m_error_checker( eps_abs , eps_rel , factor_x, factor_dxdt ) , m_max_dt(max_dt) , m_control_interpolation( control_interpolation) , m_last_step_rejected( false ) , m_first( true ) , m_current_state_x1( true ) , m_error( m_k_max ) , m_interval_sequence( m_k_max+1 ) , m_coeff( m_k_max+1 ) , m_cost( m_k_max+1 ) , m_facmin_table( m_k_max+1 ) , m_table( m_k_max ) , m_mp_states( m_k_max+1 ) , m_derivs( m_k_max+1 ) , m_diffs( 2*m_k_max+2 ) , STEPFAC1( 0.65 ) , STEPFAC2( 0.94 ) , STEPFAC3( 0.02 ) , STEPFAC4( 4.0 ) , KFAC1( 0.8 ) , KFAC2( 0.9 ) { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); for( unsigned short i = 0; i < m_k_max+1; i++ ) { /* only this specific sequence allows for dense output */ m_interval_sequence[i] = 2 + 4*i; // 2 6 10 14 ... m_derivs[i].resize( m_interval_sequence[i] ); if( i == 0 ) { m_cost[i] = m_interval_sequence[i]; } else { m_cost[i] = m_cost[i-1] + m_interval_sequence[i]; } m_facmin_table[i] = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , static_cast< value_type >(1) / static_cast< value_type >( 2*i+1 ) ); m_coeff[i].resize(i); for( size_t k = 0 ; k < i ; ++k ) { const value_type r = static_cast< value_type >( m_interval_sequence[i] ) / static_cast< value_type >( m_interval_sequence[k] ); m_coeff[i][k] = 1.0 / ( r*r - static_cast< value_type >( 1.0 ) ); // coefficients for extrapolation } // crude estimate of optimal order m_current_k_opt = 4; /* no calculation because log10 might not exist for value_type! const value_type logfact( -log10( max BOOST_PREVENT_MACRO_SUBSTITUTION( eps_rel , static_cast< value_type >( 1.0E-12 ) ) ) * 0.6 + 0.5 ); m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( 1 , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>( m_k_max-1 ) , static_cast<int>( logfact ) )); */ } int num = 1; for( int i = 2*(m_k_max)+1 ; i >=0 ; i-- ) { m_diffs[i].resize( num ); num += (i+1)%2; } } template< class System , class StateIn , class DerivIn , class StateOut , class DerivOut > controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , DerivOut &dxdt_new , time_type &dt ) { if( m_max_dt != static_cast<time_type>(0) && detail::less_with_sign(m_max_dt, dt, dt) ) { // given step size is bigger then max_dt // set limit and return fail dt = m_max_dt; return fail; } BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; static const value_type val1( 1.0 ); bool reject( true ); time_vector h_opt( m_k_max+1 ); inv_time_vector work( m_k_max+1 ); m_k_final = 0; time_type new_h = dt; //std::cout << "t=" << t <<", dt=" << dt << ", k_opt=" << m_current_k_opt << ", first: " << m_first << std::endl; for( size_t k = 0 ; k <= m_current_k_opt+1 ; k++ ) { m_midpoint.set_steps( m_interval_sequence[k] ); if( k == 0 ) { m_midpoint.do_step( system , in , dxdt , t , out , dt , m_mp_states[k].m_v , m_derivs[k]); } else { m_midpoint.do_step( system , in , dxdt , t , m_table[k-1].m_v , dt , m_mp_states[k].m_v , m_derivs[k] ); extrapolate( k , m_table , m_coeff , out ); // get error estimate m_algebra.for_each3( m_err.m_v , out , m_table[0].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 , -val1 ) ); const value_type error = m_error_checker.error( m_algebra , in , dxdt , m_err.m_v , dt ); h_opt[k] = calc_h_opt( dt , error , k ); work[k] = static_cast<value_type>( m_cost[k] ) / h_opt[k]; m_k_final = k; if( (k == m_current_k_opt-1) || m_first ) { // convergence before k_opt ? if( error < 1.0 ) { //convergence reject = false; if( (work[k] < KFAC2*work[k-1]) || (m_current_k_opt <= 2) ) { // leave order as is (except we were in first round) m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(k)+1 ) ); new_h = h_opt[k] * static_cast<value_type>( m_cost[k+1] ) / static_cast<value_type>( m_cost[k] ); } else { m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(k) ) ); new_h = h_opt[k]; } break; } else if( should_reject( error , k ) && !m_first ) { reject = true; new_h = h_opt[k]; break; } } if( k == m_current_k_opt ) { // convergence at k_opt ? if( error < 1.0 ) { //convergence reject = false; if( (work[k-1] < KFAC2*work[k]) ) { m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(m_current_k_opt)-1 ); new_h = h_opt[m_current_k_opt]; } else if( (work[k] < KFAC2*work[k-1]) && !m_last_step_rejected ) { m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , static_cast<int>(m_current_k_opt)+1 ); new_h = h_opt[k]*static_cast<value_type>( m_cost[m_current_k_opt] ) / static_cast<value_type>( m_cost[k] ); } else new_h = h_opt[m_current_k_opt]; break; } else if( should_reject( error , k ) ) { reject = true; new_h = h_opt[m_current_k_opt]; break; } } if( k == m_current_k_opt+1 ) { // convergence at k_opt+1 ? if( error < 1.0 ) { //convergence reject = false; if( work[k-2] < KFAC2*work[k-1] ) m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(m_current_k_opt)-1 ); if( (work[k] < KFAC2*work[m_current_k_opt]) && !m_last_step_rejected ) m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , static_cast<int>(k) ); new_h = h_opt[m_current_k_opt]; } else { reject = true; new_h = h_opt[m_current_k_opt]; } break; } } } if( !reject ) { //calculate dxdt for next step and dense output typename odeint::unwrap_reference< System >::type &sys = system; sys( out , dxdt_new , t+dt ); //prepare dense output value_type error = prepare_dense_output( m_k_final , in , dxdt , out , dxdt_new , dt ); if( error > static_cast<value_type>(10) ) // we are not as accurate for interpolation as for the steps { reject = true; new_h = dt * pow BOOST_PREVENT_MACRO_SUBSTITUTION( error , static_cast<value_type>(-1)/(2*m_k_final+2) ); } else { t += dt; } } //set next stepsize if( !m_last_step_rejected || (new_h < dt) ) { // limit step size if( m_max_dt != static_cast<time_type>(0) ) { new_h = detail::min_abs(m_max_dt, new_h); } dt = new_h; } m_last_step_rejected = reject; if( reject ) return fail; else return success; } template< class StateType > void initialize( const StateType &x0 , const time_type &t0 , const time_type &dt0 ) { m_resizer.adjust_size( x0 , detail::bind( &controlled_error_bs_type::template resize_impl< StateType > , detail::ref( *this ) , detail::_1 ) ); boost::numeric::odeint::copy( x0 , get_current_state() ); m_t = t0; m_dt = dt0; reset(); } /* ======================================================= * the actual step method that should be called from outside (maybe make try_step private?) */ template< class System > std::pair< time_type , time_type > do_step( System system ) { if( m_first ) { typename odeint::unwrap_reference< System >::type &sys = system; sys( get_current_state() , get_current_deriv() , m_t ); } failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails controlled_step_result res = fail; m_t_last = m_t; while( res == fail ) { res = try_step( system , get_current_state() , get_current_deriv() , m_t , get_old_state() , get_old_deriv() , m_dt ); m_first = false; fail_checker(); // check for overflow of failed steps } toggle_current_state(); return std::make_pair( m_t_last , m_t ); } /* performs the interpolation from a calculated step */ template< class StateOut > void calc_state( time_type t , StateOut &x ) const { do_interpolation( t , x ); } const state_type& current_state( void ) const { return get_current_state(); } time_type current_time( void ) const { return m_t; } const state_type& previous_state( void ) const { return get_old_state(); } time_type previous_time( void ) const { return m_t_last; } time_type current_time_step( void ) const { return m_dt; } /** \brief Resets the internal state of the stepper. */ void reset() { m_first = true; m_last_step_rejected = false; } template< class StateIn > void adjust_size( const StateIn &x ) { resize_impl( x ); m_midpoint.adjust_size( x ); } protected: time_type m_max_dt; private: template< class StateInOut , class StateVector > void extrapolate( size_t k , StateVector &table , const value_matrix &coeff , StateInOut &xest , size_t order_start_index = 0 ) //polynomial extrapolation, see http://www.nr.com/webnotes/nr3web21.pdf { static const value_type val1( 1.0 ); for( int j=k-1 ; j>0 ; --j ) { m_algebra.for_each3( table[j-1].m_v , table[j].m_v , table[j-1].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k + order_start_index][j + order_start_index] , -coeff[k + order_start_index][j + order_start_index] ) ); } m_algebra.for_each3( xest , table[0].m_v , xest , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k + order_start_index][0 + order_start_index] , -coeff[k + order_start_index][0 + order_start_index]) ); } template< class StateVector > void extrapolate_dense_out( size_t k , StateVector &table , const value_matrix &coeff , size_t order_start_index = 0 ) //polynomial extrapolation, see http://www.nr.com/webnotes/nr3web21.pdf { // result is written into table[0] static const value_type val1( 1.0 ); for( int j=k ; j>1 ; --j ) { m_algebra.for_each3( table[j-1].m_v , table[j].m_v , table[j-1].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k + order_start_index][j + order_start_index - 1] , -coeff[k + order_start_index][j + order_start_index - 1] ) ); } m_algebra.for_each3( table[0].m_v , table[1].m_v , table[0].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k + order_start_index][order_start_index] , -coeff[k + order_start_index][order_start_index]) ); } time_type calc_h_opt( time_type h , value_type error , size_t k ) const { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; value_type expo = static_cast<value_type>(1)/(m_interval_sequence[k-1]); value_type facmin = m_facmin_table[k]; value_type fac; if (error == 0.0) fac = static_cast<value_type>(1)/facmin; else { fac = STEPFAC2 / pow BOOST_PREVENT_MACRO_SUBSTITUTION( error / STEPFAC1 , expo ); fac = max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( facmin/STEPFAC4 ) , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>(static_cast<value_type>(1)/facmin) , fac ) ); } return h*fac; } bool in_convergence_window( size_t k ) const { if( (k == m_current_k_opt-1) && !m_last_step_rejected ) return true; // decrease order only if last step was not rejected return ( (k == m_current_k_opt) || (k == m_current_k_opt+1) ); } bool should_reject( value_type error , size_t k ) const { if( k == m_current_k_opt-1 ) { const value_type d = m_interval_sequence[m_current_k_opt] * m_interval_sequence[m_current_k_opt+1] / (m_interval_sequence[0]*m_interval_sequence[0]); //step will fail, criterion 17.3.17 in NR return ( error > d*d ); } else if( k == m_current_k_opt ) { const value_type d = m_interval_sequence[m_current_k_opt+1] / m_interval_sequence[0]; return ( error > d*d ); } else return error > 1.0; } template< class StateIn1 , class DerivIn1 , class StateIn2 , class DerivIn2 > value_type prepare_dense_output( int k , const StateIn1 &x_start , const DerivIn1 &dxdt_start , const StateIn2 & /* x_end */ , const DerivIn2 & /*dxdt_end */ , time_type dt ) /* k is the order to which the result was approximated */ { /* compute the coefficients of the interpolation polynomial * we parametrize the interval t .. t+dt by theta = -1 .. 1 * we use 2k+3 values at the interval center theta=0 to obtain the interpolation coefficients * the values are x(t+dt/2) and the derivatives dx/dt , ... d^(2k+2) x / dt^(2k+2) at the midpoints * the derivatives are approximated via finite differences * all values are obtained from interpolation of the results from the increasing orders of the midpoint calls */ // calculate finite difference approximations to derivatives at the midpoint for( int j = 0 ; j<=k ; j++ ) { /* not working with boost units... */ const value_type d = m_interval_sequence[j] / ( static_cast<value_type>(2) * dt ); value_type f = 1.0; //factor 1/2 here because our interpolation interval has length 2 !!! for( int kappa = 0 ; kappa <= 2*j+1 ; ++kappa ) { calculate_finite_difference( j , kappa , f , dxdt_start ); f *= d; } if( j > 0 ) extrapolate_dense_out( j , m_mp_states , m_coeff ); } time_type d = dt/2; // extrapolate finite differences for( int kappa = 0 ; kappa<=2*k+1 ; kappa++ ) { for( int j=1 ; j<=(k-kappa/2) ; ++j ) extrapolate_dense_out( j , m_diffs[kappa] , m_coeff , kappa/2 ); // extrapolation results are now stored in m_diffs[kappa][0] // divide kappa-th derivative by kappa because we need these terms for dense output interpolation m_algebra.for_each1( m_diffs[kappa][0].m_v , typename operations_type::template scale< time_type >( static_cast<time_type>(d) ) ); d *= dt/(2*(kappa+2)); } // dense output coefficients a_0 is stored in m_mp_states[0], a_i for i = 1...2k are stored in m_diffs[i-1][0] // the error is just the highest order coefficient of the interpolation polynomial // this is because we use only the midpoint theta=0 as support for the interpolation (remember that theta = -1 .. 1) value_type error = 0.0; if( m_control_interpolation ) { boost::numeric::odeint::copy( m_diffs[2*k+1][0].m_v , m_err.m_v ); error = m_error_checker.error( m_algebra , x_start , dxdt_start , m_err.m_v , dt ); } return error; } template< class DerivIn > void calculate_finite_difference( size_t j , size_t kappa , value_type fac , const DerivIn &dxdt ) { const int m = m_interval_sequence[j]/2-1; if( kappa == 0) // no calculation required for 0th derivative of f { m_algebra.for_each2( m_diffs[0][j].m_v , m_derivs[j][m].m_v , typename operations_type::template scale_sum1< value_type >( fac ) ); } else { // calculate the index of m_diffs for this kappa-j-combination const int j_diffs = j - kappa/2; m_algebra.for_each2( m_diffs[kappa][j_diffs].m_v , m_derivs[j][m+kappa].m_v , typename operations_type::template scale_sum1< value_type >( fac ) ); value_type sign = -1.0; int c = 1; //computes the j-th order finite difference for the kappa-th derivative of f at t+dt/2 using function evaluations stored in m_derivs for( int i = m+static_cast<int>(kappa)-2 ; i >= m-static_cast<int>(kappa) ; i -= 2 ) { if( i >= 0 ) { m_algebra.for_each3( m_diffs[kappa][j_diffs].m_v , m_diffs[kappa][j_diffs].m_v , m_derivs[j][i].m_v , typename operations_type::template scale_sum2< value_type , value_type >( 1.0 , sign * fac * boost::math::binomial_coefficient< value_type >( kappa , c ) ) ); } else { m_algebra.for_each3( m_diffs[kappa][j_diffs].m_v , m_diffs[kappa][j_diffs].m_v , dxdt , typename operations_type::template scale_sum2< value_type , value_type >( 1.0 , sign * fac ) ); } sign *= -1; ++c; } } } template< class StateOut > void do_interpolation( time_type t , StateOut &out ) const { // interpolation polynomial is defined for theta = -1 ... 1 // m_k_final is the number of order-iterations done for the last step - it governs the order of the interpolation polynomial const value_type theta = 2 * get_unit_value( (t - m_t_last) / (m_t - m_t_last) ) - 1; // we use only values at interval center, that is theta=0, for interpolation // our interpolation polynomial is thus of order 2k+2, hence we have 2k+3 terms boost::numeric::odeint::copy( m_mp_states[0].m_v , out ); // add remaining terms: x += a_1 theta + a2 theta^2 + ... + a_{2k} theta^{2k} value_type theta_pow( theta ); for( size_t i=0 ; i<=2*m_k_final+1 ; ++i ) { m_algebra.for_each3( out , out , m_diffs[i][0].m_v , typename operations_type::template scale_sum2< value_type >( static_cast<value_type>(1) , theta_pow ) ); theta_pow *= theta; } } /* Resizer methods */ template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); resized |= adjust_size_by_resizeability( m_x1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_x2 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdt1 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_dxdt2 , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_err , x , typename is_resizeable<state_type>::type() ); for( size_t i = 0 ; i < m_k_max ; ++i ) resized |= adjust_size_by_resizeability( m_table[i] , x , typename is_resizeable<state_type>::type() ); for( size_t i = 0 ; i < m_k_max+1 ; ++i ) resized |= adjust_size_by_resizeability( m_mp_states[i] , x , typename is_resizeable<state_type>::type() ); for( size_t i = 0 ; i < m_k_max+1 ; ++i ) for( size_t j = 0 ; j < m_derivs[i].size() ; ++j ) resized |= adjust_size_by_resizeability( m_derivs[i][j] , x , typename is_resizeable<deriv_type>::type() ); for( size_t i = 0 ; i < 2*m_k_max+2 ; ++i ) for( size_t j = 0 ; j < m_diffs[i].size() ; ++j ) resized |= adjust_size_by_resizeability( m_diffs[i][j] , x , typename is_resizeable<deriv_type>::type() ); return resized; } state_type& get_current_state( void ) { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } const state_type& get_current_state( void ) const { return m_current_state_x1 ? m_x1.m_v : m_x2.m_v ; } state_type& get_old_state( void ) { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } const state_type& get_old_state( void ) const { return m_current_state_x1 ? m_x2.m_v : m_x1.m_v ; } deriv_type& get_current_deriv( void ) { return m_current_state_x1 ? m_dxdt1.m_v : m_dxdt2.m_v ; } const deriv_type& get_current_deriv( void ) const { return m_current_state_x1 ? m_dxdt1.m_v : m_dxdt2.m_v ; } deriv_type& get_old_deriv( void ) { return m_current_state_x1 ? m_dxdt2.m_v : m_dxdt1.m_v ; } const deriv_type& get_old_deriv( void ) const { return m_current_state_x1 ? m_dxdt2.m_v : m_dxdt1.m_v ; } void toggle_current_state( void ) { m_current_state_x1 = ! m_current_state_x1; } default_error_checker< value_type, algebra_type , operations_type > m_error_checker; modified_midpoint_dense_out< state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type > m_midpoint; bool m_control_interpolation; bool m_last_step_rejected; bool m_first; time_type m_t; time_type m_dt; time_type m_dt_last; time_type m_t_last; size_t m_current_k_opt; size_t m_k_final; algebra_type m_algebra; resizer_type m_resizer; wrapped_state_type m_x1 , m_x2; wrapped_deriv_type m_dxdt1 , m_dxdt2; wrapped_state_type m_err; bool m_current_state_x1; value_vector m_error; // errors of repeated midpoint steps and extrapolations int_vector m_interval_sequence; // stores the successive interval counts value_matrix m_coeff; int_vector m_cost; // costs for interval count value_vector m_facmin_table; // for precomputed facmin to save pow calls state_vector_type m_table; // sequence of states for extrapolation //for dense output: state_vector_type m_mp_states; // sequence of approximations of x at distance center deriv_table_type m_derivs; // table of function values deriv_table_type m_diffs; // table of function values //wrapped_state_type m_a1 , m_a2 , m_a3 , m_a4; value_type STEPFAC1 , STEPFAC2 , STEPFAC3 , STEPFAC4 , KFAC1 , KFAC2; }; /********** DOXYGEN **********/ /** * \class bulirsch_stoer_dense_out * \brief The Bulirsch-Stoer algorithm. * * The Bulirsch-Stoer is a controlled stepper that adjusts both step size * and order of the method. The algorithm uses the modified midpoint and * a polynomial extrapolation compute the solution. This class also provides * dense output facility. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn bulirsch_stoer_dense_out::bulirsch_stoer_dense_out( value_type eps_abs , value_type eps_rel , value_type factor_x , value_type factor_dxdt , bool control_interpolation ) * \brief Constructs the bulirsch_stoer class, including initialization of * the error bounds. * * \param eps_abs Absolute tolerance level. * \param eps_rel Relative tolerance level. * \param factor_x Factor for the weight of the state. * \param factor_dxdt Factor for the weight of the derivative. * \param control_interpolation Set true to additionally control the error of * the interpolation. */ /** * \fn bulirsch_stoer_dense_out::try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , DerivOut &dxdt_new , time_type &dt ) * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. Also, the internal order of the stepper is adjusted if required. * * \param system The system function to solve, hence the r.h.s. of the ODE. * It must fulfill the Simple System concept. * \param in The state of the ODE which should be solved. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ /** * \fn bulirsch_stoer_dense_out::initialize( const StateType &x0 , const time_type &t0 , const time_type &dt0 ) * \brief Initializes the dense output stepper. * * \param x0 The initial state. * \param t0 The initial time. * \param dt0 The initial time step. */ /** * \fn bulirsch_stoer_dense_out::do_step( System system ) * \brief Does one time step. This is the main method that should be used to * integrate an ODE with this stepper. * \note initialize has to be called before using this method to set the * initial conditions x,t and the stepsize. * \param system The system function to solve, hence the r.h.s. of the * ordinary differential equation. It must fulfill the Simple System concept. * \return Pair with start and end time of the integration step. */ /** * \fn bulirsch_stoer_dense_out::calc_state( time_type t , StateOut &x ) const * \brief Calculates the solution at an intermediate point within the last step * \param t The time at which the solution should be calculated, has to be * in the current time interval. * \param x The output variable where the result is written into. */ /** * \fn bulirsch_stoer_dense_out::current_state( void ) const * \brief Returns the current state of the solution. * \return The current state of the solution x(t). */ /** * \fn bulirsch_stoer_dense_out::current_time( void ) const * \brief Returns the current time of the solution. * \return The current time of the solution t. */ /** * \fn bulirsch_stoer_dense_out::previous_state( void ) const * \brief Returns the last state of the solution. * \return The last state of the solution x(t-dt). */ /** * \fn bulirsch_stoer_dense_out::previous_time( void ) const * \brief Returns the last time of the solution. * \return The last time of the solution t-dt. */ /** * \fn bulirsch_stoer_dense_out::current_time_step( void ) const * \brief Returns the current step size. * \return The current step size. */ /** * \fn bulirsch_stoer_dense_out::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_BULIRSCH_STOER_HPP_INCLUDED odeint/stepper/bulirsch_stoer.hpp 0000644 00000063115 15125237305 0013261 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/bulirsch_stoer.hpp [begin_description] Implementation of the Burlish-Stoer method. As described in Ernst Hairer, Syvert Paul Norsett, Gerhard Wanner Solving Ordinary Differential Equations I. Nonstiff Problems. Springer Series in Comput. Mathematics, Vol. 8, Springer-Verlag 1987, Second revised edition 1993. [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2013 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_BULIRSCH_STOER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_BULIRSCH_STOER_HPP_INCLUDED #include <iostream> #include <algorithm> #include <boost/config.hpp> // for min/max guidelines #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/modified_midpoint.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > class bulirsch_stoer { public: typedef State state_type; typedef Value value_type; typedef Deriv deriv_type; typedef Time time_type; typedef Algebra algebra_type; typedef Operations operations_type; typedef Resizer resizer_type; #ifndef DOXYGEN_SKIP typedef state_wrapper< state_type > wrapped_state_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef controlled_stepper_tag stepper_category; typedef bulirsch_stoer< State , Value , Deriv , Time , Algebra , Operations , Resizer > controlled_error_bs_type; typedef typename inverse_time< time_type >::type inv_time_type; typedef std::vector< value_type > value_vector; typedef std::vector< time_type > time_vector; typedef std::vector< inv_time_type > inv_time_vector; //should be 1/time_type for boost.units typedef std::vector< value_vector > value_matrix; typedef std::vector< size_t > int_vector; typedef std::vector< wrapped_state_type > state_table_type; #endif //DOXYGEN_SKIP const static size_t m_k_max = 8; bulirsch_stoer( value_type eps_abs = 1E-6 , value_type eps_rel = 1E-6 , value_type factor_x = 1.0 , value_type factor_dxdt = 1.0 , time_type max_dt = static_cast<time_type>(0)) : m_error_checker( eps_abs , eps_rel , factor_x, factor_dxdt ) , m_midpoint() , m_last_step_rejected( false ) , m_first( true ) , m_max_dt(max_dt) , m_interval_sequence( m_k_max+1 ) , m_coeff( m_k_max+1 ) , m_cost( m_k_max+1 ) , m_facmin_table( m_k_max+1 ) , m_table( m_k_max ) , STEPFAC1( 0.65 ) , STEPFAC2( 0.94 ) , STEPFAC3( 0.02 ) , STEPFAC4( 4.0 ) , KFAC1( 0.8 ) , KFAC2( 0.9 ) { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); /* initialize sequence of stage numbers and work */ for( unsigned short i = 0; i < m_k_max+1; i++ ) { m_interval_sequence[i] = 2 * (i+1); if( i == 0 ) m_cost[i] = m_interval_sequence[i]; else m_cost[i] = m_cost[i-1] + m_interval_sequence[i]; m_coeff[i].resize(i); m_facmin_table[i] = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , static_cast< value_type >(1) / static_cast< value_type >( 2*i+1 ) ); for( size_t k = 0 ; k < i ; ++k ) { const value_type r = static_cast< value_type >( m_interval_sequence[i] ) / static_cast< value_type >( m_interval_sequence[k] ); m_coeff[i][k] = 1.0 / ( r*r - static_cast< value_type >( 1.0 ) ); // coefficients for extrapolation } } reset(); } /* * Version 1 : try_step( sys , x , t , dt ) * * The overloads are needed to solve the forwarding problem */ template< class System , class StateInOut > controlled_step_result try_step( System system , StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t, dt ); } /** * \brief Second version to solve the forwarding problem, can be used with Boost.Range as StateInOut. */ template< class System , class StateInOut > controlled_step_result try_step( System system , const StateInOut &x , time_type &t , time_type &dt ) { return try_step_v1( system , x , t, dt ); } /* * Version 2 : try_step( sys , x , dxdt , t , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateInOut , class DerivIn > controlled_step_result try_step( System system , StateInOut &x , const DerivIn &dxdt , time_type &t , time_type &dt ) { m_xnew_resizer.adjust_size( x , detail::bind( &controlled_error_bs_type::template resize_m_xnew< StateInOut > , detail::ref( *this ) , detail::_1 ) ); controlled_step_result res = try_step( system , x , dxdt , t , m_xnew.m_v , dt ); if( res == success ) { boost::numeric::odeint::copy( m_xnew.m_v , x ); } return res; } /* * Version 3 : try_step( sys , in , t , out , dt ) * * this version does not solve the forwarding problem, boost.range can not be used */ template< class System , class StateIn , class StateOut > typename boost::disable_if< boost::is_same< StateIn , time_type > , controlled_step_result >::type try_step( System system , const StateIn &in , time_type &t , StateOut &out , time_type &dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_dxdt_resizer.adjust_size( in , detail::bind( &controlled_error_bs_type::template resize_m_dxdt< StateIn > , detail::ref( *this ) , detail::_1 ) ); sys( in , m_dxdt.m_v , t ); return try_step( system , in , m_dxdt.m_v , t , out , dt ); } /* * Full version : try_step( sys , in , dxdt_in , t , out , dt ) * * contains the actual implementation */ template< class System , class StateIn , class DerivIn , class StateOut > controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt ) { if( m_max_dt != static_cast<time_type>(0) && detail::less_with_sign(m_max_dt, dt, dt) ) { // given step size is bigger then max_dt // set limit and return fail dt = m_max_dt; return fail; } BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); static const value_type val1( 1.0 ); if( m_resizer.adjust_size( in , detail::bind( &controlled_error_bs_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ) ) { reset(); // system resized -> reset } if( dt != m_dt_last ) { reset(); // step size changed from outside -> reset } bool reject( true ); time_vector h_opt( m_k_max+1 ); inv_time_vector work( m_k_max+1 ); time_type new_h = dt; /* m_current_k_opt is the estimated current optimal stage number */ for( size_t k = 0 ; k <= m_current_k_opt+1 ; k++ ) { /* the stage counts are stored in m_interval_sequence */ m_midpoint.set_steps( m_interval_sequence[k] ); if( k == 0 ) { m_midpoint.do_step( system , in , dxdt , t , out , dt ); /* the first step, nothing more to do */ } else { m_midpoint.do_step( system , in , dxdt , t , m_table[k-1].m_v , dt ); extrapolate( k , m_table , m_coeff , out ); // get error estimate m_algebra.for_each3( m_err.m_v , out , m_table[0].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 , -val1 ) ); const value_type error = m_error_checker.error( m_algebra , in , dxdt , m_err.m_v , dt ); h_opt[k] = calc_h_opt( dt , error , k ); work[k] = static_cast<value_type>( m_cost[k] ) / h_opt[k]; if( (k == m_current_k_opt-1) || m_first ) { // convergence before k_opt ? if( error < 1.0 ) { //convergence reject = false; if( (work[k] < KFAC2*work[k-1]) || (m_current_k_opt <= 2) ) { // leave order as is (except we were in first round) m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(k)+1 ) ); new_h = h_opt[k]; new_h *= static_cast<value_type>( m_cost[k+1] ) / static_cast<value_type>( m_cost[k] ); } else { m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(k) ) ); new_h = h_opt[k]; } break; } else if( should_reject( error , k ) && !m_first ) { reject = true; new_h = h_opt[k]; break; } } if( k == m_current_k_opt ) { // convergence at k_opt ? if( error < 1.0 ) { //convergence reject = false; if( (work[k-1] < KFAC2*work[k]) ) { m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(m_current_k_opt)-1 ); new_h = h_opt[m_current_k_opt]; } else if( (work[k] < KFAC2*work[k-1]) && !m_last_step_rejected ) { m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max-1) , static_cast<int>(m_current_k_opt)+1 ); new_h = h_opt[k]; new_h *= static_cast<value_type>(m_cost[m_current_k_opt])/static_cast<value_type>(m_cost[k]); } else new_h = h_opt[m_current_k_opt]; break; } else if( should_reject( error , k ) ) { reject = true; new_h = h_opt[m_current_k_opt]; break; } } if( k == m_current_k_opt+1 ) { // convergence at k_opt+1 ? if( error < 1.0 ) { //convergence reject = false; if( work[k-2] < KFAC2*work[k-1] ) m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( 2 , static_cast<int>(m_current_k_opt)-1 ); if( (work[k] < KFAC2*work[m_current_k_opt]) && !m_last_step_rejected ) m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max)-1 , static_cast<int>(k) ); new_h = h_opt[m_current_k_opt]; } else { reject = true; new_h = h_opt[m_current_k_opt]; } break; } } } if( !reject ) { t += dt; } if( !m_last_step_rejected || boost::numeric::odeint::detail::less_with_sign(new_h, dt, dt) ) { // limit step size if( m_max_dt != static_cast<time_type>(0) ) { new_h = detail::min_abs(m_max_dt, new_h); } m_dt_last = new_h; dt = new_h; } m_last_step_rejected = reject; m_first = false; if( reject ) return fail; else return success; } /** \brief Resets the internal state of the stepper */ void reset() { m_first = true; m_last_step_rejected = false; // crude estimate of optimal order m_current_k_opt = 4; /* no calculation because log10 might not exist for value_type! const value_type logfact( -log10( max BOOST_PREVENT_MACRO_SUBSTITUTION( eps_rel , static_cast< value_type >(1.0E-12) ) ) * 0.6 + 0.5 ); m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( 1 ) , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( m_k_max-1 ) , logfact )); */ } /* Resizer methods */ template< class StateIn > void adjust_size( const StateIn &x ) { resize_m_dxdt( x ); resize_m_xnew( x ); resize_impl( x ); m_midpoint.adjust_size( x ); } private: template< class StateIn > bool resize_m_dxdt( const StateIn &x ) { return adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); } template< class StateIn > bool resize_m_xnew( const StateIn &x ) { return adjust_size_by_resizeability( m_xnew , x , typename is_resizeable<state_type>::type() ); } template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized( false ); for( size_t i = 0 ; i < m_k_max ; ++i ) resized |= adjust_size_by_resizeability( m_table[i] , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_err , x , typename is_resizeable<state_type>::type() ); return resized; } template< class System , class StateInOut > controlled_step_result try_step_v1( System system , StateInOut &x , time_type &t , time_type &dt ) { typename odeint::unwrap_reference< System >::type &sys = system; m_dxdt_resizer.adjust_size( x , detail::bind( &controlled_error_bs_type::template resize_m_dxdt< StateInOut > , detail::ref( *this ) , detail::_1 ) ); sys( x , m_dxdt.m_v ,t ); return try_step( system , x , m_dxdt.m_v , t , dt ); } template< class StateInOut > void extrapolate( size_t k , state_table_type &table , const value_matrix &coeff , StateInOut &xest ) /* polynomial extrapolation, see http://www.nr.com/webnotes/nr3web21.pdf uses the obtained intermediate results to extrapolate to dt->0 */ { static const value_type val1 = static_cast< value_type >( 1.0 ); for( int j=k-1 ; j>0 ; --j ) { m_algebra.for_each3( table[j-1].m_v , table[j].m_v , table[j-1].m_v , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k][j] , -coeff[k][j] ) ); } m_algebra.for_each3( xest , table[0].m_v , xest , typename operations_type::template scale_sum2< value_type , value_type >( val1 + coeff[k][0] , -coeff[k][0]) ); } time_type calc_h_opt( time_type h , value_type error , size_t k ) const /* calculates the optimal step size for a given error and stage number */ { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); using std::pow; value_type expo( 1.0/(2*k+1) ); value_type facmin = m_facmin_table[k]; value_type fac; if (error == 0.0) fac=1.0/facmin; else { fac = STEPFAC2 / pow BOOST_PREVENT_MACRO_SUBSTITUTION( error / STEPFAC1 , expo ); fac = max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>(facmin/STEPFAC4) , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>(1.0/facmin) , fac ) ); } return h*fac; } controlled_step_result set_k_opt( size_t k , const inv_time_vector &work , const time_vector &h_opt , time_type &dt ) /* calculates the optimal stage number */ { if( k == 1 ) { m_current_k_opt = 2; return success; } if( (work[k-1] < KFAC1*work[k]) || (k == m_k_max) ) { // order decrease m_current_k_opt = k-1; dt = h_opt[ m_current_k_opt ]; return success; } else if( (work[k] < KFAC2*work[k-1]) || m_last_step_rejected || (k == m_k_max-1) ) { // same order - also do this if last step got rejected m_current_k_opt = k; dt = h_opt[ m_current_k_opt ]; return success; } else { // order increase - only if last step was not rejected m_current_k_opt = k+1; dt = h_opt[ m_current_k_opt-1 ] * m_cost[ m_current_k_opt ] / m_cost[ m_current_k_opt-1 ] ; return success; } } bool in_convergence_window( size_t k ) const { if( (k == m_current_k_opt-1) && !m_last_step_rejected ) return true; // decrease stepsize only if last step was not rejected return ( (k == m_current_k_opt) || (k == m_current_k_opt+1) ); } bool should_reject( value_type error , size_t k ) const { if( k == m_current_k_opt-1 ) { const value_type d = m_interval_sequence[m_current_k_opt] * m_interval_sequence[m_current_k_opt+1] / (m_interval_sequence[0]*m_interval_sequence[0]); //step will fail, criterion 17.3.17 in NR return ( error > d*d ); } else if( k == m_current_k_opt ) { const value_type d = m_interval_sequence[m_current_k_opt] / m_interval_sequence[0]; return ( error > d*d ); } else return error > 1.0; } default_error_checker< value_type, algebra_type , operations_type > m_error_checker; modified_midpoint< state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type > m_midpoint; bool m_last_step_rejected; bool m_first; time_type m_dt_last; time_type m_t_last; time_type m_max_dt; size_t m_current_k_opt; algebra_type m_algebra; resizer_type m_dxdt_resizer; resizer_type m_xnew_resizer; resizer_type m_resizer; wrapped_state_type m_xnew; wrapped_state_type m_err; wrapped_deriv_type m_dxdt; int_vector m_interval_sequence; // stores the successive interval counts value_matrix m_coeff; int_vector m_cost; // costs for interval count value_vector m_facmin_table; // for precomputed facmin to save pow calls state_table_type m_table; // sequence of states for extrapolation value_type STEPFAC1 , STEPFAC2 , STEPFAC3 , STEPFAC4 , KFAC1 , KFAC2; }; /******** DOXYGEN ********/ /** * \class bulirsch_stoer * \brief The Bulirsch-Stoer algorithm. * * The Bulirsch-Stoer is a controlled stepper that adjusts both step size * and order of the method. The algorithm uses the modified midpoint and * a polynomial extrapolation compute the solution. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn bulirsch_stoer::bulirsch_stoer( value_type eps_abs , value_type eps_rel , value_type factor_x , value_type factor_dxdt ) * \brief Constructs the bulirsch_stoer class, including initialization of * the error bounds. * * \param eps_abs Absolute tolerance level. * \param eps_rel Relative tolerance level. * \param factor_x Factor for the weight of the state. * \param factor_dxdt Factor for the weight of the derivative. */ /** * \fn bulirsch_stoer::try_step( System system , StateInOut &x , time_type &t , time_type &dt ) * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. Also, the internal order of the stepper is adjusted if required. * * \param system The system function to solve, hence the r.h.s. of the ODE. * It must fulfill the Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ /** * \fn bulirsch_stoer::try_step( System system , StateInOut &x , const DerivIn &dxdt , time_type &t , time_type &dt ) * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. Also, the internal order of the stepper is adjusted if required. * * \param system The system function to solve, hence the r.h.s. of the ODE. * It must fulfill the Simple System concept. * \param x The state of the ODE which should be solved. Overwritten if * the step is successful. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ /** * \fn bulirsch_stoer::try_step( System system , const StateIn &in , time_type &t , StateOut &out , time_type &dt ) * \brief Tries to perform one step. * * \note This method is disabled if state_type=time_type to avoid ambiguity. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. Also, the internal order of the stepper is adjusted if required. * * \param system The system function to solve, hence the r.h.s. of the ODE. * It must fulfill the Simple System concept. * \param in The state of the ODE which should be solved. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ /** * \fn bulirsch_stoer::try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt ) * \brief Tries to perform one step. * * This method tries to do one step with step size dt. If the error estimate * is to large, the step is rejected and the method returns fail and the * step size dt is reduced. If the error estimate is acceptably small, the * step is performed, success is returned and dt might be increased to make * the steps as large as possible. This method also updates t if a step is * performed. Also, the internal order of the stepper is adjusted if required. * * \param system The system function to solve, hence the r.h.s. of the ODE. * It must fulfill the Simple System concept. * \param in The state of the ODE which should be solved. * \param dxdt The derivative of state. * \param t The value of the time. Updated if the step is successful. * \param out Used to store the result of the step. * \param dt The step size. Updated. * \return success if the step was accepted, fail otherwise. */ /** * \fn bulirsch_stoer::adjust_size( const StateIn &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } } } #endif // BOOST_NUMERIC_ODEINT_STEPPER_BULIRSCH_STOER_HPP_INCLUDED odeint/stepper/runge_kutta4_classic.hpp 0000644 00000022047 15125237305 0014346 0 ustar 00 /* [auto_generated] boost/numeric/odeint/stepper/runge_kutta4_classic.hpp [begin_description] Implementation for the classical Runge Kutta stepper. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2013 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_STEPPER_RUNGE_KUTTA4_CLASSIC_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA4_CLASSIC_HPP_INCLUDED #include <boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/default_operations.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resizer.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Value = double , class Deriv = State , class Time = Value , class Algebra = typename algebra_dispatcher< State >::algebra_type , class Operations = typename operations_dispatcher< State >::operations_type , class Resizer = initially_resizer > #ifndef DOXYGEN_SKIP class runge_kutta4_classic : public explicit_stepper_base< runge_kutta4_classic< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > #else class runge_kutta4_classic : public explicit_stepper_base #endif { public : #ifndef DOXYGEN_SKIP typedef explicit_stepper_base< runge_kutta4_classic< State , Value , Deriv , Time , Algebra , Operations , Resizer > , 4 , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_base_type; #else typedef explicit_stepper_base< runge_kutta4_classic< ... > , ... > stepper_base_type; #endif typedef typename stepper_base_type::state_type state_type; typedef typename stepper_base_type::value_type value_type; typedef typename stepper_base_type::deriv_type deriv_type; typedef typename stepper_base_type::time_type time_type; typedef typename stepper_base_type::algebra_type algebra_type; typedef typename stepper_base_type::operations_type operations_type; typedef typename stepper_base_type::resizer_type resizer_type; #ifndef DOXYGEN_SKIP typedef typename stepper_base_type::stepper_type stepper_type; typedef typename stepper_base_type::wrapped_state_type wrapped_state_type; typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type; #endif // DOXYGEN_SKIP runge_kutta4_classic( const algebra_type &algebra = algebra_type() ) : stepper_base_type( algebra ) { } template< class System , class StateIn , class DerivIn , class StateOut > void do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) { // ToDo : check if size of in,dxdt,out are equal? static const value_type val1 = static_cast< value_type >( 1 ); m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateIn > , detail::ref( *this ) , detail::_1 ) ); typename odeint::unwrap_reference< System >::type &sys = system; const time_type dh = dt / static_cast< value_type >( 2 ); const time_type th = t + dh; // dt * dxdt = k1 // m_x_tmp = x + dh*dxdt stepper_base_type::m_algebra.for_each3( m_x_tmp.m_v , in , dxdt , typename operations_type::template scale_sum2< value_type , time_type >( val1 , dh ) ); // dt * m_dxt = k2 sys( m_x_tmp.m_v , m_dxt.m_v , th ); // m_x_tmp = x + dh*m_dxt stepper_base_type::m_algebra.for_each3( m_x_tmp.m_v , in , m_dxt.m_v , typename operations_type::template scale_sum2< value_type , time_type >( val1 , dh ) ); // dt * m_dxm = k3 sys( m_x_tmp.m_v , m_dxm.m_v , th ); //m_x_tmp = x + dt*m_dxm stepper_base_type::m_algebra.for_each3( m_x_tmp.m_v , in , m_dxm.m_v , typename operations_type::template scale_sum2< value_type , time_type >( val1 , dt ) ); // dt * m_dxh = k4 sys( m_x_tmp.m_v , m_dxh.m_v , t + dt ); //x += dt/6 * ( m_dxdt + m_dxt + val2*m_dxm ) time_type dt6 = dt / static_cast< value_type >( 6 ); time_type dt3 = dt / static_cast< value_type >( 3 ); stepper_base_type::m_algebra.for_each6( out , in , dxdt , m_dxt.m_v , m_dxm.m_v , m_dxh.m_v , typename operations_type::template scale_sum5< value_type , time_type , time_type , time_type , time_type >( 1.0 , dt6 , dt3 , dt3 , dt6 ) ); // x += dt/6 * m_dxdt + dt/3 * m_dxt ) // stepper_base_type::m_algebra.for_each4( out , in , dxdt , m_dxt.m_v , // typename operations_type::template scale_sum3< value_type , time_type , time_type >( 1.0 , dt6 , dt3 ) ); // // x += dt/3 * m_dxm + dt/6 * m_dxh ) // stepper_base_type::m_algebra.for_each4( out , out , m_dxm.m_v , m_dxh.m_v , // typename operations_type::template scale_sum3< value_type , time_type , time_type >( 1.0 , dt3 , dt6 ) ); } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); stepper_base_type::adjust_size( x ); } private: template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_x_tmp , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_dxm , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_dxt , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_dxh , x , typename is_resizeable<deriv_type>::type() ); return resized; } resizer_type m_resizer; wrapped_deriv_type m_dxt; wrapped_deriv_type m_dxm; wrapped_deriv_type m_dxh; wrapped_state_type m_x_tmp; }; /********* DOXYGEN *********/ /** * \class runge_kutta4_classic * \brief The classical Runge-Kutta stepper of fourth order. * * The Runge-Kutta method of fourth order is one standard method for * solving ordinary differential equations and is widely used, see also * <a href="http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods">en.wikipedia.org/wiki/Runge-Kutta_methods</a> * The method is explicit and fulfills the Stepper concept. Step size control * or continuous output are not provided. This class implements the method directly, hence the * generic Runge-Kutta algorithm is not used. * * This class derives from explicit_stepper_base and inherits its interface via * CRTP (current recurring template pattern). For more details see * explicit_stepper_base. * * \tparam State The state type. * \tparam Value The value type. * \tparam Deriv The type representing the time derivative of the state. * \tparam Time The time representing the independent variable - the time. * \tparam Algebra The algebra type. * \tparam Operations The operations type. * \tparam Resizer The resizer policy type. */ /** * \fn runge_kutta4_classic::runge_kutta4_classic( const algebra_type &algebra ) * \brief Constructs the runge_kutta4_classic class. This constructor can be used as a default * constructor if the algebra has a default constructor. * \param algebra A copy of algebra is made and stored inside explicit_stepper_base. */ /** * \fn runge_kutta4_classic::do_step_impl( System system , const StateIn &in , const DerivIn &dxdt , time_type t , StateOut &out , time_type dt ) * \brief This method performs one step. The derivative `dxdt` of `in` at the time `t` is passed to the method. * The result is updated out of place, hence the input is in `in` and the output in `out`. * Access to this step functionality is provided by explicit_stepper_base and * `do_step_impl` should not be called directly. * * \param system The system function to solve, hence the r.h.s. of the ODE. It must fulfill the * Simple System concept. * \param in The state of the ODE which should be solved. in is not modified in this method * \param dxdt The derivative of x at t. * \param t The value of the time, at which the step should be performed. * \param out The result of the step is written in out. * \param dt The step size. */ /** * \fn runge_kutta4_classic::adjust_size( const StateType &x ) * \brief Adjust the size of all temporaries in the stepper manually. * \param x A state from which the size of the temporaries to be resized is deduced. */ } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_STEPPER_RUNGE_KUTTA4_CLASSIC_HPP_INCLUDED odeint/version.hpp 0000644 00000002267 15125237305 0010236 0 ustar 00 /* [auto_generated] boost/numeric/odeint/version.hpp [begin_description] Defines the current version of odeint. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_VERSION_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_VERSION_HPP_INCLUDED #include <string> #include <sstream> #define ODEINT_MAJOR_VERSION 2 #define ODEINT_MINOR_VERSION 2 #define ODEINT_PATCH_LEVEL 0 #define ODEINT_VERSION ( ODEINT_MAJOR_VERSION * 100000 + ODEINT_MINOR_VERSION * 100 + ODEINT_PATCH_LEVEL ) namespace boost { namespace numeric { namespace odeint { namespace version { const int major = ODEINT_MAJOR_VERSION ; const int minor = ODEINT_MINOR_VERSION ; const int patch_level = ODEINT_PATCH_LEVEL ; } inline std::string get_version_string( void ) { std::ostringstream str; str << "v" << version::major << "." << version::minor; if( version::patch_level != 0 ) str << "_" << version::patch_level; return str.str(); } } } } #endif // BOOST_NUMERIC_ODEINT_VERSION_HPP_INCLUDED odeint/iterator/adaptive_iterator.hpp 0000644 00000015331 15125237305 0014104 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/adaptive_iterator.hpp [begin_description] Iterator for iterating throught the solution of an ODE with adaptive step size. The dereferenced types containes also the time. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_ITERATOR_ADAPTIVE_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_ADAPTIVE_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/iterator/impl/adaptive_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the adaptive_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class adaptive_iterator : public adaptive_iterator_impl< adaptive_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef adaptive_iterator< Stepper , System , State , StepperTag > iterator_type; public: adaptive_iterator( Stepper stepper , System sys , State &s , time_type t_start , time_type t_end , time_type dt ) : adaptive_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} adaptive_iterator( Stepper stepper , System sys , State &s ) : adaptive_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s ) {} }; template< class Stepper , class System , class State > adaptive_iterator< Stepper , System , State > make_adaptive_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return adaptive_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ); } template< class Stepper , class System , class State > adaptive_iterator< Stepper , System , State > make_adaptive_iterator_end( Stepper stepper , System system , State &x ) { return adaptive_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< adaptive_iterator< Stepper , System , State > , adaptive_iterator< Stepper , System , State > > make_adaptive_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( adaptive_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ) , adaptive_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class adaptive_iterator * * \brief ODE Iterator with adaptive step size. The value type of this iterator is the state type of the stepper. * * Implements an iterator representing the solution of an ODE from t_start * to t_end evaluated at steps with an adaptive step size dt. * After each iteration the iterator dereferences to the state x at the next * time t+dt where dt is controlled by the stepper. * This iterator can be used with ControlledSteppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_adaptive routine. * * adaptive_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_adaptive_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for adaptive_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The adaptive iterator. */ /** * \fn make_adaptive_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for adaptive_iterator. Constructs a end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. * \returns The adaptive iterator. */ /** * \fn make_adaptive_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function to construct a single pass range of adaptive iterators. A range is here a pair of adaptive_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The adaptive range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_ADAPTIVE_ITERATOR_HPP_INCLUDED odeint/iterator/n_step_time_iterator.hpp 0000644 00000015365 15125237305 0014624 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/n_step_time_iterator.hpp [begin_description] Iterator for iterating through the solution of an ODE with constant step size performing exactly n steps. The dereferenced type contains also the time. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_N_STEP_TIME_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_N_STEP_TIME_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/n_step_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the n_step_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class n_step_time_iterator : public n_step_iterator_impl< n_step_time_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef n_step_time_iterator< Stepper , System , State , StepperTag > iterator_type; public: n_step_time_iterator( Stepper stepper , System sys , State &s , time_type t , time_type dt , size_t num_of_steps ) : n_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s , t , dt , num_of_steps ) {} n_step_time_iterator( Stepper stepper , System sys , State &s ) : n_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s ) {} }; /* make functions */ template< class Stepper , class System , class State > n_step_time_iterator< Stepper , System, State > make_n_step_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) { return n_step_time_iterator< Stepper , System , State >( stepper , system , x , t , dt , num_of_steps ); } template< class Stepper , class System , class State > n_step_time_iterator< Stepper , System , State > make_n_step_time_iterator_end( Stepper stepper , System system , State &x ) { return n_step_time_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< n_step_time_iterator< Stepper , System , State > , n_step_time_iterator< Stepper , System , State > > make_n_step_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) { return std::make_pair( n_step_time_iterator< Stepper , System , State >( stepper , system , x , t , dt , num_of_steps ) , n_step_time_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class n_step_time_iterator * * \brief ODE Iterator with constant step size. The value type of this iterator is a std::pair containing state and time. * * Implements an iterator representing the solution of an ODE starting from t * with n steps and a constant step size dt. * After each iteration the iterator dereferences to a pair of state and time at the next * time t+dt. * This iterator can be used with Steppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_n_steps routine. * * n_step_time_iterator is a model of single-pass iterator. * * The value type of this iterator is pair of state and time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_n_step_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) * * \brief Factory function for n_step_time_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps The number of steps to be executed. * \returns The n-step iterator. */ /** * \fn make_n_step_time_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for n_step_time_iterator. Constructs an end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \returns The const_step_iterator. */ /** * \fn make_n_step_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) * * \brief Factory function to construct a single pass range of n-step iterators. A range is here a pair * of n_step_time_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator store a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps The number of steps to be executed. * \returns The n-step range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_CONST_N_STEP_TIME_ITERATOR_HPP_INCLUDED odeint/iterator/impl/adaptive_iterator_impl.hpp 0000644 00000023455 15125237305 0016074 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/detail/adaptive_iterator_impl.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> namespace boost { namespace numeric { namespace odeint { template< class Iterator , class Stepper , class System , class State , typename Tag , typename StepperTag > class adaptive_iterator_impl; /* * Specilization for controlled steppers */ /** * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper. * * Implements an ODE iterator with adaptive step size control. Uses controlled steppers. adaptive_iterator is a model * of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , typename Tag > class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , controlled_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. */ adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt ) : base_type( stepper , sys , t , dt ) , m_t_end( t_end ) , m_state( &s ) { if( detail::less_with_sign( this->m_t_end , this->m_t , this->m_dt ) ) this->m_at_end = true; } /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration. */ adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment() { if( detail::less_with_sign( this->m_t , this->m_t_end , this->m_dt) ) { if( detail::less_with_sign( this->m_t_end , static_cast<time_type>(this->m_t + this->m_dt) , this->m_dt ) ) { this->m_dt = this->m_t_end - this->m_t; } unwrapped_stepper_type &stepper = this->m_stepper; const size_t max_attempts = 1000; size_t trials = 0; controlled_step_result res = success; do { res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , this->m_dt ); ++trials; } while( ( res == fail ) && ( trials < max_attempts ) ); if( trials == max_attempts ) { BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." )); } } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *this->m_state; } private: time_type m_t_end; state_type* m_state; }; /* * Specilization for dense outputer steppers */ /** * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper. * * Implements an ODE iterator with adaptive step size control. Uses dense-output steppers. adaptive_iterator is a model * of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , typename Tag > class adaptive_iterator_impl< Iterator , Stepper , System , State , Tag , dense_output_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. * \param t The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. */ adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt ) : base_type( stepper , sys , t , dt ) , m_t_end( t_end ) { if( detail::less_eq_with_sign( this->m_t , this->m_t_end , this->m_dt ) ) { unwrapped_stepper_type &st = this->m_stepper; st.initialize( s , this->m_t , this->m_dt ); } else { this->m_at_end = true; } } /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. */ adaptive_iterator_impl( stepper_type stepper , system_type sys , state_type& /* s */ ) : base_type( stepper , sys ) { } protected: friend class boost::iterator_core_access; void increment() { unwrapped_stepper_type &stepper = this->m_stepper; if( detail::less_with_sign( this->m_t , this->m_t_end , stepper.current_time_step() ) ) { if( detail::less_with_sign( this->m_t_end , static_cast<time_type>(this->m_t + stepper.current_time_step()) , stepper.current_time_step() ) ) { // make stpper to end exactly at t_end stepper.initialize( stepper.current_state() , stepper.current_time() , static_cast<time_type>(this->m_t_end-this->m_t) ); } stepper.do_step( this->m_system ); this->m_t = stepper.current_time(); } else { // we have reached t_end this->m_at_end = true; } } public: const state_type& get_state() const { const unwrapped_stepper_type &stepper = this->m_stepper; return stepper.current_state(); } private: time_type m_t_end; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ADAPTIVE_ITERATOR_IMPL_HPP_DEFINED odeint/iterator/impl/times_iterator_impl.hpp 0000644 00000034230 15125237305 0015411 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/detail/times_iterator_impl.hpp [begin_description] tba. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> namespace boost { namespace numeric { namespace odeint { template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag , typename StepperTag > class times_iterator_impl; /* * Specilization for basic steppers */ /** * \brief ODE Iterator with constant step size. * * Implements an ODE iterator with observer calls at predefined times. * Uses controlled steppers. times_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag > class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef TimeIterator time_iterator_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration. * \param t_start Iterator to the begin of a sequence of time values. * \param t_end Iterator to the begin of a sequence of time values. * \param dt The (initial) time step. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_iterator_type t_start , time_iterator_type t_end , time_type dt ) : base_type( stepper , sys , *t_start , dt ) , m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s ) { if( t_start == t_end ) this->m_at_end = true; } /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment() { unwrapped_stepper_type &stepper = this->m_stepper; if( ++m_t_start != m_t_end ) { while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) ) { const time_type current_dt = detail::min_abs( this->m_dt , static_cast<time_type>(*m_t_start) - this->m_t ); stepper.do_step( this->m_system , *( this->m_state ) , this->m_t , current_dt ); this->m_t += current_dt; } } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_iterator_type m_t_start; time_iterator_type m_t_end; state_type* m_state; }; /* * Specilization for controlled steppers */ /** * \brief ODE Iterator with adaptive step size control. The value type of this iterator is the state type of the stepper. * * Implements an ODE iterator with observer calls at predefined times. * Uses controlled steppers. times_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag > class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , controlled_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef TimeIterator time_iterator_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator stores a reference of s and changes its value during the iteration. * \param t_start Iterator to the begin of a sequence of time values. * \param t_end Iterator to the begin of a sequence of time values. * \param dt The (initial) time step. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_iterator_type t_start , time_iterator_type t_end , time_type dt ) : base_type( stepper , sys , *t_start , dt ) , m_t_start( t_start ) , m_t_end( t_end ) , m_state( &s ) { if( t_start == t_end ) this->m_at_end = true; } /** * \brief Constructs an adaptive_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. adaptive_iterator store a reference of s and changes its value during the iteration. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment() { if( ++m_t_start != m_t_end ) { while( detail::less_with_sign( this->m_t , static_cast<time_type>(*m_t_start) , this->m_dt ) ) { if( detail::less_with_sign( static_cast<time_type>(*m_t_start) - this->m_t , this->m_dt , this->m_dt ) ) { // we want to end exactly at the time point time_type current_dt = static_cast<time_type>(*m_t_start) - this->m_t; step_loop( current_dt ); } else { step_loop( this->m_dt ); } } } else { this->m_at_end = true; } } private: void step_loop( time_type &dt ) { unwrapped_stepper_type &stepper = this->m_stepper; const size_t max_attempts = 1000; size_t trials = 0; controlled_step_result res = success; do { res = stepper.try_step( this->m_system , *( this->m_state ) , this->m_t , dt ); ++trials; } while( ( res == fail ) && ( trials < max_attempts ) ); if( trials == max_attempts ) { BOOST_THROW_EXCEPTION( std::overflow_error( "Adaptive iterator : Maximal number of iterations reached. A step size could not be found." ) ); } } public: const state_type& get_state() const { return *m_state; } private: time_iterator_type m_t_start; time_iterator_type m_t_end; state_type* m_state; }; /* * Specilization for dense outputer steppers */ /** * \brief ODE Iterator with step size control and dense output. * Implements an ODE iterator with adaptive step size control. Uses dense-output steppers. * times_iterator is a model of single-pass iterator. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , class TimeIterator , typename Tag > class times_iterator_impl< Iterator , Stepper , System , State , TimeIterator , Tag , dense_output_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef TimeIterator time_iterator_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a times_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. * \param t_start Iterator to the begin of a sequence of time values. * \param t_end Iterator to the begin of a sequence of time values. * \param dt The (initial) time step. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_iterator_type t_start , time_iterator_type t_end , time_type dt ) : base_type( stepper , sys , *t_start , dt ) , m_t_start( t_start ) , m_t_end( t_end ) , m_final_time( *(t_end-1) ) , m_state( &s ) { if( t_start != t_end ) { unwrapped_stepper_type &st = this->m_stepper; st.initialize( *( this->m_state ) , this->m_t , this->m_dt ); } else { this->m_at_end = true; } } /** * \brief Constructs a times_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. */ times_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment() { unwrapped_stepper_type &st = this->m_stepper; if( ++m_t_start != m_t_end ) { this->m_t = static_cast<time_type>(*m_t_start); while( detail::less_with_sign( st.current_time() , this->m_t , this->m_dt ) ) { // make sure we don't go beyond the last point if( detail::less_with_sign( m_final_time-st.current_time() , st.current_time_step() , st.current_time_step() ) ) { st.initialize( st.current_state() , st.current_time() , m_final_time-st.current_time() ); } st.do_step( this->m_system ); } st.calc_state( this->m_t , *( this->m_state ) ); } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_iterator_type m_t_start; time_iterator_type m_t_end; time_type m_final_time; state_type* m_state; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_TIMES_ITERATOR_IMPL_HPP_DEFINED odeint/iterator/impl/n_step_iterator_impl.hpp 0000644 00000021543 15125237305 0015563 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/detail/n_step_iterator_impl.hpp [begin_description] tba. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_DETAIL_N_STEP_ITERATOR_IMPL_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_N_STEP_ITERATOR_IMPL_HPP_DEFINED #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> namespace boost { namespace numeric { namespace odeint { template< class Iterator , class Stepper , class System , class State , typename Tag , class StepperTag > class n_step_iterator_impl; /* * Specilization for steppers and error steppers */ /** * \brief ODE Iterator performing exactly n steps with constant step size. The value type of this iterator is the state type of the stepper. * * Implements an ODE iterator solving the ODE with constant step size. Uses steppers fulfilling the Stepper concept. * n_step_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , typename Tag > class n_step_iterator_impl< Iterator , Stepper , System , State , Tag , stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a n_step_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps the number of steps to be executed. */ n_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type dt , size_t num_of_steps ) : base_type( stepper , sys , t , dt ) , m_t_start( t ) , m_state( &s ) , m_steps(num_of_steps) , m_step( 0 ) { } /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. */ n_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment() { if( this->m_step < this->m_steps ) { unwrapped_stepper_type &stepper = this->m_stepper; stepper.do_step( this->m_system , *this->m_state , this->m_t , this->m_dt ); // use integer to compute current time to reduce roundoff errors this->m_step++; this->m_t = this->m_t_start + static_cast< typename unit_value_type<time_type>::type >(this->m_step)*this->m_dt; } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_type m_t_start; time_type m_t_end; state_type* m_state; size_t m_steps; size_t m_step; }; /* * Specilization for dense output stepper */ /** * \brief ODE Iterator with step-size control and dense output. * * Implements an ODE iterator solving the ODE with constant steps. Uses dense-output steppers. * n_step_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , typename Tag > class n_step_iterator_impl< Iterator , Stepper , System , State , Tag , dense_output_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps the number of steps to be executed. */ n_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type dt , size_t num_of_steps ) : base_type( stepper , sys , t , dt ) , m_t_start( t ) , m_state( &s ) , m_steps( num_of_steps ) , m_step( 0 ) { unwrapped_stepper_type &st = this->m_stepper; st.initialize( * ( this->m_state ) , this->m_t , this->m_dt ); } /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. */ n_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment( void ) { if( this->m_step < this->m_steps ) { unwrapped_stepper_type &stepper = this->m_stepper; // use integer to compute current time to reduce roundoff errors this->m_step++; this->m_t = this->m_t_start + static_cast< typename unit_value_type<time_type>::type >(this->m_step)*this->m_dt; while( detail::less_with_sign( stepper.current_time() , this->m_t , stepper.current_time_step() ) ) { stepper.do_step( this->m_system ); } stepper.calc_state( this->m_t , *( this->m_state ) ); } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_type m_t_start; time_type m_t_end; state_type* m_state; size_t m_steps; size_t m_step; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_N_STEP_ITERATOR_IMPL_HPP_DEFINED odeint/iterator/impl/const_step_iterator_impl.hpp 0000644 00000021255 15125237305 0016454 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/detail/const_step_iterator_impl.hpp [begin_description] tba. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ITERATOR_DETAIL_CONST_STEP_ITERATOR_IMPL_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_CONST_STEP_ITERATOR_IMPL_HPP_DEFINED #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> namespace boost { namespace numeric { namespace odeint { template< class Iterator , class Stepper , class System , class State , typename Tag , class StepperTag > class const_step_iterator_impl; /* * Specilization for steppers and error steppers */ template< class Iterator , class Stepper , class System , class State , typename Tag > class const_step_iterator_impl< Iterator , Stepper , System , State , Tag , stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. */ const_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt ) : base_type( stepper , sys , t , dt ) , m_t_start( t ) , m_t_end( t_end ) , m_state( &s ) , m_step( 0 ) { if( detail::less_with_sign( this->m_t_end , this->m_t , this->m_dt ) ) this->m_at_end = true; } /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. */ const_step_iterator_impl( stepper_type stepper , system_type sys , state_type& /* s */ ) : base_type( stepper , sys ) { } protected: friend class boost::iterator_core_access; void increment() { if( detail::less_eq_with_sign( static_cast<time_type>(this->m_t+this->m_dt) , this->m_t_end , this->m_dt ) ) { unwrapped_stepper_type &stepper = this->m_stepper; stepper.do_step( this->m_system , *this->m_state , this->m_t , this->m_dt ); // use integer to compute current time to reduce roundoff errors this->m_step++; this->m_t = this->m_t_start + static_cast< typename unit_value_type<time_type>::type >(this->m_step)*this->m_dt; } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_type m_t_start; time_type m_t_end; state_type* m_state; size_t m_step; }; /* * Specilization for dense output stepper */ /** * \brief ODE Iterator with constant step size. The value type of this iterator is the state type of the stepper. * * Implements an ODE iterator solving the ODE with constant steps. Uses dense-output steppers. * const_step_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. */ template< class Iterator , class Stepper , class System , class State , typename Tag > class const_step_iterator_impl< Iterator , Stepper , System , State , Tag , dense_output_stepper_tag > : public detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename traits::time_type< stepper_type >::type time_type; typedef typename traits::value_type< stepper_type >::type ode_value_type; #ifndef DOXYGEN_SKIP typedef detail::ode_iterator_base< Iterator , Stepper , System , State , Tag > base_type; #endif public: /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the begin iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. */ const_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s , time_type t , time_type t_end , time_type dt ) : base_type( stepper , sys , t , dt ) , m_t_start( t ) , m_t_end( t_end ) , m_state( &s ) , m_step( 0 ) { if( detail::less_eq_with_sign( this->m_t , this->m_t_end , this->m_dt ) ) { unwrapped_stepper_type &st = this->m_stepper; st.initialize( * ( this->m_state ) , this->m_t , this->m_dt ); } else { this->m_at_end = true; } } /** * \brief Constructs a const_step_iterator. This constructor should be used to construct the end iterator. * * \param stepper The stepper to use during the iteration. * \param sys The system function (ODE) to solve. * \param s The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. */ const_step_iterator_impl( stepper_type stepper , system_type sys , state_type &s ) : base_type( stepper , sys ) , m_state( &s ) { } protected: friend class boost::iterator_core_access; void increment( void ) { if( detail::less_eq_with_sign( static_cast<time_type>(this->m_t+this->m_dt) , this->m_t_end , this->m_dt ) ) { unwrapped_stepper_type &stepper = this->m_stepper; // use integer to compute current time to reduce roundoff errors this->m_step++; this->m_t = this->m_t_start + static_cast< typename unit_value_type<time_type>::type >(this->m_step)*this->m_dt; while( detail::less_with_sign( stepper.current_time() , this->m_t , stepper.current_time_step() ) ) { stepper.do_step( this->m_system ); } stepper.calc_state( this->m_t , *( this->m_state ) ); } else { this->m_at_end = true; } } public: const state_type& get_state() const { return *m_state; } private: time_type m_t_start; time_type m_t_end; state_type* m_state; size_t m_step; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_CONST_STEP_ITERATOR_IMPL_HPP_DEFINED odeint/iterator/const_step_time_iterator.hpp 0000644 00000016144 15125237305 0015511 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/const_step_time_iterator.hpp [begin_description] Iterator for iterating throught the solution of an ODE with constant step size. The dereferences types containes also the time. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ITERATOR_CONST_STEP_TIME_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_CONST_STEP_TIME_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/const_step_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the const_step_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class const_step_time_iterator : public const_step_iterator_impl< const_step_time_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef const_step_time_iterator< Stepper , System , State , StepperTag > iterator_type; public: const_step_time_iterator( Stepper stepper , System sys , State &s , time_type t_start , time_type t_end , time_type dt ) : const_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} const_step_time_iterator( Stepper stepper , System sys , State &s ) : const_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s ) {} }; template< class Stepper , class System , class State > const_step_time_iterator< Stepper , System , State > make_const_step_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return const_step_time_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ); } template< class Stepper , class System , class State > const_step_time_iterator< Stepper , System , State > make_const_step_time_iterator_end( Stepper stepper , System system , State &x ) { return const_step_time_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< const_step_time_iterator< Stepper , System , State > , const_step_time_iterator< Stepper , System , State > > make_const_step_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( const_step_time_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ) , const_step_time_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class const_step_time_iterator * * \brief ODE Iterator with constant step size. The value type of this iterator is a std::pair containing state and time. * * Implements an iterator representing the solution of an ODE from t_start * to t_end evaluated at steps with constant step size dt. * After each iteration the iterator dereferences to a pair containing * state and time at the next time point t+dt.. * This iterator can be used with Steppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_const routine. * * const_step_time_iterator is a model of single-pass iterator. * * The value type of this iterator is a pair with the state type and time type of the stepper. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_const_step_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for const_step_time_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_time_iterator stores a reference of s and changes its value during the iteration. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The const step time iterator. */ /** * \fn make_const_step_time_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for const_step_time_iterator. Constructs a end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_time_iterator store a reference of s and changes its value during the iteration. * \returns The const step time iterator. */ /** * \fn make_const_step_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt) * * \brief Factory function to construct a single pass range of const_step_time_iterator. A range is here a pair of const_step_time_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_time_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The const step time range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_CONST_STEP_TIME_ITERATOR_HPP_INCLUDED odeint/iterator/const_step_iterator.hpp 0000644 00000016042 15125237305 0014470 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/const_step_iterator.hpp [begin_description] Iterator for iterating through the solution of an ODE with constant step size. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ITERATOR_CONST_STEP_ODE_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_CONST_STEP_ODE_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/const_step_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the const_step_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class const_step_iterator : public const_step_iterator_impl< const_step_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef const_step_iterator< Stepper , System , State , StepperTag > iterator_type; public: const_step_iterator( Stepper stepper , System sys , State &s , time_type t_start , time_type t_end , time_type dt ) : const_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} const_step_iterator( Stepper stepper , System sys , State &s ) : const_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s ) {} }; /* make functions */ template< class Stepper , class System , class State > const_step_iterator< Stepper , System, State > make_const_step_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return const_step_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ); } template< class Stepper , class System , class State > const_step_iterator< Stepper , System , State > make_const_step_iterator_end( Stepper stepper , System system , State &x ) { return const_step_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< const_step_iterator< Stepper , System , State > , const_step_iterator< Stepper , System , State > > make_const_step_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( const_step_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ) , const_step_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class const_step_iterator * * \brief ODE Iterator with constant step size. The value type of this iterator is the state type of the stepper. * * Implements an iterator representing the solution of an ODE from t_start * to t_end evaluated at steps with constant step size dt. * After each iteration the iterator dereferences to the state x at the next * time t+dt. * This iterator can be used with Steppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_const routine. * * const_step_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_const_step_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for const_step_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The const step iterator. */ /** * \fn make_const_step_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for const_step_iterator. Constructs a end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \returns The const_step_iterator. */ /** * \fn make_const_step_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function to construct a single pass range of const step iterators. A range is here a pair * of const_step_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator store a reference of s and changes its value during the iteration. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The const step range. */ } // namespace odeint } // namespace numeric } // namespace boost //#include <boost/numeric/odeint/iterator/impl/const_step_iterator_dense_output_impl.hpp> #endif // BOOST_NUMERIC_ODEINT_ITERATOR_CONST_STEP_ODE_ITERATOR_HPP_INCLUDED odeint/iterator/times_iterator.hpp 0000644 00000017122 15125237305 0013430 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/times_iterator.hpp [begin_description] Iterator for iterating through the solution of an ODE with oscillator calls at times from a given sequence. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_TIMES_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_TIMES_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/times_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the times_iterator_impl with the right tags */ template< class Stepper , class System , class State , class TimeIterator #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class times_iterator : public times_iterator_impl< times_iterator< Stepper , System , State , TimeIterator , StepperTag > , Stepper , System , State , TimeIterator , detail::ode_state_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef times_iterator< Stepper , System , State , TimeIterator , StepperTag > iterator_type; public: times_iterator( Stepper stepper , System sys , State &s , TimeIterator t_start , TimeIterator t_end , time_type dt ) : times_iterator_impl< iterator_type , Stepper , System , State , TimeIterator, detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} times_iterator( Stepper stepper , System sys , State &s ) : times_iterator_impl< iterator_type , Stepper , System , State , TimeIterator , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s ) {} }; /* make functions */ template< class Stepper , class System , class State , class TimeIterator > times_iterator< Stepper , System, State , TimeIterator > make_times_iterator_begin( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) { return times_iterator< Stepper , System , State , TimeIterator >( stepper , system , x , t_start , t_end , dt ); } // ToDo: requires to specifically provide the TimeIterator template parameter, can this be improved? template< class TimeIterator , class Stepper , class System , class State > times_iterator< Stepper , System , State , TimeIterator > make_times_iterator_end( Stepper stepper , System system , State &x ) //TimeIterator t_end ) { return times_iterator< Stepper , System , State , TimeIterator >( stepper , system , x ); } template< class Stepper , class System , class State , class TimeIterator > std::pair< times_iterator< Stepper , System , State , TimeIterator > , times_iterator< Stepper , System , State , TimeIterator > > make_times_range( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( times_iterator< Stepper , System , State , TimeIterator >( stepper , system , x , t_start , t_end , dt ) , times_iterator< Stepper , System , State , TimeIterator >( stepper , system , x ) ); } /** * \class times_iterator * * \brief ODE Iterator with given evaluation points. The value type of this iterator is the state type of the stepper. * * Implements an iterator representing the solution of an ODE from *t_start * to *t_end evaluated at time points given by the sequence t_start to t_end. * t_start and t_end are iterators representing a sequence of time points * where the solution of the ODE should be evaluated. * After each iteration the iterator dereferences to the state x at the next * time *t_start++ until t_end is reached. * This iterator can be used with Steppers, ControlledSteppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_times routine. * * times_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. * \tparam TimeIterator The iterator type for the sequence of time points. */ /** * \fn make_times_iterator_begin( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for times_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t_start Begin iterator of the sequence of evaluation time points. * \param t_end End iterator of the sequence of evaluation time points. * \param dt The initial time step. * \returns The times iterator. */ /** * \fn make_times_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for times_iterator. Constructs an end iterator. * * \tparam TimesIterator The iterator type of the time sequence, must be specifically provided. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \returns The times iterator. * * This function needs the TimeIterator type specifically defined as a * template parameter. */ /** * \fn make_times_range( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function to construct a single pass range of times iterators. A range is here a pair * of times_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator store a reference of s and changes its value during the iteration. * \param t_start Begin iterator of the sequence of evaluation time points. * \param t_end End iterator of the sequence of evaluation time points. * \param dt The initial time step. * \returns The times iterator range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_TIMES_ITERATOR_HPP_INCLUDED odeint/iterator/adaptive_time_iterator.hpp 0000644 00000016011 15125237305 0015116 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/adaptive_time_iterator.hpp [begin_description] Iterator for iterating throught the solution of an ODE with adaptive step size. The dereferenced types containes also the time. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_ITERATOR_ADAPTIVE_TIME_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_ADAPTIVE_TIME_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/iterator/impl/adaptive_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the adaptive_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class adaptive_time_iterator : public adaptive_iterator_impl< adaptive_time_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef adaptive_time_iterator< Stepper , System , State , StepperTag > iterator_type; public: adaptive_time_iterator( Stepper stepper , System sys , State &s , time_type t_start , time_type t_end , time_type dt ) : adaptive_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} adaptive_time_iterator( Stepper stepper , System sys , State &s ) : adaptive_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s ) {} }; template< class Stepper , class System , class State > adaptive_time_iterator< Stepper , System , State > make_adaptive_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return adaptive_time_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ); } template< class Stepper , class System , class State > adaptive_time_iterator< Stepper , System , State > make_adaptive_time_iterator_end( Stepper stepper , System system , State &x ) { return adaptive_time_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< adaptive_time_iterator< Stepper , System , State > , adaptive_time_iterator< Stepper , System , State > > make_adaptive_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( adaptive_time_iterator< Stepper , System , State >( stepper , system , x , t_start , t_end , dt ) , adaptive_time_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class adaptive_time_iterator * * \brief ODE Iterator with adaptive step size. The value type of this iterator is a std::pair containing state and time. * * Implements an iterator representing the solution of an ODE from t_start * to t_end evaluated at steps with an adaptive step size dt. * After each iteration the iterator dereferences to a pair containing state * and time at the next time point t+dt where dt is controlled by the stepper. * This iterator can be used with ControlledSteppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_adaptive routine. * * adaptive_iterator is a model of single-pass iterator. * * The value type of this iterator is a std::pair of state and time of the stepper. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_adaptive_time_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for adaptive_time_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. adaptive_time_iterator stores a reference of s and changes its value during the iteration. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The adaptive time iterator. */ /** * \fn make_adaptive_time_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for adaptive_time_iterator. Constructs a end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. adaptive_time_iterator stores a reference of s and changes its value during the iteration. * \returns The adaptive time iterator. */ /** * \fn make_adaptive_time_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t_start , typename traits::time_type< Stepper >::type t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function to construct a single pass range of adaptive time iterators. A range is here a pair of adaptive_time_iterators. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. adaptive_time_iterator stores a reference of s and changes its value during the iteration. * \param t_start The initial time. * \param t_end The end time, at which the iteration should stop. * \param dt The initial time step. * \returns The adaptive time range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_ADAPTIVE_TIME_ITERATOR_HPP_INCLUDED odeint/iterator/n_step_iterator.hpp 0000644 00000015133 15125237305 0013577 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/n_step_iterator.hpp [begin_description] Iterator for iterating through the solution of an ODE with constant step size performing exactly n steps. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_N_STEP_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_N_STEP_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/n_step_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the n_step_iterator_impl with the right tags */ template< class Stepper , class System , class State #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class n_step_iterator : public n_step_iterator_impl< n_step_iterator< Stepper , System , State , StepperTag > , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef n_step_iterator< Stepper , System , State , StepperTag > iterator_type; public: n_step_iterator( Stepper stepper , System sys , State &s , time_type t , time_type dt , size_t num_of_steps ) : n_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s , t , dt , num_of_steps ) {} n_step_iterator( Stepper stepper , System sys , State &s ) : n_step_iterator_impl< iterator_type , Stepper , System , State , detail::ode_state_iterator_tag , StepperTag >( stepper , sys , s ) {} }; /* make functions */ template< class Stepper , class System , class State > n_step_iterator< Stepper , System, State > make_n_step_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) { return n_step_iterator< Stepper , System , State >( stepper , system , x , t , dt , num_of_steps ); } template< class Stepper , class System , class State > n_step_iterator< Stepper , System , State > make_n_step_iterator_end( Stepper stepper , System system , State &x ) { return n_step_iterator< Stepper , System , State >( stepper , system , x ); } template< class Stepper , class System , class State > std::pair< n_step_iterator< Stepper , System , State > , n_step_iterator< Stepper , System , State > > make_n_step_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) { return std::make_pair( n_step_iterator< Stepper , System , State >( stepper , system , x , t , dt , num_of_steps ) , n_step_iterator< Stepper , System , State >( stepper , system , x ) ); } /** * \class n_step_iterator * * \brief ODE Iterator with constant step size. The value type of this iterator is the state type of the stepper. * * Implements an iterator representing the solution of an ODE starting from t * with n steps and a constant step size dt. * After each iteration the iterator dereferences to the state x at the next * time t+dt. * This iterator can be used with Steppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_n_steps routine. * * n_step_iterator is a model of single-pass iterator. * * The value type of this iterator is the state type of the stepper. Hence one can only access the state and not the current time. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. */ /** * \fn make_n_step_iterator_begin( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , size_t num_of_steps ) * * \brief Factory function for n_step_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps The number of steps to be executed. * \returns The n-step iterator. */ /** * \fn make_n_step_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for n_step_iterator. Constructs an end iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \returns The const_step_iterator. */ /** * \fn make_n_step_range( Stepper stepper , System system , State &x , typename traits::time_type< Stepper >::type t , typename traits::time_type< Stepper >::type dt , , size_t num_of_steps ) * * \brief Factory function to construct a single pass range of n-step iterators. A range is here a pair * of n_step_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator store a reference of s and changes its value during the iteration. * \param t The initial time. * \param dt The initial time step. * \param num_of_steps The number of steps to be executed. * \returns The n-step range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_CONST_N_STEP_ITERATOR_HPP_INCLUDED odeint/iterator/detail/ode_iterator_base.hpp 0000644 00000013530 15125237305 0015311 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp [begin_description] Base class for const_step_iterator and adaptive_iterator. [end_description] Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_ITERATOR_DETAIL_ODE_ITERATOR_BASE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ODE_ITERATOR_BASE_HPP_INCLUDED #include <boost/iterator/iterator_facade.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { struct ode_state_iterator_tag {}; struct ode_state_time_iterator_tag {}; template< class Iterator , class Stepper , class System , class State , typename Tag > class ode_iterator_base; /* Specialization for the state iterator that has only state_type as its value_type */ template< class Iterator , class Stepper , class System , class State > class ode_iterator_base< Iterator , Stepper , System , State , ode_state_iterator_tag > : public boost::iterator_facade < Iterator , typename traits::state_type< Stepper >::type const , boost::single_pass_traversal_tag > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename unwrapped_stepper_type::time_type time_type; typedef typename unwrapped_stepper_type::value_type ode_value_type; public: ode_iterator_base( stepper_type stepper , system_type sys , time_type t , time_type dt ) : m_stepper( stepper ) , m_system( sys ) , m_t( t ) , m_dt( dt ) , m_at_end( false ) { } ode_iterator_base( stepper_type stepper , system_type sys ) : m_stepper( stepper ) , m_system( sys ) , m_t() , m_dt() , m_at_end( true ) { } // this function is only for testing bool same( const ode_iterator_base &iter ) const { return ( //( static_cast<Iterator>(*this).get_state() == // static_cast<Iterator>(iter).get_state ) && ( m_t == iter.m_t ) && ( m_dt == iter.m_dt ) && ( m_at_end == iter.m_at_end ) ); } protected: friend class boost::iterator_core_access; bool equal( ode_iterator_base const& other ) const { if( m_at_end == other.m_at_end ) { return true; } else { return false; } } const state_type& dereference() const { return static_cast<const Iterator*>(this)->get_state(); } protected: stepper_type m_stepper; system_type m_system; time_type m_t; time_type m_dt; bool m_at_end; }; /* Specialization for the state-time iterator that has pair<state_type,time_type> as its value_type */ template< class Iterator , class Stepper , class System , class State > class ode_iterator_base< Iterator , Stepper , System , State , ode_state_time_iterator_tag > : public boost::iterator_facade < Iterator , std::pair< const State , const typename traits::time_type< Stepper >::type > , boost::single_pass_traversal_tag , std::pair< const State& , const typename traits::time_type< Stepper >::type& > > { private: typedef Stepper stepper_type; typedef System system_type; typedef typename boost::numeric::odeint::unwrap_reference< stepper_type >::type unwrapped_stepper_type; typedef State state_type; typedef typename unwrapped_stepper_type::time_type time_type; typedef typename unwrapped_stepper_type::value_type ode_value_type; public: ode_iterator_base( stepper_type stepper , system_type sys , time_type t , time_type dt ) : m_stepper( stepper ) , m_system( sys ) , m_t( t ) , m_dt( dt ) , m_at_end( false ) { } ode_iterator_base( stepper_type stepper , system_type sys ) : m_stepper( stepper ) , m_system( sys ) , m_at_end( true ) { } bool same( ode_iterator_base const& iter ) { return ( //( static_cast<Iterator>(*this).get_state() == // static_cast<Iterator>(iter).get_state ) && ( m_t == iter.m_t ) && ( m_dt == iter.m_dt ) && ( m_at_end == iter.m_at_end ) ); } protected: friend class boost::iterator_core_access; bool equal( ode_iterator_base const& other ) const { if( m_at_end == other.m_at_end ) { return true; } else { return false; } } std::pair< const state_type& , const time_type& > dereference() const { return std::pair< const state_type & , const time_type & >( static_cast<const Iterator*>(this)->get_state() , m_t ); } stepper_type m_stepper; system_type m_system; time_type m_t; time_type m_dt; bool m_at_end; }; } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_DETAIL_ODE_ITERATOR_BASE_HPP_INCLUDED odeint/iterator/integrate/integrate_n_steps.hpp 0000644 00000011120 15125237305 0016065 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_n_steps.hpp [begin_description] Integration of n steps with constant time size. Adaptive and dense-output methods are fully supported. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/integrate/null_observer.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_n_steps.hpp> namespace boost { namespace numeric { namespace odeint { /* * Integrates n steps * * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class Time , class Observer> Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , observer , stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer > Time integrate_n_steps( Stepper stepper , System system , const State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , observer , stepper_category() ); } /** * \brief The same function as above, but without observer calls. */ template< class Stepper , class System , class State , class Time > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps ) { return integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , null_observer() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time > Time integrate_n_steps( Stepper stepper , System system , const State &start_state , Time start_time , Time dt , size_t num_of_steps ) { return integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , null_observer() ); } /************* DOXYGEN *************/ /** * \fn Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) * \brief Integrates the ODE with constant step size. * * This function is similar to integrate_const. The observer is called at * equidistant time intervals t0 + n*dt. * If the Stepper is a normal stepper without step size control, dt is also * used for the numerical scheme. If a ControlledStepper is provided, the * algorithm might reduce the step size to meet the error bounds, but it is * ensured that the observer is always called at equidistant time points * t0 + n*dt. If a DenseOutputStepper is used, the step size also may vary * and the dense output is used to call the observer at equidistant time * points. The final integration time is always t0 + num_of_steps*dt. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param num_of_steps Number of steps to be performed * \param observer Function/Functor called at equidistant time intervals. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED odeint/iterator/integrate/observer_collection.hpp 0000644 00000002537 15125237305 0016426 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/observer_collection.hpp [begin_description] Collection of observers, which are all called during the evolution of the ODE. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED #include <vector> #include <boost/function.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Time > class observer_collection { public: typedef boost::function< void( const State& , const Time& ) > observer_type; typedef std::vector< observer_type > collection_type; void operator()( const State& x , Time t ) { for( size_t i=0 ; i<m_observers.size() ; ++i ) m_observers[i]( x , t ); } collection_type& observers( void ) { return m_observers; } const collection_type& observers( void ) const { return m_observers; } private: collection_type m_observers; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED odeint/iterator/integrate/integrate_times.hpp 0000644 00000011476 15125237305 0015551 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_times.hpp [begin_description] Integration of ODEs with observation at user defined points [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/range.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/integrate/null_observer.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_times.hpp> namespace boost { namespace numeric { namespace odeint { /* * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_times( stepper , system , start_state , times_start , times_end , dt , observer , stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , const State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_times( stepper , system , start_state , times_start , times_end , dt , observer , stepper_category() ); } /** * \brief The same function as above, but without observer calls. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , const TimeRange × , Time dt , Observer observer ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , const State &start_state , const TimeRange × , Time dt , Observer observer ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer ); } /********* DOXYGEN ***********/ /** * \fn size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) * \brief Integrates the ODE with observer calls at given time points. * * Integrates the ODE given by system using the given stepper. This function * does observer calls at the subsequent time points given by the range * times_start, times_end. If the stepper has not step size control, the * step size might be reduced occasionally to ensure observer calls exactly * at the time points from the given sequence. If the stepper is a * ControlledStepper, the step size is adjusted to meet the error bounds, * but also might be reduced occasionally to ensure correct observer calls. * If a DenseOutputStepper is provided, the dense output functionality is * used to call the observer at the given times. The end time of the * integration is always *(end_time-1). * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param times_start Iterator to the start time * \param times_end Iterator to the end time * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer Function/Functor called at equidistant time intervals. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED odeint/iterator/integrate/null_observer.hpp 0000644 00000001475 15125237305 0015245 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/null_observer.hpp [begin_description] null_observer [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { struct null_observer { template< class State , class Time > void operator()( const State& /* x */ , Time /* t */ ) const { } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED odeint/iterator/integrate/detail/integrate_n_steps.hpp 0000644 00000007464 15125237305 0017347 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp [begin_description] integrate steps implementation [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_adaptive.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/functors.hpp> #include <boost/numeric/odeint/iterator/n_step_time_iterator.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer , controlled_stepper_tag ); /* basic version */ template< class Stepper , class System , class State , class Time , class Observer> Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , stepper_tag ) { // ToDo: is there a better way to extract the final time? Time t = start_time; // Assignment is only here to avoid warnings. boost::for_each( make_n_step_time_range( stepper , system , start_state , start_time , dt , num_of_steps ) , obs_caller_time< Observer , Time >( t , observer ) ); return t; } /* controlled version */ template< class Stepper , class System , class State , class Time , class Observer> Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; Time time = start_time; Time time_step = dt; for( size_t step = 0; step < num_of_steps ; ++step ) { obs( start_state , time ); detail::integrate_adaptive( stepper , system , start_state , time , static_cast<Time>(time+time_step) , dt , null_observer() , controlled_stepper_tag() ); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here time = start_time + static_cast< typename unit_value_type<Time>::type >(step+1) * time_step; } obs( start_state , time ); return time; } /* dense output version */ template< class Stepper , class System , class State , class Time , class Observer> Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , dense_output_stepper_tag ) { // ToDo: is there a better way to extract the final time? Time t = start_time; // Assignment is only here to avoid warnings. boost::for_each( make_n_step_time_range( stepper , system , start_state , start_time , dt , num_of_steps ) , obs_caller_time< Observer , Time >( t , observer ) ); return t; } } } } } #endif /* BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED */ odeint/iterator/integrate/detail/functors.hpp 0000644 00000003260 15125237305 0015463 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/functors.hpp [begin_description] some functors for the iterator based integrate routines [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED #include <utility> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Observer > struct obs_caller { size_t &m_n; Observer m_obs; obs_caller( size_t &m , Observer &obs ) : m_n(m) , m_obs( obs ) {} template< class State , class Time > void operator()( std::pair< const State & , const Time & > x ) { typedef typename odeint::unwrap_reference< Observer >::type observer_type; observer_type &obs = m_obs; obs( x.first , x.second ); m_n++; } }; template< class Observer , class Time > struct obs_caller_time { Time &m_t; Observer m_obs; obs_caller_time( Time &t , Observer &obs ) : m_t(t) , m_obs( obs ) {} template< class State > void operator()( std::pair< const State & , const Time & > x ) { typedef typename odeint::unwrap_reference< Observer >::type observer_type; observer_type &obs = m_obs; obs( x.first , x.second ); m_t = x.second; } }; } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED odeint/iterator/integrate/detail/integrate_times.hpp 0000644 00000003742 15125237305 0017010 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_times.hpp [begin_description] Default integrate times implementation. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED #include <stdexcept> #include <boost/config.hpp> #include <boost/range/algorithm/for_each.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> #include <boost/numeric/odeint/iterator/times_time_iterator.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/functors.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { /* * integrate_times for all steppers */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepperTag > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator start_time , TimeIterator end_time , Time dt , Observer observer , StepperTag ) { size_t obs_calls = 0; boost::for_each( make_times_time_range( stepper , system , start_state , start_time , end_time , dt ) , // should we use traits<Stepper>::state_type here instead of State? NO! obs_caller< Observer >( obs_calls , observer ) ); // step integration steps gives step+1 observer calls return obs_calls-1; } } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/iterator/integrate/detail/integrate_adaptive.hpp 0000644 00000007556 15125237305 0017473 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp [begin_description] Default Integrate adaptive implementation. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED #include <stdexcept> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_const.hpp> #include <boost/numeric/odeint/iterator/adaptive_time_iterator.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/functors.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer> size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ); /* * integrate_adaptive for simple stepper is basically an integrate_const + some last step */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ) { size_t steps = detail::integrate_const( stepper , system , start_state , start_time , end_time , dt , observer , stepper_tag() ); typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time end = start_time + dt*steps; if( less_with_sign( end , end_time , dt ) ) { //make a last step to end exactly at end_time st.do_step( system , start_state , end , end_time - end ); steps++; obs( start_state , end_time ); } return steps; } /* * classical integrate adaptive */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer , controlled_stepper_tag ) { size_t obs_calls = 0; boost::for_each( make_adaptive_time_range( stepper , system , start_state , start_time , end_time , dt ) , obs_caller< Observer >( obs_calls , observer ) ); return obs_calls-1; } /* * integrate adaptive for dense output steppers * * step size control is used if the stepper supports it */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , dense_output_stepper_tag ) { size_t obs_calls = 0; boost::for_each( make_adaptive_time_range( stepper , system , start_state , start_time , end_time , dt ) , obs_caller< Observer >( obs_calls , observer ) ); return obs_calls-1; } } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/iterator/integrate/detail/integrate_const.hpp 0000644 00000007347 15125237305 0017022 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_const.hpp [begin_description] integrate const implementation [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED #include <boost/range/algorithm/for_each.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/iterator/const_step_time_iterator.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_adaptive.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/functors.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer , controlled_stepper_tag ); template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ) { size_t obs_calls = 0; boost::for_each( make_const_step_time_range( stepper , system , start_state , start_time , end_time , dt ) , // should we use traits<Stepper>::state_type here instead of State? NO! obs_caller< Observer >( obs_calls , observer ) ); // step integration steps gives step+1 observer calls return obs_calls-1; } template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; Time time = start_time; const Time time_step = dt; int step = 0; while( less_eq_with_sign( static_cast<Time>(time+time_step) , end_time , dt ) ) { obs( start_state , time ); detail::integrate_adaptive( stepper , system , start_state , time , time+time_step , dt , null_observer() , controlled_stepper_tag() ); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here ++step; time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * time_step; } obs( start_state , time ); return step; } template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , dense_output_stepper_tag ) { size_t obs_calls = 0; boost::for_each( make_const_step_time_range( stepper , system , start_state , start_time , end_time , dt ) , obs_caller< Observer >( obs_calls , observer ) ); return obs_calls-1; } } } } } #endif odeint/iterator/integrate/integrate_adaptive.hpp 0000644 00000010760 15125237305 0016220 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_adaptive.hpp [begin_description] Adaptive integration of ODEs. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/integrate/null_observer.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_adaptive.hpp> namespace boost { namespace numeric { namespace odeint { /* * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); /* * Suggestion for a new extendable version: * * integrator_adaptive< Stepper , System, State , Time , Observer , typename Stepper::stepper_category > integrator; * return integrator.run( stepper , system , start_state , start_time , end_time , dt , observer ); */ } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } /** * \brief integrate_adaptive without an observer. */ template< class Stepper , class System , class State , class Time > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time > size_t integrate_adaptive( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /************* DOXYGEN ************/ /** * \fn integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) * \brief Integrates the ODE with adaptive step size. * * This function integrates the ODE given by system with the given stepper. * The observer is called after each step. If the stepper has no error * control, the step size remains constant and the observer is called at * equidistant time points t0+n*dt. If the stepper is a ControlledStepper, * the step size is adjusted and the observer is called in non-equidistant * intervals. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param end_time The final integration time tend. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer Function/Functor called at equidistant time intervals. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/iterator/integrate/integrate.hpp 0000644 00000007536 15125237305 0014352 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate.hpp [begin_description] Convenience methods which choose the stepper for the current ODE. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED #include <boost/utility/enable_if.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp> #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/iterator/integrate/null_observer.hpp> #include <boost/numeric/odeint/iterator/integrate/integrate_adaptive.hpp> // for has_value_type trait #include <boost/numeric/odeint/algebra/detail/extract_value_type.hpp> namespace boost { namespace numeric { namespace odeint { /* * ToDo : * * determine type of dxdt for units * */ template< class System , class State , class Time , class Observer > typename boost::enable_if< typename has_value_type<State>::type , size_t >::type integrate( System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef controlled_runge_kutta< runge_kutta_dopri5< State , typename State::value_type , State , Time > > stepper_type; return integrate_adaptive( stepper_type() , system , start_state , start_time , end_time , dt , observer ); } /* * the two overloads are needed in order to solve the forwarding problem */ template< class System , class State , class Time > size_t integrate( System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate( system , start_state , start_time , end_time , dt , null_observer() ); } /** * \fn integrate( System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) * \brief Integrates the ODE. * * Integrates the ODE given by system from start_time to end_time starting * with start_state as initial condition and dt as initial time step. * This function uses a dense output dopri5 stepper and performs an adaptive * integration with step size control, thus dt changes during the integration. * This method uses standard error bounds of 1E-6. * After each step, the observer is called. * * \param system The system function to solve, hence the r.h.s. of the * ordinary differential equation. * \param start_state The initial state. * \param start_time Start time of the integration. * \param end_time End time of the integration. * \param dt Initial step size, will be adjusted during the integration. * \param observer Observer that will be called after each time step. * \return The number of steps performed. */ /** * \fn integrate( System system , State &start_state , Time start_time , Time end_time , Time dt ) * \brief Integrates the ODE without observer calls. * * Integrates the ODE given by system from start_time to end_time starting * with start_state as initial condition and dt as initial time step. * This function uses a dense output dopri5 stepper and performs an adaptive * integration with step size control, thus dt changes during the integration. * This method uses standard error bounds of 1E-6. * No observer is called. * * \param system The system function to solve, hence the r.h.s. of the * ordinary differential equation. * \param start_state The initial state. * \param start_time Start time of the integration. * \param end_time End time of the integration. * \param dt Initial step size, will be adjusted during the integration. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED odeint/iterator/integrate/integrate_const.hpp 0000644 00000012476 15125237305 0015557 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_const.hpp [begin_description] Constant integration of ODEs, meaning that the state of the ODE is observed on constant time intervals. The routines makes full use of adaptive and dense-output methods. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/integrate/null_observer.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_const.hpp> #include <boost/numeric/odeint/iterator/integrate/detail/integrate_adaptive.hpp> namespace boost { namespace numeric { namespace odeint { /* * Integrates with constant time step dt. */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; // we want to get as fast as possible to the end if( boost::is_same< null_observer , Observer >::value ) { return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } else { return detail::integrate_const( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; // we want to get as fast as possible to the end if( boost::is_same< null_observer , Observer >::value ) { return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } else { return detail::integrate_const( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } } /** * \brief integrate_const without observer calls */ template< class Stepper , class System , class State , class Time > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_const( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time > size_t integrate_const( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_const( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /********* DOXYGEN *********/ /** * \fn integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) * \brief Integrates the ODE with constant step size. * * Integrates the ODE defined by system using the given stepper. * This method ensures that the observer is called at constant intervals dt. * If the Stepper is a normal stepper without step size control, dt is also * used for the numerical scheme. If a ControlledStepper is provided, the * algorithm might reduce the step size to meet the error bounds, but it is * ensured that the observer is always called at equidistant time points * t0 + n*dt. If a DenseOutputStepper is used, the step size also may vary * and the dense output is used to call the observer at equidistant time * points. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param end_time The final integration time tend. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer Function/Functor called at equidistant time intervals. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED odeint/iterator/times_time_iterator.hpp 0000644 00000017433 15125237305 0014453 0 ustar 00 /* [auto_generated] boost/numeric/odeint/iterator/times_time_iterator.hpp [begin_description] Iterator for iterating through the solution of an ODE with oscillator calls at times from a given sequence. The dereferenced type contains also the time. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_ITERATOR_TIMES_TIME_ITERATOR_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ITERATOR_TIMES_TIME_ITERATOR_HPP_INCLUDED #include <boost/numeric/odeint/util/stepper_traits.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/iterator/detail/ode_iterator_base.hpp> #include <boost/numeric/odeint/iterator/impl/times_iterator_impl.hpp> namespace boost { namespace numeric { namespace odeint { /* use the times_iterator_impl with the right tags */ template< class Stepper , class System , class State , class TimeIterator #ifndef DOXYGEN_SKIP , class StepperTag = typename base_tag< typename traits::stepper_category< Stepper >::type >::type #endif > class times_time_iterator : public times_iterator_impl< times_time_iterator< Stepper , System , State , TimeIterator , StepperTag > , Stepper , System , State , TimeIterator , detail::ode_state_time_iterator_tag , StepperTag > { typedef typename traits::time_type< Stepper >::type time_type; typedef times_time_iterator< Stepper , System , State , TimeIterator , StepperTag > iterator_type; public: times_time_iterator( Stepper stepper , System sys , State &s , TimeIterator t_start , TimeIterator t_end , time_type dt ) : times_iterator_impl< iterator_type , Stepper , System , State , TimeIterator, detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s , t_start , t_end , dt ) {} times_time_iterator( Stepper stepper , System sys , State &s ) : times_iterator_impl< iterator_type , Stepper , System , State , TimeIterator , detail::ode_state_time_iterator_tag , StepperTag >( stepper , sys , s ) {} }; /* make functions */ template< class Stepper , class System , class State , class TimeIterator > times_time_iterator< Stepper , System, State , TimeIterator > make_times_time_iterator_begin( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) { return times_time_iterator< Stepper , System , State , TimeIterator >( stepper , system , x , t_start , t_end , dt ); } // ToDo: requires to specifically provide the TimeIterator template parameter, can this be improved? template< class TimeIterator , class Stepper , class System , class State > times_time_iterator< Stepper , System , State , TimeIterator > make_times_time_iterator_end( Stepper stepper , System system , State &x ) //TimeIterator t_end ) { return times_time_iterator< Stepper , System , State , TimeIterator >( stepper , system , x ); } template< class Stepper , class System , class State , class TimeIterator > std::pair< times_time_iterator< Stepper , System , State , TimeIterator > , times_time_iterator< Stepper , System , State , TimeIterator > > make_times_time_range( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) { return std::make_pair( times_time_iterator< Stepper , System , State , TimeIterator >( stepper , system , x , t_start , t_end , dt ) , times_time_iterator< Stepper , System , State , TimeIterator >( stepper , system , x ) ); } /** * \class times_time_iterator * * \brief ODE Iterator with given evaluation points. The value type of this iterator is a std::pair containing state and time. * * Implements an iterator representing the solution of an ODE from *t_start * to *t_end evaluated at time points given by the sequence t_start to t_end. * t_start and t_end are iterators representing a sequence of time points * where the solution of the ODE should be evaluated. * After each iteration the iterator dereferences to a pair with the state * and the time at the next evaluation point *t_start++ until t_end is reached. * This iterator can be used with Steppers, ControlledSteppers and * DenseOutputSteppers and it always makes use of the all the given steppers * capabilities. A for_each over such an iterator range behaves similar to * the integrate_times routine. * * times_time_iterator is a model of single-pass iterator. * * The value type of this iterator is a pair of state and time type. * * \tparam Stepper The stepper type which should be used during the iteration. * \tparam System The type of the system function (ODE) which should be solved. * \tparam State The state type of the ODE. * \tparam TimeIterator The iterator type for the sequence of time points. */ /** * \fn make_times_time_iterator_begin( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function for times_time_iterator. Constructs a begin iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \param t_start Begin iterator of the sequence of evaluation time points. * \param t_end End iterator of the sequence of evaluation time points. * \param dt The initial time step. * \returns The times_time iterator. */ /** * \fn make_times_time_iterator_end( Stepper stepper , System system , State &x ) * \brief Factory function for times_time_iterator. Constructs an end iterator. * * \tparam TimesIterator The iterator type of the time sequence, must be specifically provided. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator stores a reference of s and changes its value during the iteration. * \returns The times_time iterator. * * This function needs the TimeIterator type specifically defined as a * template parameter. */ /** * \fn make_times_time_range( Stepper stepper , System system , State &x , TimeIterator t_start , TimeIterator t_end , typename traits::time_type< Stepper >::type dt ) * * \brief Factory function to construct a single pass range of times_time iterators. A range is here a pair * of times_iterator. * * \param stepper The stepper to use during the iteration. * \param system The system function (ODE) to solve. * \param x The initial state. const_step_iterator store a reference of s and changes its value during the iteration. * \param t_start Begin iterator of the sequence of evaluation time points. * \param t_end End iterator of the sequence of evaluation time points. * \param dt The initial time step. * \returns The times_time iterator range. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ITERATOR_TIMES_TIME_ITERATOR_HPP_INCLUDED odeint/algebra/range_algebra.hpp 0000644 00000020246 15125237305 0012714 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/range_algebra.hpp [begin_description] Default algebra, which works with the most state types, like vector< double >, boost::array< double >, boost::range. Internally is uses boost::range to obtain the begin and end iterator of the according sequence. [end_description] Copyright 2010-2013 Karsten Ahnert Copyright 2010-2013 Mario Mulansky 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_ODEINT_ALGEBRA_RANGE_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_RANGE_ALGEBRA_HPP_INCLUDED #include <boost/range.hpp> #include <boost/mpl/size_t.hpp> #include <boost/numeric/odeint/algebra/detail/macros.hpp> #include <boost/numeric/odeint/algebra/detail/for_each.hpp> #include <boost/numeric/odeint/algebra/detail/norm_inf.hpp> #include <boost/numeric/odeint/algebra/norm_result_type.hpp> namespace boost { namespace numeric { namespace odeint { struct range_algebra { template< class S1 , class Op > static void for_each1( S1 &s1 , Op op ) { detail::for_each1( boost::begin( s1 ) , boost::end( s1 ) , op ); } template< class S1 , class S2 , class Op > static void for_each2( S1 &s1 , S2 &s2 , Op op ) { detail::for_each2( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , op ); } template< class S1 , class S2 , class S3 , class Op > static void for_each3( S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { detail::for_each3( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class Op > static void for_each4( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { detail::for_each4( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each5( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { detail::for_each5( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each6( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { detail::for_each6( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class Op > static void for_each7( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { detail::for_each7( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class Op > static void for_each8( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { detail::for_each8( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class Op > static void for_each9( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { detail::for_each9( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class Op > static void for_each10( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { detail::for_each10( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each11( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { detail::for_each11( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , boost::begin( s11 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each12( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { detail::for_each12( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , boost::begin( s11 ) , boost::begin( s12 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each13( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { detail::for_each13( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , boost::begin( s11 ) , boost::begin( s12 ) , boost::begin( s13 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each14( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { detail::for_each14( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , boost::begin( s11 ) , boost::begin( s12 ) , boost::begin( s13 ) , boost::begin( s14 ) , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class S15 , class Op > static void for_each15( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , S15 &s15 , Op op ) { detail::for_each15( boost::begin( s1 ) , boost::end( s1 ) , boost::begin( s2 ) , boost::begin( s3 ) , boost::begin( s4 ) , boost::begin( s5 ) , boost::begin( s6 ) , boost::begin( s7 ) , boost::begin( s8 ) , boost::begin( s9 ) , boost::begin( s10 ) , boost::begin( s11 ) , boost::begin( s12 ) , boost::begin( s13 ) , boost::begin( s14 ) , boost::begin( s15 ) , op ); } template< typename S > static typename norm_result_type<S>::type norm_inf( const S &s ) { return detail::norm_inf( boost::begin( s ) , boost::end( s ) , static_cast< typename norm_result_type<S>::type >( 0 ) ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_RANGE_ALGEBRA_HPP_INCLUDED odeint/algebra/fusion_algebra.hpp 0000644 00000026236 15125237305 0013130 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/fusion_algebra.hpp [begin_description] Algebra for boost::fusion sequences. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2013 Mario Mulansky 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_ODEINT_ALGEBRA_FUSION_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_FUSION_ALGEBRA_HPP_INCLUDED #include <algorithm> #include <boost/numeric/odeint/config.hpp> #include <boost/fusion/container/vector.hpp> #include <boost/fusion/algorithm/iteration/for_each.hpp> #include <boost/fusion/view/zip_view.hpp> #include <boost/fusion/functional/generation/make_fused.hpp> #include <boost/fusion/algorithm/iteration/accumulate.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Value > struct fusion_maximum { template< class Fac1 , class Fac2 > Value operator()( Fac1 t1 , const Fac2 t2 ) const { using std::abs; Value a1 = abs( get_unit_value( t1 ) ) , a2 = abs( get_unit_value( t2 ) ); return ( a1 < a2 ) ? a2 : a1 ; } typedef Value result_type; }; } /* specialize this if the fundamental numeric type in your fusion sequence is * anything else but double (most likely not) */ template< typename Sequence > struct fusion_traits { typedef double value_type; }; struct fusion_algebra { template< class S1 , class Op > static void for_each1( S1 &s1 , Op op ) { boost::fusion::for_each( s1 , op ); }; template< class S1 , class S2 , class Op > static void for_each2( S1 &s1 , S2 &s2 , Op op ) { typedef boost::fusion::vector< S1& , S2& > Sequences; Sequences sequences( s1 , s2 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class Op > static void for_each3( S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { typedef boost::fusion::vector< S1& , S2& , S3& > Sequences; Sequences sequences( s1 , s2 , s3 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class Op > static void for_each4( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { typedef boost::fusion::vector< S1& , S2& , S3& , S4& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each5( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each6( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class Op > static void for_each7( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class Op > static void for_each8( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 8 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class Op > static void for_each9( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 9 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class Op > static void for_each10( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 10 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each11( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 11 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); BOOST_STATIC_ASSERT_MSG( BOOST_RESULT_OF_NUM_ARGS >= 11 , "Macro Parameter BOOST_RESULT_OF_NUM_ARGS to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& , S11& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each12( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 12 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); BOOST_STATIC_ASSERT_MSG( BOOST_RESULT_OF_NUM_ARGS >= 12 , "Macro Parameter BOOST_RESULT_OF_NUM_ARGS to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& , S11& , S12& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each13( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 13 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); BOOST_STATIC_ASSERT_MSG( BOOST_RESULT_OF_NUM_ARGS >= 13 , "Macro Parameter BOOST_RESULT_OF_NUM_ARGS to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& , S11& , S12& , S13& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each14( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 14 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); BOOST_STATIC_ASSERT_MSG( BOOST_RESULT_OF_NUM_ARGS >= 14 , "Macro Parameter BOOST_RESULT_OF_NUM_ARGS to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& , S11& , S12& , S13& , S14& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 , s14 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class S15 , class Op > static void for_each15( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , S15 &s15 , Op op ) { BOOST_STATIC_ASSERT_MSG( BOOST_FUSION_INVOKE_MAX_ARITY >= 15 , "Macro Parameter BOOST_FUSION_INVOKE_MAX_ARITY to small!" ); BOOST_STATIC_ASSERT_MSG( BOOST_RESULT_OF_NUM_ARGS >= 15 , "Macro Parameter BOOST_RESULT_OF_NUM_ARGS to small!" ); typedef boost::fusion::vector< S1& , S2& , S3& , S4& , S5& , S6& , S7& , S8& , S9& , S10& , S11& , S12& , S13& , S14& , S15& > Sequences; Sequences sequences( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 , s14 , s15 ); boost::fusion::for_each( boost::fusion::zip_view< Sequences >( sequences ) , boost::fusion::make_fused( op ) ); } template< class S > static typename fusion_traits< S >::value_type norm_inf( const S &s ) { typedef typename fusion_traits< S >::value_type value_type; return boost::fusion::accumulate( s , static_cast<value_type>(0) , detail::fusion_maximum<value_type>() ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_FUSION_ALGEBRA_HPP_INCLUDED odeint/algebra/default_operations.hpp 0000644 00000056362 15125237305 0014042 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/default_operations.hpp [begin_description] Default operations. They work with the default numerical types, like float, double, complex< double> ... [end_description] Copyright 2010-2012 Karsten Ahnert Copyright 2010-2013 Mario Mulansky 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_ODEINT_ALGEBRA_DEFAULT_OPERATIONS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_DEFAULT_OPERATIONS_HPP_INCLUDED #include <algorithm> #include <boost/config.hpp> #include <boost/array.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> namespace boost { namespace numeric { namespace odeint { /* * Notes: * * * the results structs are needed in order to work with fusion_algebra */ struct default_operations { template< class Fac1 = double > struct scale { const Fac1 m_alpha1; scale( Fac1 alpha1 ) : m_alpha1( alpha1 ) { } template< class T1 > void operator()( T1 &t1 ) const { t1 *= m_alpha1; } typedef void result_type; }; template< class Fac1 = double > struct scale_sum1 { const Fac1 m_alpha1; scale_sum1( Fac1 alpha1 ) : m_alpha1( alpha1 ) { } template< class T1 , class T2 > void operator()( T1 &t1 , const T2 &t2 ) const { t1 = m_alpha1 * t2; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 > struct scale_sum2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum2( Fac1 alpha1 , Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class T1 , class T2 , class T3 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3) const { t1 = m_alpha1 * t2 + m_alpha2 * t3; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 > struct scale_sum3 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; scale_sum3( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) { } template< class T1 , class T2 , class T3 , class T4 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 > struct scale_sum4 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; scale_sum4( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 > struct scale_sum5 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; scale_sum5( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 > struct scale_sum6 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; scale_sum6( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ){ } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 ,const T7 &t7) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 > struct scale_sum7 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; scale_sum7( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 > struct scale_sum8 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; scale_sum8( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 > struct scale_sum9 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; scale_sum9( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 , class Fac10 = Fac9 > struct scale_sum10 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; const Fac10 m_alpha10; scale_sum10( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 , Fac10 alpha10 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) , m_alpha10( alpha10 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 , const T11 &t11 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10 + m_alpha10 * t11; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 , class Fac10 = Fac9 , class Fac11 = Fac10 > struct scale_sum11 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; const Fac10 m_alpha10; const Fac11 m_alpha11; scale_sum11( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 , Fac10 alpha10 , Fac11 alpha11 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) , m_alpha10( alpha10 ) , m_alpha11( alpha11 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 , const T11 &t11 , const T12 &t12 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10 + m_alpha10 * t11 + m_alpha11 * t12; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 , class Fac10 = Fac9 , class Fac11 = Fac10 , class Fac12 = Fac11 > struct scale_sum12 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; const Fac10 m_alpha10; const Fac11 m_alpha11; const Fac12 m_alpha12; scale_sum12( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 , Fac10 alpha10 , Fac11 alpha11 , Fac12 alpha12 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) , m_alpha10( alpha10 ) , m_alpha11( alpha11 ) , m_alpha12( alpha12 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 , const T11 &t11 , const T12 &t12 , const T13 &t13 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10 + m_alpha10 * t11 + m_alpha11 * t12 + m_alpha12 * t13; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 , class Fac10 = Fac9 , class Fac11 = Fac10 , class Fac12 = Fac11 , class Fac13 = Fac12 > struct scale_sum13 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; const Fac10 m_alpha10; const Fac11 m_alpha11; const Fac12 m_alpha12; const Fac13 m_alpha13; scale_sum13( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 , Fac10 alpha10 , Fac11 alpha11 , Fac12 alpha12 , Fac13 alpha13 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) , m_alpha10( alpha10 ) , m_alpha11( alpha11 ) , m_alpha12( alpha12 ) , m_alpha13( alpha13 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 , const T11 &t11 , const T12 &t12 , const T13 &t13 , const T14 &t14 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10 + m_alpha10 * t11 + m_alpha11 * t12 + m_alpha12 * t13 + m_alpha13 * t14; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 , class Fac8 = Fac7 , class Fac9 = Fac8 , class Fac10 = Fac9 , class Fac11 = Fac10 , class Fac12 = Fac11 , class Fac13 = Fac12 , class Fac14 = Fac13 > struct scale_sum14 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; const Fac8 m_alpha8; const Fac9 m_alpha9; const Fac10 m_alpha10; const Fac11 m_alpha11; const Fac12 m_alpha12; const Fac13 m_alpha13; const Fac14 m_alpha14; scale_sum14( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 , Fac6 alpha6 , Fac7 alpha7 , Fac8 alpha8 , Fac9 alpha9 , Fac10 alpha10 , Fac11 alpha11 , Fac12 alpha12 , Fac13 alpha13 , Fac14 alpha14 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) , m_alpha8( alpha8 ) , m_alpha9( alpha9 ) , m_alpha10( alpha10 ) , m_alpha11( alpha11 ) , m_alpha12( alpha12 ) , m_alpha13( alpha13 ) , m_alpha14( alpha14 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 , const T7 &t7 , const T8 &t8 , const T9 &t9 , const T10 &t10 , const T11 &t11 , const T12 &t12 , const T13 &t13 , const T14 &t14 , const T15 &t15 ) const { t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6 + m_alpha6 * t7 + m_alpha7 * t8 + m_alpha8 * t9 + m_alpha9 * t10 + m_alpha10 * t11 + m_alpha11 * t12 + m_alpha12 * t13 + m_alpha13 * t14 + m_alpha14 * t15; } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 > struct scale_sum_swap2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum_swap2( Fac1 alpha1 , Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class T1 , class T2 , class T3 > void operator()( T1 &t1 , T2 &t2 , const T3 &t3) const { const T1 tmp( t1 ); t1 = m_alpha1 * t2 + m_alpha2 * t3; t2 = tmp; } typedef void result_type; }; /* * for usage in for_each2 * * Works with boost::units by eliminating the unit */ template< class Fac1 = double > struct rel_error { const Fac1 m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt; rel_error( Fac1 eps_abs , Fac1 eps_rel , Fac1 a_x , Fac1 a_dxdt ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) , m_a_x( a_x ) , m_a_dxdt( a_dxdt ) { } template< class T1 , class T2 , class T3 > void operator()( T3 &t3 , const T1 &t1 , const T2 &t2 ) const { using std::abs; set_unit_value( t3 , abs( get_unit_value( t3 ) ) / ( m_eps_abs + m_eps_rel * ( m_a_x * abs( get_unit_value( t1 ) ) + m_a_dxdt * abs( get_unit_value( t2 ) ) ) ) ); } typedef void result_type; }; /* * for usage in for_each3 * * used in the controller for the rosenbrock4 method * * Works with boost::units by eliminating the unit */ template< class Fac1 = double > struct default_rel_error { const Fac1 m_eps_abs , m_eps_rel ; default_rel_error( Fac1 eps_abs , Fac1 eps_rel ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) { } /* * xerr = xerr / ( eps_abs + eps_rel * max( x , x_old ) ) */ template< class T1 , class T2 , class T3 > void operator()( T3 &t3 , const T1 &t1 , const T2 &t2 ) const { BOOST_USING_STD_MAX(); using std::abs; Fac1 x1 = abs( get_unit_value( t1 ) ) , x2 = abs( get_unit_value( t2 ) ); set_unit_value( t3 , abs( get_unit_value( t3 ) ) / ( m_eps_abs + m_eps_rel * max BOOST_PREVENT_MACRO_SUBSTITUTION ( x1 , x2 ) ) ); } typedef void result_type; }; /* * for usage in reduce */ template< class Value > struct maximum { template< class Fac1 , class Fac2 > Value operator()( Fac1 t1 , const Fac2 t2 ) const { using std::abs; Value a1 = abs( get_unit_value( t1 ) ) , a2 = abs( get_unit_value( t2 ) ); return ( a1 < a2 ) ? a2 : a1 ; } typedef Value result_type; }; template< class Fac1 = double > struct rel_error_max { const Fac1 m_eps_abs , m_eps_rel; rel_error_max( Fac1 eps_abs , Fac1 eps_rel ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) { } template< class Res , class T1 , class T2 , class T3 > Res operator()( Res r , const T1 &x_old , const T2 &x , const T3 &x_err ) { BOOST_USING_STD_MAX(); using std::abs; Res tmp = abs( get_unit_value( x_err ) ) / ( m_eps_abs + m_eps_rel * max BOOST_PREVENT_MACRO_SUBSTITUTION ( abs( x_old ) , abs( x ) ) ); return max BOOST_PREVENT_MACRO_SUBSTITUTION ( r , tmp ); } }; template< class Fac1 = double > struct rel_error_max2 { const Fac1 m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt; rel_error_max2( Fac1 eps_abs , Fac1 eps_rel , Fac1 a_x , Fac1 a_dxdt ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) , m_a_x( a_x ) , m_a_dxdt( a_dxdt ) { } template< class Res , class T1 , class T2 , class T3 , class T4 > Res operator()( Res r , const T1 &x_old , const T2 &/*x*/ , const T3 &dxdt_old , const T4 &x_err ) { BOOST_USING_STD_MAX(); using std::abs; Res tmp = abs( get_unit_value( x_err ) ) / ( m_eps_abs + m_eps_rel * ( m_a_x * abs( get_unit_value( x_old ) ) + m_a_dxdt * abs( get_unit_value( dxdt_old ) ) ) ); return max BOOST_PREVENT_MACRO_SUBSTITUTION ( r , tmp ); } }; template< class Fac1 = double > struct rel_error_l2 { const Fac1 m_eps_abs , m_eps_rel; rel_error_l2( Fac1 eps_abs , Fac1 eps_rel ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) { } template< class Res , class T1 , class T2 , class T3 > Res operator()( Res r , const T1 &x_old , const T2 &x , const T3 &x_err ) { BOOST_USING_STD_MAX(); using std::abs; Res tmp = abs( get_unit_value( x_err ) ) / ( m_eps_abs + m_eps_rel * max BOOST_PREVENT_MACRO_SUBSTITUTION ( abs( x_old ) , abs( x ) ) ); return r + tmp * tmp; } }; template< class Fac1 = double > struct rel_error_l2_2 { const Fac1 m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt; rel_error_l2_2( Fac1 eps_abs , Fac1 eps_rel , Fac1 a_x , Fac1 a_dxdt ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) , m_a_x( a_x ) , m_a_dxdt( a_dxdt ) { } template< class Res , class T1 , class T2 , class T3 , class T4 > Res operator()( Res r , const T1 &x_old , const T2 &/*x*/ , const T3 &dxdt_old , const T4 &x_err ) { using std::abs; Res tmp = abs( get_unit_value( x_err ) ) / ( m_eps_abs + m_eps_rel * ( m_a_x * abs( get_unit_value( x_old ) ) + m_a_dxdt * abs( get_unit_value( dxdt_old ) ) ) ); return r + tmp * tmp; } }; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_DEFAULT_OPERATIONS_HPP_INCLUDED odeint/algebra/algebra_dispatcher.hpp 0000644 00000004765 15125237305 0013756 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/algebra_dispatcher.hpp [begin_description] Algebra dispatcher to automatically chose suitable algebra. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_ALGEBRA_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_ALGEBRA_DISPATCHER_HPP_INCLUDED #include <boost/numeric/odeint/config.hpp> #include <complex> #include <boost/type_traits/is_floating_point.hpp> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/odeint/algebra/range_algebra.hpp> #include <boost/numeric/odeint/algebra/array_algebra.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> #include <boost/array.hpp> namespace boost { namespace numeric { namespace odeint { template< class StateType , class Enabler = void > struct algebra_dispatcher_sfinae { // range_algebra is the standard algebra typedef range_algebra algebra_type; }; template< class StateType > struct algebra_dispatcher : algebra_dispatcher_sfinae< StateType > { }; // specialize for array template< class T , size_t N > struct algebra_dispatcher< boost::array< T , N > > { typedef array_algebra algebra_type; }; //specialize for some integral types template< typename T > struct algebra_dispatcher_sfinae< T , typename boost::enable_if< typename boost::is_floating_point< T >::type >::type > { typedef vector_space_algebra algebra_type; }; template< typename T > struct algebra_dispatcher< std::complex<T> > { typedef vector_space_algebra algebra_type; }; ///* think about that again.... // specialize for ublas vector and matrix types template< class T , class A > struct algebra_dispatcher< boost::numeric::ublas::vector< T , A > > { typedef vector_space_algebra algebra_type; }; template< class T , class L , class A > struct algebra_dispatcher< boost::numeric::ublas::matrix< T , L , A > > { typedef vector_space_algebra algebra_type; }; //*/ } } } #ifdef BOOST_NUMERIC_ODEINT_CXX11 // c++11 mode: specialization for std::array if available #include <array> namespace boost { namespace numeric { namespace odeint { // specialize for std::array template< class T , size_t N > struct algebra_dispatcher< std::array< T , N > > { typedef array_algebra algebra_type; }; } } } #endif #endif odeint/algebra/multi_array_algebra.hpp 0000644 00000016353 15125237305 0014154 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/multi_array_algebra.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_ALGEBRA_MULTI_ARRAY_ALGEBRA_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ALGEBRA_MULTI_ARRAY_ALGEBRA_HPP_DEFINED #include <boost/multi_array.hpp> #include <boost/numeric/odeint/algebra/detail/for_each.hpp> #include <boost/numeric/odeint/algebra/detail/norm_inf.hpp> #include <boost/numeric/odeint/algebra/norm_result_type.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { // not ready struct multi_array_algebra { template< class S1 , class Op > static void for_each1( S1 &s1 , Op op ) { detail::for_each1( s1.data() , s1.data() + s1.num_elements() , op ); } template< class S1 , class S2 , class Op > static void for_each2( S1 &s1 , S2 &s2 , Op op ) { detail::for_each2( s1.data() , s1.data() + s1.num_elements() , s2.data() , op ); } template< class S1 , class S2 , class S3 , class Op > static void for_each3( S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { detail::for_each3( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class Op > static void for_each4( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { detail::for_each4( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each5( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { detail::for_each5( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each6( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { detail::for_each6( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class Op > static void for_each7( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { detail::for_each7( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class Op > static void for_each8( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { detail::for_each8( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class Op > static void for_each9( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { detail::for_each9( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class Op > static void for_each10( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { detail::for_each10( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each11( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { detail::for_each11( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each12( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { detail::for_each12( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , s12.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each13( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { detail::for_each13( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , s12.data() , s13.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each14( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { detail::for_each14( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , s12.data() , s13.data() , s14.data() , op ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class S15 , class Op > static void for_each15( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , S15 &s15 , Op op ) { detail::for_each15( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , s12.data() , s13.data() , s14.data() , s15.data() , op ); } template< typename S > static typename norm_result_type<S>::type norm_inf( const S &s ) { return detail::norm_inf( s.data() , s.data() + s.num_elements() , static_cast< typename norm_result_type<S>::type >( 0 ) ); } }; template< class T , size_t N > struct algebra_dispatcher< boost::multi_array< T , N > > { typedef multi_array_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_MULTI_ARRAY_ALGEBRA_HPP_DEFINED odeint/algebra/norm_result_type.hpp 0000644 00000001465 15125237305 0013557 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/norm_result_type.hpp [begin_description] Calculates the type of the norm_inf operation for container types [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_NORM_RESULT_TYPE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_NORM_RESULT_TYPE_HPP_INCLUDED #include <boost/numeric/odeint/algebra/detail/extract_value_type.hpp> namespace boost { namespace numeric { namespace odeint { template< typename S , typename Enabler = void > struct norm_result_type { typedef typename detail::extract_value_type< S >::type type; }; } } } #endif odeint/algebra/detail/macros.hpp 0000644 00000002156 15125237305 0012671 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/detail/macros.hpp [begin_description] Some macros for type checking. [end_description] Copyright 2010-2012 Karsten Ahnert Copyright 2010 Mario Mulansky 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_ODEINT_ALGEBRA_DETAIL_MACROS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_MACROS_HPP_INCLUDED //type traits aren't working with nvcc #ifndef __CUDACC__ #include <boost/type_traits.hpp> #include <boost/static_assert.hpp> #define BOOST_ODEINT_CHECK_CONTAINER_TYPE( Type1 , Type2 ) \ BOOST_STATIC_ASSERT(( boost::is_same< typename boost::remove_const< Type1 >::type , Type2 >::value )) #else //empty macro for nvcc #define BOOST_ODEINT_CHECK_CONTAINER_TYPE( Type1 , Type2 ) #endif // __CUDACC__ /* #define BOOST_ODEINT_CHECK_OPERATION_ARITY( Operation , Arity ) \ BOOST_STATIC_ASSERT(( boost::function_traits< Operation >::arity == Arity )) */ #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_MACROS_HPP_INCLUDED odeint/algebra/detail/extract_value_type.hpp 0000644 00000002516 15125237305 0015314 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/detail/extract_value_type.hpp [begin_description] Extract true value type from complex types (eg. std::complex) [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_DETAIL_EXTRACT_VALUE_TYPE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_EXTRACT_VALUE_TYPE_HPP_INCLUDED #include <boost/utility.hpp> #include <boost/mpl/has_xxx.hpp> BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) namespace boost { namespace numeric { namespace odeint { namespace detail { template< typename S , typename Enabler = void > struct extract_value_type {}; // as long as value_types are defined we go down the value_type chain // e.g. returning S::value_type::value_type::value_type template< typename S > struct extract_value_type<S , typename boost::disable_if< has_value_type<S> >::type > { // no value_type defined, return S typedef S type; }; template< typename S > struct extract_value_type< S , typename boost::enable_if< has_value_type<S> >::type > { // go down the value_type typedef typename extract_value_type< typename S::value_type >::type type; }; } } } } #endif odeint/algebra/detail/for_each.hpp 0000644 00000022517 15125237305 0013156 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/detail/for_each.hpp [begin_description] Default for_each implementations. [end_description] Copyright 2010-2012 Karsten Ahnert Copyright 2011 Mario Mulansky 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_ODEINT_ALGEBRA_DETAIL_FOR_EACH_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_FOR_EACH_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Iterator1 , class Operation > inline void for_each1( Iterator1 first1 , Iterator1 last1 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ ); } template< class Iterator1 , class Iterator2 , class Operation > inline void for_each2( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Operation > inline void for_each3( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Operation > inline void for_each4( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Operation > inline void for_each5( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Operation > inline void for_each6( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Operation > inline void for_each7( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Operation > inline void for_each8( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Operation > inline void for_each9( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Operation > inline void for_each10( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Iterator11 , class Operation > inline void for_each11( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Iterator11 first11 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ , *first11++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Iterator11 , class Iterator12 , class Operation > inline void for_each12( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Iterator11 first11 , Iterator12 first12 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ , *first11++ , *first12++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Iterator11 , class Iterator12 , class Iterator13 , class Operation > inline void for_each13( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Iterator11 first11 , Iterator12 first12 , Iterator13 first13 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ , *first11++ , *first12++ , *first13++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Iterator11 , class Iterator12 , class Iterator13 , class Iterator14 , class Operation > inline void for_each14( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Iterator11 first11 , Iterator12 first12 , Iterator13 first13 , Iterator14 first14 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ , *first11++ , *first12++ , *first13++ , *first14++ ); } template< class Iterator1 , class Iterator2 , class Iterator3 , class Iterator4 , class Iterator5 , class Iterator6 , class Iterator7 , class Iterator8 , class Iterator9 , class Iterator10 , class Iterator11 , class Iterator12 , class Iterator13 , class Iterator14 , class Iterator15 , class Operation > inline void for_each15( Iterator1 first1 , Iterator1 last1 , Iterator2 first2 , Iterator3 first3, Iterator4 first4, Iterator5 first5, Iterator6 first6 , Iterator7 first7 , Iterator8 first8 , Iterator9 first9 , Iterator10 first10 , Iterator11 first11 , Iterator12 first12 , Iterator13 first13 , Iterator14 first14 , Iterator15 first15 , Operation op ) { for( ; first1 != last1 ; ) op( *first1++ , *first2++ , *first3++ , *first4++ , *first5++ , *first6++ , *first7++ , *first8++ , *first9++ , *first10++ , *first11++ , *first12++ , *first13++ , *first14++ , *first15++ ); } } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_FOR_EACH_HPP_INCLUDED odeint/algebra/detail/norm_inf.hpp 0000644 00000001711 15125237305 0013210 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/detail/norm_inf.hpp [begin_description] Default reduce implementation. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_DETAIL_NORM_INF_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_NORM_INF_HPP_INCLUDED #include <cmath> namespace boost { namespace numeric { namespace odeint { namespace detail { template< typename Value , class Iterator1 > inline Value norm_inf( Iterator1 first1 , Iterator1 last1 , Value init ) { using std::max; using std::abs; for( ; first1 != last1 ; ) init = max( init , abs( *first1++ ) ); return init; } } // detail } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_DETAIL_NORM_INF_HPP_INCLUDED odeint/algebra/array_algebra.hpp 0000644 00000025136 15125237305 0012741 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/array_algebra.hpp [begin_description] Algebra for Arrays. Highly specialized for odeint. Const arguments are introduce to work with odeint. The Array algebra can be used for Array structures with two template parameters: Array<T, N> [end_description] Copyright 2011-2013 Mario Mulansky Copyright 2011-2012 Karsten Ahnert 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_ODEINT_ALGEBRA_ARRAY_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_ARRAY_ALGEBRA_HPP_INCLUDED #include <algorithm> #include <boost/array.hpp> #include <boost/numeric/odeint/algebra/norm_result_type.hpp> namespace boost { namespace numeric { namespace odeint { struct array_algebra { //template< typename T , size_t dim , class Op > template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each1( Array< T, dim > &s1, Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each2( Array< T, dim > &s1, const Array< T, dim > &s2, Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each3( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] ); } /* different const signature - required for the scale_sum_swap2 operation */ template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each3( Array< T , dim > &s1 , Array< T , dim > &s2 , const Array< T , dim > &s3 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each4( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each5( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each6( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each7( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each8( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each9( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each10( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each11( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , const Array< T , dim > &s11 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] , s11[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each12( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , const Array< T , dim > &s11 , const Array< T , dim > &s12 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] , s11[i] , s12[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each13( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , const Array< T , dim > &s11 , const Array< T , dim > &s12 , const Array< T , dim > &s13 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] , s11[i] , s12[i] , s13[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each14( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , const Array< T , dim > &s11 , const Array< T , dim > &s12 , const Array< T , dim > &s13 , const Array< T , dim > &s14 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] , s11[i] , s12[i] , s13[i] , s14[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim, class Op > static void for_each15( Array< T , dim > &s1 , const Array< T , dim > &s2 , const Array< T , dim > &s3 , const Array< T , dim > &s4 , const Array< T , dim > &s5 , const Array< T , dim > &s6 , const Array< T , dim > &s7 , const Array< T , dim > &s8 , const Array< T , dim > &s9 , const Array< T , dim > &s10 , const Array< T , dim > &s11 , const Array< T , dim > &s12 , const Array< T , dim > &s13 , const Array< T , dim > &s14 , const Array< T , dim > &s15 , Op op ) { for( size_t i=0 ; i<dim ; ++i ) op( s1[i] , s2[i] , s3[i] , s4[i] , s5[i] , s6[i] , s7[i] , s8[i] , s9[i] , s10[i] , s11[i] , s12[i] , s13[i] , s14[i] , s15[i] ); } template < template < typename, size_t > class Array, typename T, size_t dim> static typename norm_result_type< Array< T , dim > >::type norm_inf( const Array< T , dim > &s ) { BOOST_USING_STD_MAX(); using std::abs; typedef typename norm_result_type< Array< T , dim > >::type result_type; result_type init = static_cast< result_type >( 0 ); for( size_t i=0 ; i<dim ; ++i ) init = max BOOST_PREVENT_MACRO_SUBSTITUTION ( init , static_cast< result_type >(abs(s[i])) ); return init; } }; } } } #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_ARRAY_ALGEBRA_HPP_INCLUDED odeint/algebra/fusion_algebra_dispatcher.hpp 0000644 00000002352 15125237305 0015327 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/fusion_algebra_dispatcher.hpp [begin_description] tba. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_FUSION_ALGEBRA_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_ALGEBRA_FUSION_ALGEBRA_DISPATCHER_HPP_DEFINED #include <boost/numeric/odeint/algebra/fusion_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/utility/enable_if.hpp> #include <boost/fusion/include/is_sequence.hpp> namespace boost { namespace numeric { namespace odeint { // specialization for fusion sequences template< class FusionSequence > struct algebra_dispatcher_sfinae< FusionSequence , typename boost::enable_if< typename boost::fusion::traits::is_sequence< FusionSequence >::type >::type > { typedef fusion_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_FUSION_ALGEBRA_DISPATCHER_HPP_DEFINED odeint/algebra/vector_space_algebra.hpp 0000644 00000014361 15125237305 0014276 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/vector_space_algebra.hpp [begin_description] An algebra for types which have vector space semantics, hence types on which the operators +,-,* are well defined. [end_description] Copyright 2010-2012 Karsten Ahnert Copyright 2010-2013 Mario Mulansky 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_ODEINT_ALGEBRA_VECTOR_SPACE_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_VECTOR_SPACE_ALGEBRA_HPP_INCLUDED #include <complex> #include <boost/type_traits/remove_reference.hpp> namespace boost { namespace numeric { namespace odeint { /* * This class template has to be overload in order to call vector_space_algebra::norm_inf */ template< class State, class Enabler = void > struct vector_space_norm_inf; /* * Example: instantiation for sole doubles and complex */ template<> struct vector_space_norm_inf< double > { typedef double result_type; double operator()( double x ) const { using std::abs; return abs(x); } }; template<> struct vector_space_norm_inf< float > { typedef float result_type; result_type operator()( float x ) const { using std::abs; return abs(x); } }; template< typename T > struct vector_space_norm_inf< std::complex<T> > { typedef T result_type; result_type operator()( std::complex<T> x ) const { using std::abs; return abs( x ); } }; struct vector_space_algebra { template< class S1 , class Op > static void for_each1( S1 &s1 , Op op ) { // ToDo : build checks, that the +-*/ operators are well defined op( s1 ); } template< class S1 , class S2 , class Op > static void for_each2( S1 &s1 , S2 &s2 , Op op ) { op( s1 , s2 ); } template< class S1 , class S2 , class S3 , class Op > static void for_each3( S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { op( s1 , s2 , s3 ); } template< class S1 , class S2 , class S3 , class S4 , class Op > static void for_each4( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { op( s1 , s2 , s3 , s4 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each5( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { op( s1 , s2 , s3 , s4 , s5 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each6( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class Op > static void for_each7( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class Op > static void for_each8( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class Op > static void for_each9( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class Op > static void for_each10( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each11( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each12( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each13( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each14( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 , s14 ); } template< class S1 , class S2 , class S3 , class S4 , class S5 , class S6 ,class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class S15 , class Op > static void for_each15( S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , S15 &s15 , Op op ) { op( s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10 , s11 , s12 , s13 , s14 , s15 ); } template< class S > static typename boost::numeric::odeint::vector_space_norm_inf< S >::result_type norm_inf( const S &s ) { boost::numeric::odeint::vector_space_norm_inf< S > n; return n( s ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_ALGEBRA_VECTOR_SPACE_ALGEBRA_HPP_INCLUDED odeint/algebra/operations_dispatcher.hpp 0000644 00000001720 15125237305 0014530 0 ustar 00 /* [auto_generated] boost/numeric/odeint/algebra/operations_dispatcher.hpp [begin_description] Operations dispatcher to automatically chose suitable operations. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_ALGEBRA_OPERATIONS_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_ALGEBRA_OPERATIONS_DISPATCHER_HPP_INCLUDED #include <boost/numeric/odeint/algebra/default_operations.hpp> namespace boost { namespace numeric { namespace odeint { template< class StateType , class Enabler = void > struct operations_dispatcher_sfinae { typedef default_operations operations_type; }; template< class StateType > struct operations_dispatcher : operations_dispatcher_sfinae< StateType > {}; // no further specializations required } } } #endif odeint/integrate/integrate_n_steps.hpp 0000644 00000016103 15125237305 0014242 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_n_steps.hpp [begin_description] Integration of n steps with constant time size. Adaptive and dense-output methods are fully supported. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/null_observer.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp> #include <boost/numeric/odeint/integrate/check_adapter.hpp> namespace boost { namespace numeric { namespace odeint { /* * Integrates n steps * * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , StepOverflowChecker checker ) { // unwrap references typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; typedef typename stepper_type::stepper_category stepper_category; return detail::integrate_n_steps( checked_stepper<stepper_type, checker_type>(stepper, checker), system , start_state , start_time , dt , num_of_steps , checked_observer<observer_type, checker_type>(observer, checker), stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker > Time integrate_n_steps( Stepper stepper , System system , const State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , StepOverflowChecker checker ) { typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; typedef typename stepper_type::stepper_category stepper_category; return detail::integrate_n_steps( checked_stepper<stepper_type, checker_type>(stepper, checker), system , start_state , start_time , dt , num_of_steps , checked_observer<observer_type, checker_type>(observer, checker), stepper_category() ); } /** * \brief The same function as above, but without checker. */ template< class Stepper , class System , class State , class Time , class Observer > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; return detail::integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , observer , stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer > Time integrate_n_steps( Stepper stepper , System system , const State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; return detail::integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , observer , stepper_category() ); } /** * \brief The same function as above, but without observer calls. */ template< class Stepper , class System , class State , class Time > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps ) { return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, null_observer()); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time > Time integrate_n_steps( Stepper stepper , System system , const State &start_state , Time start_time , Time dt , size_t num_of_steps ) { return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, null_observer()); } /************* DOXYGEN *************/ /** * \fn Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer ) * \brief Integrates the ODE with constant step size. * * This function is similar to integrate_const. The observer is called at * equidistant time intervals t0 + n*dt. * If the Stepper is a normal stepper without step size control, dt is also * used for the numerical scheme. If a ControlledStepper is provided, the * algorithm might reduce the step size to meet the error bounds, but it is * ensured that the observer is always called at equidistant time points * t0 + n*dt. If a DenseOutputStepper is used, the step size also may vary * and the dense output is used to call the observer at equidistant time * points. The final integration time is always t0 + num_of_steps*dt. * If a max_step_checker is provided as StepOverflowChecker, a * no_progress_errror is thrown if too many steps (default: 500) are * performed without progress, i.e. in between observer calls. If no * checker is provided, no such overflow check is performed. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param num_of_steps Number of steps to be performed * \param observer Function/Functor called at equidistant time intervals. * \param checker [optional] Functor to check for step count overflows, if no * checker is provided, no exception is thrown. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_N_STEPS_HPP_INCLUDED odeint/integrate/observer_collection.hpp 0000644 00000002537 15125237305 0014575 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/observer_collection.hpp [begin_description] Collection of observers, which are all called during the evolution of the ODE. [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED #include <vector> #include <boost/function.hpp> namespace boost { namespace numeric { namespace odeint { template< class State , class Time > class observer_collection { public: typedef boost::function< void( const State& , const Time& ) > observer_type; typedef std::vector< observer_type > collection_type; void operator()( const State& x , Time t ) { for( size_t i=0 ; i<m_observers.size() ; ++i ) m_observers[i]( x , t ); } collection_type& observers( void ) { return m_observers; } const collection_type& observers( void ) const { return m_observers; } private: collection_type m_observers; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_OBSERVER_COLLECTION_HPP_INCLUDED odeint/integrate/check_adapter.hpp 0000644 00000013363 15125237305 0013307 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/check_adapter.hpp [begin_description] Adapters to add checking facility to stepper and observer [end_description] Copyright 2015 Mario Mulansky 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_ODEINT_INTEGRATE_CHECK_ADAPTER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_CHECK_ADAPTER_HPP_INCLUDED #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> namespace boost { namespace numeric { namespace odeint { template<class Stepper, class Checker, class StepperCategory = typename base_tag<typename Stepper::stepper_category>::type> class checked_stepper; /** * \brief Adapter to combine basic stepper and checker. */ template<class Stepper, class Checker> class checked_stepper<Stepper, Checker, stepper_tag> { public: typedef Stepper stepper_type; typedef Checker checker_type; // forward stepper typedefs typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; private: stepper_type &m_stepper; checker_type &m_checker; public: /** * \brief Construct the checked_stepper. */ checked_stepper(stepper_type &stepper, checker_type &checker) : m_stepper(stepper), m_checker(checker) { } /** * \brief forward of the do_step method */ template<class System, class StateInOut> void do_step(System system, StateInOut &state, const time_type t, const time_type dt) { // do the step m_stepper.do_step(system, state, t, dt); // call the checker m_checker(); } }; /** * \brief Adapter to combine controlled stepper and checker. */ template<class ControlledStepper, class Checker> class checked_stepper<ControlledStepper, Checker, controlled_stepper_tag> { public: typedef ControlledStepper stepper_type; typedef Checker checker_type; // forward stepper typedefs typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; private: stepper_type &m_stepper; checker_type &m_checker; public: /** * \brief Construct the checked_stepper. */ checked_stepper(stepper_type &stepper, checker_type &checker) : m_stepper(stepper), m_checker(checker) { } /** * \brief forward of the do_step method */ template< class System , class StateInOut > controlled_step_result try_step( System system , StateInOut &state , time_type &t , time_type &dt ) { // do the step if( m_stepper.try_step(system, state, t, dt) == success ) { // call the checker if step was successful m_checker(); return success; } else { // step failed -> return fail return fail; } } }; /** * \brief Adapter to combine dense out stepper and checker. */ template<class DenseOutStepper, class Checker> class checked_stepper<DenseOutStepper, Checker, dense_output_stepper_tag> { public: typedef DenseOutStepper stepper_type; typedef Checker checker_type; // forward stepper typedefs typedef typename stepper_type::state_type state_type; typedef typename stepper_type::value_type value_type; typedef typename stepper_type::deriv_type deriv_type; typedef typename stepper_type::time_type time_type; private: stepper_type &m_stepper; checker_type &m_checker; public: /** * \brief Construct the checked_stepper. */ checked_stepper(stepper_type &stepper, checker_type &checker) : m_stepper(stepper), m_checker(checker) { } template< class System > std::pair< time_type , time_type > do_step( System system ) { m_checker(); return m_stepper.do_step(system); } /* provide the remaining dense out stepper interface */ template< class StateType > void initialize( const StateType &x0 , time_type t0 , time_type dt0 ) { m_stepper.initialize(x0, t0, dt0); } template< class StateOut > void calc_state( time_type t , StateOut &x ) const { m_stepper.calc_state(t, x); } template< class StateOut > void calc_state( time_type t , const StateOut &x ) const { m_stepper.calc_state(t, x); } const state_type& current_state( void ) const { return m_stepper.current_state(); } time_type current_time( void ) const { return m_stepper.current_time(); } const state_type& previous_state( void ) const { return m_stepper.previous_state(); } time_type previous_time( void ) const { return m_stepper.previous_time(); } time_type current_time_step( void ) const { return m_stepper.current_time_step(); } }; /** * \brief Adapter to combine observer and checker. */ template<class Observer, class Checker> class checked_observer { public: typedef Observer observer_type; typedef Checker checker_type; private: observer_type &m_observer; checker_type &m_checker; public: checked_observer(observer_type &observer, checker_type &checker) : m_observer(observer), m_checker(checker) {} template< class State , class Time > void operator()(const State& state, Time t) const { // call the observer m_observer(state, t); // reset the checker m_checker.reset(); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif odeint/integrate/integrate_times.hpp 0000644 00000021565 15125237305 0013720 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_times.hpp [begin_description] Integration of ODEs with observation at user defined points [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/range.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/null_observer.hpp> #include <boost/numeric/odeint/integrate/check_adapter.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_times.hpp> namespace boost { namespace numeric { namespace odeint { /* * \brief Integrates while calling the observer at the time points given by sequence [times_start, time_end) * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer , StepOverflowChecker checker ) { // unwrap references typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; typedef typename stepper_type::stepper_category stepper_category; // pass on checked stepper and observer // checked_stepper/observer use references internally, so passing by value is fine return detail::integrate_times( checked_stepper<stepper_type, checker_type>(stepper, checker) , system , start_state , times_start , times_end , dt , checked_observer<observer_type, checker_type>(observer, checker), stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker > size_t integrate_times( Stepper stepper , System system , const State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer , StepOverflowChecker checker ) { typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; typedef typename stepper_type::stepper_category stepper_category; stepper_type &st = stepper; observer_type &obs = observer; checker_type &chk = checker; return detail::integrate_times( checked_stepper<stepper_type, checker_type>(stepper, checker) , system , start_state , times_start , times_end , dt , checked_observer<observer_type, checker_type>(observer, checker), stepper_category() ); } /** * \brief The same function as above, but with the observation times given as range. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer , class StepOverflowChecker > size_t integrate_times( Stepper stepper , System system , State &start_state , const TimeRange × , Time dt , Observer observer , StepOverflowChecker checker ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer , checker ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer , class StepOverflowChecker > size_t integrate_times( Stepper stepper , System system , const State &start_state , const TimeRange × , Time dt , Observer observer , StepOverflowChecker checker ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer , checker ); } /* * The same functions as above, but without a StepOverflowChecker */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; // simply don't use checked_* adapters return detail::integrate_times( stepper , system , start_state , times_start , times_end , dt , observer , stepper_category() ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , const State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_times( stepper , system , start_state , times_start , times_end , dt , observer , stepper_category() ); } /** * \brief The same function as above, but with the observation times given as range. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , const TimeRange × , Time dt , Observer observer ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer ); } /** * \brief Solves the forwarding problem, can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class TimeRange , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , const State &start_state , const TimeRange × , Time dt , Observer observer ) { return integrate_times( stepper , system , start_state , boost::begin( times ) , boost::end( times ) , dt , observer); } /********* DOXYGEN ***********/ /** * \fn size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator times_start , TimeIterator times_end , Time dt , Observer observer ) * \brief Integrates the ODE with observer calls at given time points. * * Integrates the ODE given by system using the given stepper. This function * does observer calls at the subsequent time points given by the range * times_start, times_end. If the stepper has not step size control, the * step size might be reduced occasionally to ensure observer calls exactly * at the time points from the given sequence. If the stepper is a * ControlledStepper, the step size is adjusted to meet the error bounds, * but also might be reduced occasionally to ensure correct observer calls. * If a DenseOutputStepper is provided, the dense output functionality is * used to call the observer at the given times. The end time of the * integration is always *(end_time-1). * If a max_step_checker is provided as StepOverflowChecker, a * no_progress_error is thrown if too many steps (default: 500) are * performed without progress, i.e. in between observer calls. If no * checker is provided, no such overflow check is performed. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param times_start Iterator to the start time * \param times_end Iterator to the end time * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer Function/Functor called at equidistant time intervals. * \param checker [optional] Functor to check for step count overflows, if no * checker is provided, no exception is thrown. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_TIMES_HPP_INCLUDED odeint/integrate/null_observer.hpp 0000644 00000001475 15125237305 0013414 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/null_observer.hpp [begin_description] null_observer [end_description] Copyright 2011-2012 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { struct null_observer { template< class State , class Time > void operator()( const State& /* x */ , Time /* t */ ) const { } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_NULL_OBSERVER_HPP_INCLUDED odeint/integrate/detail/integrate_n_steps.hpp 0000644 00000013271 15125237305 0015507 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp [begin_description] integrate steps implementation [end_description] Copyright 2012-2015 Mario Mulansky Copyright 2012 Christoph Koke Copyright 2012 Karsten Ahnert 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive_checked( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer, controlled_stepper_tag ); /* basic version */ template< class Stepper , class System , class State , class Time , class Observer> Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time time = start_time; for( size_t step = 0; step < num_of_steps ; ++step ) { obs( start_state , time ); st.do_step( system , start_state , time , dt ); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here time = start_time + static_cast< typename unit_value_type<Time>::type >( step+1 ) * dt; } obs( start_state , time ); return time; } /* controlled version */ template< class Stepper , class System , class State , class Time , class Observer > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; Time time = start_time; Time time_step = dt; for( size_t step = 0; step < num_of_steps ; ++step ) { obs( start_state , time ); // integrate_adaptive_checked uses the given checker to throw if an overflow occurs detail::integrate_adaptive(stepper, system, start_state, time, static_cast<Time>(time + time_step), dt, null_observer(), controlled_stepper_tag()); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here time = start_time + static_cast< typename unit_value_type<Time>::type >(step+1) * time_step; } obs( start_state , time ); return time; } /* dense output version */ template< class Stepper , class System , class State , class Time , class Observer > Time integrate_n_steps( Stepper stepper , System system , State &start_state , Time start_time , Time dt , size_t num_of_steps , Observer observer , dense_output_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time time = start_time; const Time end_time = start_time + static_cast< typename unit_value_type<Time>::type >(num_of_steps) * dt; st.initialize( start_state , time , dt ); size_t step = 0; while( step < num_of_steps ) { while( less_with_sign( time , st.current_time() , st.current_time_step() ) ) { st.calc_state( time , start_state ); obs( start_state , time ); ++step; // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * dt; } // we have not reached the end, do another real step if( less_with_sign( static_cast<Time>(st.current_time()+st.current_time_step()) , end_time , st.current_time_step() ) ) { st.do_step( system ); } else if( less_with_sign( st.current_time() , end_time , st.current_time_step() ) ) { // do the last step ending exactly on the end point st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) ); st.do_step( system ); } } // make sure we really end exactly where we should end while( st.current_time() < end_time ) { if( less_with_sign( end_time , static_cast<Time>(st.current_time()+st.current_time_step()) , st.current_time_step() ) ) st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) ); st.do_step( system ); } // observation at final point obs( st.current_state() , end_time ); return time; } } } } } #endif /* BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED */ odeint/integrate/detail/functors.hpp 0000644 00000003260 15125237305 0013632 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/functors.hpp [begin_description] some functors for the iterator based integrate routines [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED #include <utility> namespace boost { namespace numeric { namespace odeint { namespace detail { template< class Observer > struct obs_caller { size_t &m_n; Observer m_obs; obs_caller( size_t &m , Observer &obs ) : m_n(m) , m_obs( obs ) {} template< class State , class Time > void operator()( std::pair< const State & , const Time & > x ) { typedef typename odeint::unwrap_reference< Observer >::type observer_type; observer_type &obs = m_obs; obs( x.first , x.second ); m_n++; } }; template< class Observer , class Time > struct obs_caller_time { Time &m_t; Observer m_obs; obs_caller_time( Time &t , Observer &obs ) : m_t(t) , m_obs( obs ) {} template< class State > void operator()( std::pair< const State & , const Time & > x ) { typedef typename odeint::unwrap_reference< Observer >::type observer_type; observer_type &obs = m_obs; obs( x.first , x.second ); m_t = x.second; } }; } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED odeint/integrate/detail/integrate_times.hpp 0000644 00000013443 15125237305 0015156 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_times.hpp [begin_description] Default integrate times implementation. [end_description] Copyright 2011-2015 Mario Mulansky Copyright 2012 Karsten Ahnert Copyright 2012 Christoph Koke 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED #include <stdexcept> #include <boost/config.hpp> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { /* * integrate_times for simple stepper */ template<class Stepper, class System, class State, class TimeIterator, class Time, class Observer> size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator start_time , TimeIterator end_time , Time dt , Observer observer , stepper_tag ) { typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; stepper_type &st = stepper; observer_type &obs = observer; typedef typename unit_value_type<Time>::type time_type; size_t steps = 0; Time current_dt = dt; while( true ) { Time current_time = *start_time++; obs( start_state , current_time ); if( start_time == end_time ) break; while( less_with_sign( current_time , static_cast<time_type>(*start_time) , current_dt ) ) { current_dt = min_abs( dt , *start_time - current_time ); st.do_step( system , start_state , current_time , current_dt ); current_time += current_dt; steps++; } } return steps; } /* * integrate_times for controlled stepper */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator start_time , TimeIterator end_time , Time dt , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; typedef typename unit_value_type<Time>::type time_type; failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails size_t steps = 0; while( true ) { Time current_time = *start_time++; obs( start_state , current_time ); if( start_time == end_time ) break; while( less_with_sign( current_time , static_cast<time_type>(*start_time) , dt ) ) { // adjust stepsize to end up exactly at the observation point Time current_dt = min_abs( dt , *start_time - current_time ); if( st.try_step( system , start_state , current_time , current_dt ) == success ) { ++steps; // successful step -> reset the fail counter, see #173 fail_checker.reset(); // continue with the original step size if dt was reduced due to observation dt = max_abs( dt , current_dt ); } else { fail_checker(); // check for possible overflow of failed steps in step size adjustment dt = current_dt; } } } return steps; } /* * integrate_times for dense output stepper */ template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer > size_t integrate_times( Stepper stepper , System system , State &start_state , TimeIterator start_time , TimeIterator end_time , Time dt , Observer observer , dense_output_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; typedef typename unit_value_type<Time>::type time_type; if( start_time == end_time ) return 0; TimeIterator last_time_iterator = end_time; --last_time_iterator; Time last_time_point = static_cast<time_type>(*last_time_iterator); st.initialize( start_state , *start_time , dt ); obs( start_state , *start_time++ ); size_t count = 0; while( start_time != end_time ) { while( ( start_time != end_time ) && less_eq_with_sign( static_cast<time_type>(*start_time) , st.current_time() , st.current_time_step() ) ) { st.calc_state( *start_time , start_state ); obs( start_state , *start_time ); start_time++; } // we have not reached the end, do another real step if( less_eq_with_sign( st.current_time() + st.current_time_step() , last_time_point , st.current_time_step() ) ) { st.do_step( system ); ++count; } else if( start_time != end_time ) { // do the last step ending exactly on the end point st.initialize( st.current_state() , st.current_time() , last_time_point - st.current_time() ); st.do_step( system ); ++count; } } return count; } } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/integrate/detail/integrate_adaptive.hpp 0000644 00000012353 15125237305 0015631 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp [begin_description] Default Integrate adaptive implementation. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky Copyright 2012 Christoph Koke 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED #include <stdexcept> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/stepper/controlled_step_result.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_const.hpp> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> #include <iostream> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ); /* * integrate_adaptive for simple stepper is basically an integrate_const + some last step */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ) { size_t steps = detail::integrate_const( stepper , system , start_state , start_time , end_time , dt , observer , stepper_tag() ); typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time end = start_time + dt*steps; if( less_with_sign( end , end_time , dt ) ) { //make a last step to end exactly at end_time st.do_step( system , start_state , end , end_time - end ); steps++; obs( start_state , end_time ); } return steps; } /* * integrate adaptive for controlled stepper */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails size_t count = 0; while( less_with_sign( start_time , end_time , dt ) ) { obs( start_state , start_time ); if( less_with_sign( end_time , static_cast<Time>(start_time + dt) , dt ) ) { dt = end_time - start_time; } controlled_step_result res; do { res = st.try_step( system , start_state , start_time , dt ); fail_checker(); // check number of failed steps } while( res == fail ); fail_checker.reset(); // if we reach here, the step was successful -> reset fail checker ++count; } obs( start_state , start_time ); return count; } /* * integrate adaptive for dense output steppers * * step size control is used if the stepper supports it */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , dense_output_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; size_t count = 0; st.initialize( start_state , start_time , dt ); while( less_with_sign( st.current_time() , end_time , st.current_time_step() ) ) { while( less_eq_with_sign( static_cast<Time>(st.current_time() + st.current_time_step()) , end_time , st.current_time_step() ) ) { //make sure we don't go beyond the end_time obs( st.current_state() , st.current_time() ); st.do_step( system ); ++count; } // calculate time step to arrive exactly at end time st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) ); } obs( st.current_state() , st.current_time() ); // overwrite start_state with the final point boost::numeric::odeint::copy( st.current_state() , start_state ); return count; } } // namespace detail } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/integrate/detail/integrate_const.hpp 0000644 00000013370 15125237305 0015162 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/detail/integrate_const.hpp [begin_description] integrate const implementation [end_description] Copyright 2012-2015 Mario Mulansky Copyright 2012 Christoph Koke Copyright 2012 Karsten Ahnert 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_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/util/unit_helper.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp> #include <boost/numeric/odeint/util/detail/less_with_sign.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // forward declaration template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time &start_time , Time end_time , Time &dt , Observer observer , controlled_stepper_tag ); template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time time = start_time; int step = 0; // cast time+dt explicitely in case of expression templates (e.g. multiprecision) while( less_eq_with_sign( static_cast<Time>(time+dt) , end_time , dt ) ) { obs( start_state , time ); st.do_step( system , start_state , time , dt ); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here ++step; time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * dt; } obs( start_state , time ); return step; } template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , controlled_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; Time time = start_time; const Time time_step = dt; int real_steps = 0; int step = 0; while( less_eq_with_sign( static_cast<Time>(time+time_step) , end_time , dt ) ) { obs( start_state , time ); // integrate_adaptive_checked uses the given checker to throw if an overflow occurs real_steps += detail::integrate_adaptive(stepper, system, start_state, time, static_cast<Time>(time + time_step), dt, null_observer(), controlled_stepper_tag()); // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here step++; time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * time_step; } obs( start_state , time ); return real_steps; } template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_const( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer , dense_output_stepper_tag ) { typename odeint::unwrap_reference< Observer >::type &obs = observer; typename odeint::unwrap_reference< Stepper >::type &st = stepper; Time time = start_time; st.initialize( start_state , time , dt ); obs( start_state , time ); time += dt; int obs_step( 1 ); int real_step( 0 ); while( less_eq_with_sign( static_cast<Time>(time+dt) , end_time , dt ) ) { while( less_eq_with_sign( time , st.current_time() , dt ) ) { st.calc_state( time , start_state ); obs( start_state , time ); ++obs_step; // direct computation of the time avoids error propagation happening when using time += dt // we need clumsy type analysis to get boost units working here time = start_time + static_cast< typename unit_value_type<Time>::type >(obs_step) * dt; } // we have not reached the end, do another real step if( less_with_sign( static_cast<Time>(st.current_time()+st.current_time_step()) , end_time , st.current_time_step() ) ) { while( less_eq_with_sign( st.current_time() , time , dt ) ) { st.do_step( system ); ++real_step; } } else if( less_with_sign( st.current_time() , end_time , st.current_time_step() ) ) { // do the last step ending exactly on the end point st.initialize( st.current_state() , st.current_time() , end_time - st.current_time() ); st.do_step( system ); ++real_step; } } // last observation, if we are still in observation interval // might happen due to finite precision problems when computing the the time if( less_eq_with_sign( time , end_time , dt ) ) { st.calc_state( time , start_state ); obs( start_state , time ); } return real_step; } } } } } #endif odeint/integrate/integrate_adaptive.hpp 0000644 00000010736 15125237305 0014372 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_adaptive.hpp [begin_description] Adaptive integration of ODEs. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/null_observer.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp> namespace boost { namespace numeric { namespace odeint { /* * the two overloads are needed in order to solve the forwarding problem */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); /* * Suggestion for a new extendable version: * * integrator_adaptive< Stepper , System, State , Time , Observer , typename Stepper::stepper_category > integrator; * return integrator.run( stepper , system , start_state , start_time , end_time , dt , observer ); */ } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time , class Observer > size_t integrate_adaptive( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category; return detail::integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , observer , stepper_category() ); } /** * \brief integrate_adaptive without an observer. */ template< class Stepper , class System , class State , class Time > size_t integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template< class Stepper , class System , class State , class Time > size_t integrate_adaptive( Stepper stepper , System system , const State &start_state , Time start_time , Time end_time , Time dt ) { return integrate_adaptive( stepper , system , start_state , start_time , end_time , dt , null_observer() ); } /************* DOXYGEN ************/ /** * \fn integrate_adaptive( Stepper stepper , System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) * \brief Integrates the ODE with adaptive step size. * * This function integrates the ODE given by system with the given stepper. * The observer is called after each step. If the stepper has no error * control, the step size remains constant and the observer is called at * equidistant time points t0+n*dt. If the stepper is a ControlledStepper, * the step size is adjusted and the observer is called in non-equidistant * intervals. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param end_time The final integration time tend. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer Function/Functor called at equidistant time intervals. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_ADAPTIVE_HPP_INCLUDED odeint/integrate/max_step_checker.hpp 0000644 00000005445 15125237305 0014040 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/max_step_checker.hpp [begin_description] Throws exception if too many steps are performed. [end_description] Copyright 2015 Mario Mulansky 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_ODEINT_INTEGRATE_MAX_STEP_CHECKER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_MAX_STEP_CHECKER_HPP_INCLUDED #include <stdexcept> #include <cstdio> #include <boost/throw_exception.hpp> #include <boost/numeric/odeint/util/odeint_error.hpp> namespace boost { namespace numeric { namespace odeint { /** * \brief A class for performing overflow checks on the step count in integrate functions. * * Provide an instance of this class to integrate functions if you want to throw a runtime error if * too many steps are performed without progress during the integrate routine. */ class max_step_checker { public: protected: const int m_max_steps; int m_steps; public: /** * \brief Construct the max_step_checker. * max_steps is the maximal number of iterations allowed before runtime_error is thrown. */ max_step_checker(const int max_steps = 500) : m_max_steps(max_steps) { reset(); } /** * \brief Resets the max_step_checker by setting the internal counter to 0. */ void reset() { m_steps = 0; } /** * \brief Increases the counter and performs the iteration check */ void operator()(void) { if( m_steps++ >= m_max_steps ) { char error_msg[200]; std::sprintf(error_msg, "Max number of iterations exceeded (%d).", m_max_steps); BOOST_THROW_EXCEPTION( no_progress_error(error_msg) ); } } }; /** * \brief A class for performing overflow checks on the failed step count in step size adjustments. * * Used internally within the dense output stepper and integrate routines. */ class failed_step_checker : public max_step_checker { public: /** * \brief Construct the failed_step_checker. * max_steps is the maximal number of iterations allowed before runtime_error is thrown. */ failed_step_checker(const int max_steps = 500) : max_step_checker(max_steps) {} /** * \brief Increases the counter and performs the iteration check */ void operator()(void) { if( m_steps++ >= m_max_steps ) { char error_msg[200]; std::sprintf(error_msg, "Max number of iterations exceeded (%d). A new step size was not found.", m_max_steps); BOOST_THROW_EXCEPTION( step_adjustment_error(error_msg) ); } } }; } // namespace odeint } // namespace numeric } // namespace boost #endif odeint/integrate/integrate.hpp 0000644 00000011577 15125237305 0012521 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate.hpp [begin_description] Convenience methods which choose the stepper for the current ODE. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2012 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED #include <boost/utility/enable_if.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp> #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/integrate/null_observer.hpp> #include <boost/numeric/odeint/integrate/integrate_adaptive.hpp> // for has_value_type trait #include <boost/numeric/odeint/algebra/detail/extract_value_type.hpp> namespace boost { namespace numeric { namespace odeint { /* * ToDo : * * determine type of dxdt for units * */ template< class System , class State , class Time , class Observer > typename boost::enable_if< typename has_value_type<State>::type , size_t >::type integrate( System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef controlled_runge_kutta< runge_kutta_dopri5< State , typename State::value_type , State , Time > > stepper_type; return integrate_adaptive( stepper_type() , system , start_state , start_time , end_time , dt , observer ); } template< class Value , class System , class State , class Time , class Observer > size_t integrate( System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) { typedef controlled_runge_kutta< runge_kutta_dopri5< State , Value , State , Time > > stepper_type; return integrate_adaptive( stepper_type() , system , start_state , start_time , end_time , dt , observer ); } /* * the two overloads are needed in order to solve the forwarding problem */ template< class System , class State , class Time > size_t integrate( System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate( system , start_state , start_time , end_time , dt , null_observer() ); } template< class Value , class System , class State , class Time > size_t integrate( System system , State &start_state , Time start_time , Time end_time , Time dt ) { return integrate< Value >( system , start_state , start_time , end_time , dt , null_observer() ); } /** * \fn integrate( System system , State &start_state , Time start_time , Time end_time , Time dt , Observer observer ) * \brief Integrates the ODE. * * Integrates the ODE given by system from start_time to end_time starting * with start_state as initial condition and dt as initial time step. * This function uses a dense output dopri5 stepper and performs an adaptive * integration with step size control, thus dt changes during the integration. * This method uses standard error bounds of 1E-6. * After each step, the observer is called. * * \attention A second version of this function template exists which explicitly * expects the value type as template parameter, i.e. integrate< double >( sys , x , t0 , t1 , dt , obs ); * * \param system The system function to solve, hence the r.h.s. of the * ordinary differential equation. * \param start_state The initial state. * \param start_time Start time of the integration. * \param end_time End time of the integration. * \param dt Initial step size, will be adjusted during the integration. * \param observer Observer that will be called after each time step. * \return The number of steps performed. */ /** * \fn integrate( System system , State &start_state , Time start_time , Time end_time , Time dt ) * \brief Integrates the ODE without observer calls. * * Integrates the ODE given by system from start_time to end_time starting * with start_state as initial condition and dt as initial time step. * This function uses a dense output dopri5 stepper and performs an adaptive * integration with step size control, thus dt changes during the integration. * This method uses standard error bounds of 1E-6. * No observer is called. * * \attention A second version of this function template exists which explicitly * expects the value type as template parameter, i.e. integrate< double >( sys , x , t0 , t1 , dt ); * * \param system The system function to solve, hence the r.h.s. of the * ordinary differential equation. * \param start_state The initial state. * \param start_time Start time of the integration. * \param end_time End time of the integration. * \param dt Initial step size, will be adjusted during the integration. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_HPP_INCLUDED odeint/integrate/integrate_const.hpp 0000644 00000017344 15125237305 0013725 0 ustar 00 /* [auto_generated] boost/numeric/odeint/integrate/integrate_const.hpp [begin_description] Constant integration of ODEs, meaning that the state of the ODE is observed on constant time intervals. The routines makes full use of adaptive and dense-output methods. [end_description] Copyright 2011-2013 Karsten Ahnert Copyright 2011-2015 Mario Mulansky 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_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED #include <boost/type_traits/is_same.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/integrate/null_observer.hpp> #include <boost/numeric/odeint/integrate/check_adapter.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_const.hpp> #include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp> namespace boost { namespace numeric { namespace odeint { /* * Integrates with constant time step dt. */ template<class Stepper, class System, class State, class Time, class Observer, class StepOverflowChecker> size_t integrate_const( Stepper stepper, System system, State &start_state, Time start_time, Time end_time, Time dt, Observer observer, StepOverflowChecker checker ) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; // we want to get as fast as possible to the end // no overflow checks needed if (boost::is_same<null_observer, Observer>::value) { return detail::integrate_adaptive( stepper, system, start_state, start_time, end_time, dt, observer, stepper_category()); } else { // unwrap references typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; return detail::integrate_const(checked_stepper<stepper_type, checker_type>(stepper, checker), system, start_state, start_time, end_time, dt, checked_observer<observer_type, checker_type>(observer, checker), stepper_category()); } } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template<class Stepper, class System, class State, class Time, class Observer, class StepOverflowChecker > size_t integrate_const( Stepper stepper, System system, const State &start_state, Time start_time, Time end_time, Time dt, Observer observer, StepOverflowChecker checker ) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; // we want to get as fast as possible to the end if (boost::is_same<null_observer, Observer>::value) { return detail::integrate_adaptive( stepper, system, start_state, start_time, end_time, dt, observer, stepper_category()); } else { typedef typename odeint::unwrap_reference< Stepper >::type stepper_type; typedef typename odeint::unwrap_reference< Observer >::type observer_type; typedef typename odeint::unwrap_reference< StepOverflowChecker >::type checker_type; return detail::integrate_const(checked_stepper<stepper_type, checker_type>(stepper, checker), system, start_state, start_time, end_time, dt, checked_observer<observer_type, checker_type>(observer, checker), stepper_category()); } } /** * \brief integrate_const without step overflow checker */ template<class Stepper, class System, class State, class Time, class Observer> size_t integrate_const( Stepper stepper, System system, State &start_state, Time start_time, Time end_time, Time dt, Observer observer) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; return detail::integrate_const(stepper, system, start_state, start_time, end_time, dt, observer, stepper_category()); } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template<class Stepper, class System, class State, class Time, class Observer> size_t integrate_const( Stepper stepper, System system, const State &start_state, Time start_time, Time end_time, Time dt, Observer observer ) { typedef typename odeint::unwrap_reference<Stepper>::type::stepper_category stepper_category; return detail::integrate_const(stepper, system, start_state, start_time, end_time, dt, observer, stepper_category()); } /** * \brief integrate_const without observer calls */ template<class Stepper, class System, class State, class Time> size_t integrate_const( Stepper stepper, System system, State &start_state, Time start_time, Time end_time, Time dt ) { return integrate_const(stepper, system, start_state, start_time, end_time, dt, null_observer()); } /** * \brief Second version to solve the forwarding problem, * can be called with Boost.Range as start_state. */ template<class Stepper, class System, class State, class Time> size_t integrate_const( Stepper stepper, System system, const State &start_state, Time start_time, Time end_time, Time dt ) { return integrate_const(stepper, system, start_state, start_time, end_time, dt, null_observer()); } /********* DOXYGEN *********/ /** * \fn integrate_const( Stepper stepper , System system , State &start_state , Time start_time , * Time end_time , Time dt , Observer observer , StepOverflowChecker checker ) * \brief Integrates the ODE with constant step size. * * Integrates the ODE defined by system using the given stepper. * This method ensures that the observer is called at constant intervals dt. * If the Stepper is a normal stepper without step size control, dt is also * used for the numerical scheme. If a ControlledStepper is provided, the * algorithm might reduce the step size to meet the error bounds, but it is * ensured that the observer is always called at equidistant time points * t0 + n*dt. If a DenseOutputStepper is used, the step size also may vary * and the dense output is used to call the observer at equidistant time * points. * If a max_step_checker is provided as StepOverflowChecker, a * no_progress_error is thrown if too many steps (default: 500) are performed * without progress, i.e. in between observer calls. If no checker is provided, * no such overflow check is performed. * * \param stepper The stepper to be used for numerical integration. * \param system Function/Functor defining the rhs of the ODE. * \param start_state The initial condition x0. * \param start_time The initial time t0. * \param end_time The final integration time tend. * \param dt The time step between observer calls, _not_ necessarily the * time step of the integration. * \param observer [optional] Function/Functor called at equidistant time intervals. * \param checker [optional] Functor to check for step count overflows, if no * checker is provided, no exception is thrown. * \return The number of steps performed. */ } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_INTEGRATE_INTEGRATE_CONST_HPP_INCLUDED odeint/external/eigen/eigen_algebra_dispatcher.hpp 0000644 00000002366 15125237305 0016434 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/eigen/eigen_algebra_dispatcher.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_DISPATCHER_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { template< class Derived > struct algebra_dispatcher_sfinae< Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::MatrixBase< Derived > , Derived >::type >::type > { typedef vector_space_algebra algebra_type; }; template < class Derived > struct algebra_dispatcher_sfinae< Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::ArrayBase< Derived > , Derived >::type >::type > { typedef vector_space_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_DISPATCHER_HPP_INCLUDED odeint/external/eigen/eigen.hpp 0000644 00000001362 15125237305 0012544 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/eigen/eigen.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_EXTERNAL_EIGEN_EIGEN_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_HPP_INCLUDED #include <boost/numeric/odeint/external/eigen/eigen_algebra.hpp> #include <boost/numeric/odeint/external/eigen/eigen_algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/eigen/eigen_resize.hpp> #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_HPP_INCLUDED odeint/external/eigen/eigen_resize.hpp 0000644 00000006057 15125237305 0014133 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/eigen/eigen_resize.hpp [begin_description] tba. [end_description] Copyright 2013 Ankur Sinha Copyright 2013 Karsten Ahnert 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_ODEINT_EXTERNAL_EIGEN_EIGEN_RESIZE_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_RESIZE_HPP_DEFINED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_base_of.hpp> #include <Eigen/Dense> namespace boost { namespace numeric { namespace odeint { template< class Derived > struct is_resizeable_sfinae< Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::MatrixBase< Derived > , Derived >::type >::type > { typedef boost::true_type type; const static bool value = type::value; }; template < class Derived > struct is_resizeable_sfinae< Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::ArrayBase< Derived > , Derived >::type >::type > { typedef boost::true_type type; const static bool value = type::value; }; template< class Derived > struct same_size_impl_sfinae< Derived , Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::MatrixBase< Derived > , Derived >::type >::type > { static bool same_size( const Eigen::MatrixBase< Derived > &m1 , const Eigen::MatrixBase< Derived > &m2 ) { return ( ( m1.innerSize () == m2.innerSize () ) && ( m1.outerSize() == m2.outerSize() ) ); } }; template< class Derived > struct same_size_impl_sfinae< Derived , Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::ArrayBase< Derived > , Derived >::type >::type > { static bool same_size( const Eigen::ArrayBase< Derived > &v1 , const Eigen::ArrayBase< Derived > &v2 ) { return ( ( v1.innerSize () == v2.innerSize () ) && ( v1.outerSize() == v2.outerSize() ) ); } }; template< class Derived > struct resize_impl_sfinae< Derived , Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::MatrixBase< Derived > , Derived >::type >::type > { static void resize( Eigen::MatrixBase< Derived > &m1 , const Eigen::MatrixBase< Derived > &m2 ) { m1.derived().resizeLike(m2); } }; template< class Derived > struct resize_impl_sfinae< Derived , Derived , typename boost::enable_if< typename boost::is_base_of< Eigen::ArrayBase< Derived > , Derived >::type >::type > { static void resize( Eigen::ArrayBase< Derived > &v1 , const Eigen::ArrayBase< Derived > &v2 ) { v1.derived().resizeLike(v2); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_RESIZE_HPP_DEFINED odeint/external/eigen/eigen_algebra.hpp 0000644 00000005630 15125237305 0014223 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/eigen/eigen_algebra.hpp [begin_description] tba. [end_description] Copyright 2013 Christian Shelton Copyright 2013 Karsten Ahnert 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_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_HPP_INCLUDED #include <Eigen/Dense> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> // Necessary routines for Eigen matrices to work with vector_space_algebra // from odeint // (that is, it lets odeint treat the eigen matrices correctly, knowing // how to add, multiply, compute the norm, etc) namespace Eigen { template<typename D> inline const typename Eigen::CwiseBinaryOp< internal::scalar_sum_op<typename internal::traits<D>::Scalar>, typename DenseBase<D>::ConstantReturnType, const D> operator+(const typename Eigen::MatrixBase<D> &m, const typename Eigen::internal::traits<D>::Scalar &s) { return CwiseBinaryOp< internal::scalar_sum_op<typename internal::traits<D>::Scalar>, typename DenseBase<D>::ConstantReturnType, const D>(DenseBase<D>::Constant(m.rows(), m.cols(), s), m.derived()); } template<typename D> inline const typename Eigen::CwiseBinaryOp< internal::scalar_sum_op<typename internal::traits<D>::Scalar>, typename DenseBase<D>::ConstantReturnType, const D> operator+(const typename Eigen::internal::traits<D>::Scalar &s, const typename Eigen::MatrixBase<D> &m) { return CwiseBinaryOp< internal::scalar_sum_op<typename internal::traits<D>::Scalar>, typename DenseBase<D>::ConstantReturnType, const D>(DenseBase<D>::Constant(m.rows(), m.cols(), s), m.derived()); } template<typename D1,typename D2> inline const typename Eigen::CwiseBinaryOp< typename Eigen::internal::scalar_quotient_op< typename Eigen::internal::traits<D1>::Scalar>, const D1, const D2> operator/(const Eigen::MatrixBase<D1> &x1, const Eigen::MatrixBase<D2> &x2) { return x1.cwiseQuotient(x2); } template< typename D > inline const typename Eigen::CwiseUnaryOp< typename Eigen::internal::scalar_abs_op< typename Eigen::internal::traits< D >::Scalar > , const D > abs( const Eigen::MatrixBase< D > &m ) { return m.cwiseAbs(); } } // end Eigen namespace namespace boost { namespace numeric { namespace odeint { template<typename B,int S1,int S2,int O, int M1, int M2> struct vector_space_norm_inf< Eigen::Matrix<B,S1,S2,O,M1,M2> > { typedef B result_type; result_type operator()( const Eigen::Matrix<B,S1,S2,O,M1,M2> &m ) const { return m.template lpNorm<Eigen::Infinity>(); } }; } } } // end boost::numeric::odeint namespace #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_EIGEN_EIGEN_ALGEBRA_HPP_INCLUDED odeint/external/compute/compute_operations_dispatcher.hpp 0000644 00000002262 15125237305 0020167 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute_operations_dispatcher.hpp [begin_description] operations_dispatcher specialization for Boost.Compute [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_DISPATCHER_HPP_DEFINED #include <boost/compute/container/vector.hpp> #include <boost/numeric/odeint/external/compute/compute_operations.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { // specialization for Boost.Compute vector template< class T , class A > struct operations_dispatcher< boost::compute::vector< T , A > > { typedef compute_operations operations_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_DISPATCHER_HPP_DEFINED odeint/external/compute/compute_algebra_dispatcher.hpp 0000644 00000002221 15125237305 0017374 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute_algebra_dispatcher.hpp [begin_description] algebra_dispatcher specialization for Boost.Compute [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_ALGEBRA_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_ALGEBRA_DISPATCHER_HPP_DEFINED #include <boost/compute/container/vector.hpp> #include <boost/numeric/odeint/external/compute/compute_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { // specialization for Boost.Compute vector template< class T , class A > struct algebra_dispatcher< boost::compute::vector< T , A > > { typedef compute_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_ALGEBRA_DISPATCHER_HPP_DEFINED odeint/external/compute/compute_operations.hpp 0000644 00000021055 15125237305 0015762 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute_operations.hpp [begin_description] Operations of Boost.Compute zipped iterators. Is the counterpart of the compute_algebra. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_HPP_DEFINED #include <boost/preprocessor/repetition.hpp> #include <boost/compute.hpp> namespace boost { namespace numeric { namespace odeint { struct compute_operations { #define BOOST_ODEINT_COMPUTE_TEMPL_FAC(z, n, unused) \ , class Fac ## n = BOOST_PP_CAT(Fac, BOOST_PP_DEC(n)) #define BOOST_ODEINT_COMPUTE_MEMB_FAC(z, n, unused) \ const Fac ## n m_alpha ## n; #define BOOST_ODEINT_COMPUTE_PRM_FAC(z, n, unused) \ BOOST_PP_COMMA_IF(n) const Fac ## n alpha ## n #define BOOST_ODEINT_COMPUTE_INIT_FAC(z, n, unused) \ BOOST_PP_COMMA_IF(n) m_alpha ## n (alpha ## n) #define BOOST_ODEINT_COMPUTE_PRM_STATE(z, n, unused) \ BOOST_PP_COMMA_IF(n) StateType ## n &s ## n #define BOOST_ODEINT_COMPUTE_BEGIN_STATE(z, n, unused) \ BOOST_PP_COMMA_IF( BOOST_PP_DEC(n) ) s ## n.begin() #define BOOST_ODEINT_COMPUTE_END_STATE(z, n, unused) \ BOOST_PP_COMMA_IF( BOOST_PP_DEC(n) ) s ## n.end() #define BOOST_ODEINT_COMPUTE_LAMBDA(z, n, unused) \ BOOST_PP_EXPR_IF(n, +) m_alpha ## n * bc::lambda::get< n >(bc::_1) #define BOOST_ODEINT_COMPUTE_OPERATIONS(z, n, unused) \ template< \ class Fac0 = double \ BOOST_PP_REPEAT_FROM_TO(1, n, BOOST_ODEINT_COMPUTE_TEMPL_FAC, ~) \ > \ struct scale_sum ## n { \ BOOST_PP_REPEAT(n, BOOST_ODEINT_COMPUTE_MEMB_FAC, ~) \ scale_sum ## n( \ BOOST_PP_REPEAT(n, BOOST_ODEINT_COMPUTE_PRM_FAC, ~) \ ) \ : BOOST_PP_REPEAT(n, BOOST_ODEINT_COMPUTE_INIT_FAC, ~) \ { } \ template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), class StateType) > \ void operator()( \ BOOST_PP_REPEAT( \ BOOST_PP_INC(n), \ BOOST_ODEINT_COMPUTE_PRM_STATE, ~) \ ) const \ { \ namespace bc = boost::compute; \ bc::transform( \ bc::make_zip_iterator( \ boost::make_tuple( \ BOOST_PP_REPEAT_FROM_TO( \ 1, BOOST_PP_INC(n), \ BOOST_ODEINT_COMPUTE_BEGIN_STATE, ~) \ ) \ ), \ bc::make_zip_iterator( \ boost::make_tuple( \ BOOST_PP_REPEAT_FROM_TO( \ 1, BOOST_PP_INC(n), \ BOOST_ODEINT_COMPUTE_END_STATE, ~) \ ) \ ), \ s0.begin(), \ BOOST_PP_REPEAT(n, BOOST_ODEINT_COMPUTE_LAMBDA, ~) \ ); \ } \ }; BOOST_PP_REPEAT_FROM_TO(2, 8, BOOST_ODEINT_COMPUTE_OPERATIONS, ~) #undef BOOST_ODEINT_COMPUTE_TEMPL_FAC #undef BOOST_ODEINT_COMPUTE_MEMB_FAC #undef BOOST_ODEINT_COMPUTE_PRM_FAC #undef BOOST_ODEINT_COMPUTE_INIT_FAC #undef BOOST_ODEINT_COMPUTE_PRM_STATE #undef BOOST_ODEINT_COMPUTE_BEGIN_STATE #undef BOOST_ODEINT_COMPUTE_END_STATE #undef BOOST_ODEINT_COMPUTE_LAMBDA #undef BOOST_ODEINT_COMPUTE_OPERATIONS template<class Fac1 = double, class Fac2 = Fac1> struct scale_sum_swap2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum_swap2(const Fac1 alpha1, const Fac2 alpha2) : m_alpha1(alpha1), m_alpha2(alpha2) { } template<class State0, class State1, class State2> void operator()(State0 &s0, State1 &s1, State2 &s2) const { namespace bc = boost::compute; bc::command_queue &queue = bc::system::default_queue(); const bc::context &context = queue.get_context(); const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE( kernel void scale_sum_swap2( F1 a1, F2 a2, global T0 *x0, global T1 *x1, global T2 *x2, ) { uint i = get_global_id(0); T0 tmp = x0[i]; x0[i] = a1 * x1[i] + a2 * x2[i]; x1[i] = tmp; } ); std::stringstream options; options << " -DT0=" << bc::type_name<typename State0::value_type>() << " -DT1=" << bc::type_name<typename State1::value_type>() << " -DT2=" << bc::type_name<typename State2::value_type>() << " -DF1=" << bc::type_name<Fac1>() << " -DF2=" << bc::type_name<Fac2>(); bc::program program = bc::program::build_with_source(source, context, options.str()); bc::kernel kernel(program, "scale_sum_swap2"); kernel.set_arg(0, m_alpha1); kernel.set_arg(1, m_alpha2); kernel.set_arg(2, s0.get_buffer()); kernel.set_arg(3, s1.get_buffer()); kernel.set_arg(4, s2.get_buffer()); queue.enqueue_1d_range_kernel(kernel, 0, s0.size()); } }; template<class Fac1 = double> struct rel_error { const Fac1 m_eps_abs, m_eps_rel, m_a_x, m_a_dxdt; rel_error(const Fac1 eps_abs, const Fac1 eps_rel, const Fac1 a_x, const Fac1 a_dxdt) : m_eps_abs(eps_abs), m_eps_rel(eps_rel), m_a_x(a_x), m_a_dxdt(a_dxdt) { } template <class State0, class State1, class State2> void operator()(State0 &s0, State1 &s1, State2 &s2) const { namespace bc = boost::compute; using bc::_1; using bc::lambda::get; bc::for_each( bc::make_zip_iterator( boost::make_tuple( s0.begin(), s1.begin(), s2.begin() ) ), bc::make_zip_iterator( boost::make_tuple( s0.end(), s1.end(), s2.end() ) ), get<0>(_1) = abs( get<0>(_1) ) / (m_eps_abs + m_eps_rel * (m_a_x * abs(get<1>(_1) + m_a_dxdt * abs(get<2>(_1))))) ); } }; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_OPERATIONS_HPP_DEFINED odeint/external/compute/compute.hpp 0000644 00000001741 15125237305 0013517 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute.hpp [begin_description] includes all headers required for using odeint with Boost.Compute [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_HPP_DEFINED #include <boost/numeric/odeint/external/compute/compute_algebra.hpp> #include <boost/numeric/odeint/external/compute/compute_operations.hpp> #include <boost/numeric/odeint/external/compute/compute_algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/compute/compute_operations_dispatcher.hpp> #include <boost/numeric/odeint/external/compute/compute_resize.hpp> #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_HPP_DEFINED odeint/external/compute/compute_algebra.hpp 0000644 00000003752 15125237305 0015200 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute_algebra.hpp [begin_description] An algebra for Boost.Compute vectors. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_ALGEBRA_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_ALGEBRA_HPP_DEFINED #include <boost/preprocessor/repetition.hpp> #include <boost/compute.hpp> namespace boost { namespace numeric { namespace odeint { struct compute_algebra { #define BOOST_ODEINT_COMPUTE_STATE_PARAM(z, n, unused) \ StateType ## n &s ## n, #define BOOST_ODEINT_COMPUTE_ALGEBRA(z, n, unused) \ template< BOOST_PP_ENUM_PARAMS(n, class StateType), class Operation > \ static void for_each ## n( \ BOOST_PP_REPEAT(n, BOOST_ODEINT_COMPUTE_STATE_PARAM, ~) \ Operation op \ ) \ { \ op( BOOST_PP_ENUM_PARAMS(n, s) ); \ } BOOST_PP_REPEAT_FROM_TO(3, 9, BOOST_ODEINT_COMPUTE_ALGEBRA, ~) #undef BOOST_ODEINT_COMPUTE_ALGEBRA #undef BOOST_ODEINT_COMPUTE_STATE_PARAM template < class S > static typename S::value_type norm_inf( const S &s ) { typedef typename S::value_type value_type; BOOST_COMPUTE_FUNCTION(value_type, max_abs, (value_type, value_type), { return max(_1, fabs(_2)); }); return boost::compute::accumulate(s.begin(), s.end(), value_type(), max_abs); } }; } // odeint } // numeric } // boost #endif odeint/external/compute/compute_resize.hpp 0000644 00000004667 15125237305 0015112 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/compute/compute_resize.hpp [begin_description] Enable resizing for Boost.Compute vector [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_EXTERNAL_COMPUTE_COMPUTE_RESIZE_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_RESIZE_HPP_DEFINED #include <boost/compute/container/vector.hpp> #include <boost/numeric/odeint/util/copy.hpp> namespace boost { namespace numeric { namespace odeint { template< class T, class A > struct is_resizeable< boost::compute::vector< T , A > > { struct type : public boost::true_type { }; const static bool value = type::value; }; template< class T, class A > struct same_size_impl< boost::compute::vector< T, A > , boost::compute::vector< T, A > > { static bool same_size( const boost::compute::vector< T, A > &x , const boost::compute::vector< T, A > &y ) { return x.size() == y.size(); } }; template< class T, class A > struct resize_impl< boost::compute::vector< T, A > , boost::compute::vector< T, A > > { static void resize( boost::compute::vector< T, A > &x , const boost::compute::vector< T, A > &y ) { x.resize( y.size() ); } }; template< class Container1, class T, class A > struct copy_impl< Container1 , boost::compute::vector< T, A > > { static void copy( const Container1 &from , boost::compute::vector< T, A > &to ) { boost::compute::copy( boost::begin( from ) , boost::end( from ) , boost::begin( to ) ); } }; template< class T, class A, class Container2 > struct copy_impl< boost::compute::vector< T, A > , Container2 > { static void copy( const boost::compute::vector< T, A > &from , Container2 &to ) { boost::compute::copy( boost::begin( from ) , boost::end( from ) , boost::begin( to ) ); } }; template< class T, class A > struct copy_impl< boost::compute::vector< T, A > , boost::compute::vector< T, A > > { static void copy( const boost::compute::vector< T, A > &from , boost::compute::vector< T, A > &to ) { boost::compute::copy( boost::begin( from ) , boost::end( from ) , boost::begin( to ) ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_COMPUTE_COMPUTE_RESIZE_HPP_DEFINED odeint/external/thrust/thrust_algebra.hpp 0000644 00000017701 15125237305 0014731 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust_algebra.hpp [begin_description] An algebra for thrusts device_vectors. [end_description] Copyright 2010-2013 Mario Mulansky Copyright 2010-2011 Karsten Ahnert Copyright 2013 Kyle Lutz 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_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_HPP_INCLUDED #include <thrust/device_vector.h> #include <thrust/for_each.h> #include <thrust/iterator/zip_iterator.h> #include <boost/range.hpp> namespace boost { namespace numeric { namespace odeint { namespace detail { // to use in thrust::reduce template< class Value > struct maximum { template< class Fac1 , class Fac2 > __host__ __device__ Value operator()( const Fac1 t1 , const Fac2 t2 ) const { return ( abs( t1 ) < abs( t2 ) ) ? t2 : t1 ; } typedef Value result_type; }; } /** ToDO extend until for_each14 for rk78 */ /* * The const versions are needed for boost.range to work, i.e. * it allows you to do * for_each1( make_pair( vec1.begin() , vec1.begin() + 10 ) , op ); */ struct thrust_algebra { template< class StateType , class Operation > static void for_each1( StateType &s , Operation op ) { thrust::for_each( boost::begin(s) , boost::end(s) , op ); } template< class StateType1 , class StateType2 , class Operation > static void for_each2( StateType1 &s1 , StateType2 &s2 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class Operation > static void for_each3( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class StateType4 , class Operation > static void for_each4( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , StateType4 &s4 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) , boost::begin(s4) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) , boost::end(s4) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class StateType4 , class StateType5 ,class Operation > static void for_each5( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , StateType4 &s4 , StateType5 &s5 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) , boost::begin(s4) , boost::begin(s5) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) , boost::end(s4) , boost::end(s5) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class StateType4 , class StateType5 , class StateType6 , class Operation > static void for_each6( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , StateType4 &s4 , StateType5 &s5 , StateType6 &s6 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) , boost::begin(s4) , boost::begin(s5) , boost::begin(s6) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) , boost::end(s4) , boost::end(s5) , boost::end(s6) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class StateType4 , class StateType5 , class StateType6 , class StateType7 , class Operation > static void for_each7( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , StateType4 &s4 , StateType5 &s5 , StateType6 &s6 , StateType7 &s7 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) , boost::begin(s4) , boost::begin(s5) , boost::begin(s6) , boost::begin(s7) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) , boost::end(s4) , boost::end(s5) , boost::end(s6) , boost::end(s7) ) ) , op); } template< class StateType1 , class StateType2 , class StateType3 , class StateType4 , class StateType5 , class StateType6 , class StateType7 , class StateType8 , class Operation > static void for_each8( StateType1 &s1 , StateType2 &s2 , StateType3 &s3 , StateType4 &s4 , StateType5 &s5 , StateType6 &s6 , StateType7 &s7 , StateType8 &s8 , Operation op ) { thrust::for_each( thrust::make_zip_iterator( thrust::make_tuple( boost::begin(s1) , boost::begin(s2) , boost::begin(s3) , boost::begin(s4) , boost::begin(s5) , boost::begin(s6) , boost::begin(s7) , boost::begin(s8) ) ) , thrust::make_zip_iterator( thrust::make_tuple( boost::end(s1) , boost::end(s2) , boost::end(s3) , boost::end(s4) , boost::end(s5) , boost::end(s6) , boost::end(s7) , boost::end(s8) ) ) , op); } template< class S > static typename S::value_type norm_inf( const S &s ) { typedef typename S::value_type value_type; return thrust::reduce( boost::begin( s ) , boost::end( s ) , static_cast<value_type>(0) , detail::maximum<value_type>() ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_HPP_INCLUDED odeint/external/thrust/thrust.hpp 0000644 00000001651 15125237305 0013251 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust.hpp [begin_description] includes all headers required for using odeint with thrust [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_EXTERNAL_THRUST_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_HPP_DEFINED #include <boost/numeric/odeint/external/thrust/thrust_algebra.hpp> #include <boost/numeric/odeint/external/thrust/thrust_operations.hpp> #include <boost/numeric/odeint/external/thrust/thrust_algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/thrust/thrust_operations_dispatcher.hpp> #include <boost/numeric/odeint/external/thrust/thrust_resize.hpp> #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_HPP_DEFINED odeint/external/thrust/thrust_operations.hpp 0000644 00000016421 15125237305 0015515 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust_operations.hpp [begin_description] Operations of thrust zipped iterators. Is the counterpart of the thrust_algebra. [end_description] Copyright 2010-2013 Mario Mulansky Copyright 2010-2012 Karsten Ahnert 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_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_HPP_INCLUDED namespace boost { namespace numeric { namespace odeint { #include <thrust/tuple.h> #include <thrust/iterator/zip_iterator.h> /**ToDo extend to scale_sum13 for rk78 */ struct thrust_operations { template< class Fac1 = double , class Fac2 = Fac1 > struct scale_sum2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum2( const Fac1 alpha1 , const Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t); } }; template< class Fac1 = double , class Fac2 = Fac1 > struct scale_sum_swap2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum_swap2( const Fac1 alpha1 , const Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { typename thrust::tuple_element<0,Tuple>::type tmp = thrust::get<0>(t); thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t); thrust::get<1>(t) = tmp; } }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 > struct scale_sum3 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; scale_sum3( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t) + m_alpha3 * thrust::get<3>(t); } }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 > struct scale_sum4 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; scale_sum4( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ){ } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t) + m_alpha3 * thrust::get<3>(t) + m_alpha4 * thrust::get<4>(t); } }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 > struct scale_sum5 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; scale_sum5( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 , const Fac5 alpha5 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t) + m_alpha3 * thrust::get<3>(t) + m_alpha4 * thrust::get<4>(t) + m_alpha5 * thrust::get<5>(t); } }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 > struct scale_sum6 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; scale_sum6( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 , const Fac5 alpha5 , const Fac6 alpha6 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t) + m_alpha3 * thrust::get<3>(t) + m_alpha4 * thrust::get<4>(t) + m_alpha5 * thrust::get<5>(t) + m_alpha6 * thrust::get<6>(t); } }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 , class Fac6 = Fac5 , class Fac7 = Fac6 > struct scale_sum7 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; const Fac6 m_alpha6; const Fac7 m_alpha7; scale_sum7( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 , const Fac5 alpha5 , const Fac6 alpha6 , const Fac7 alpha7 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) , m_alpha6( alpha6 ) , m_alpha7( alpha7 ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { thrust::get<0>(t) = m_alpha1 * thrust::get<1>(t) + m_alpha2 * thrust::get<2>(t) + m_alpha3 * thrust::get<3>(t) + m_alpha4 * thrust::get<4>(t) + m_alpha5 * thrust::get<5>(t) + m_alpha6 * thrust::get<6>(t) + m_alpha7 * thrust::get<7>(t) ; } }; template< class Fac1 = double > struct rel_error { const Fac1 m_eps_abs , m_eps_rel , m_a_x , m_a_dxdt; rel_error( const Fac1 eps_abs , const Fac1 eps_rel , const Fac1 a_x , const Fac1 a_dxdt ) : m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) , m_a_x( a_x ) , m_a_dxdt( a_dxdt ) { } template< class Tuple > __host__ __device__ void operator()( Tuple t ) const { using std::abs; thrust::get< 0 >( t ) = abs( thrust::get< 0 >( t ) ) / ( m_eps_abs + m_eps_rel * ( m_a_x * abs( thrust::get< 1 >( t ) + m_a_dxdt * abs( thrust::get< 2 >( t ) ) ) ) ); } typedef void result_type; }; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_HPP_INCLUDED odeint/external/thrust/thrust_algebra_dispatcher.hpp 0000644 00000005451 15125237305 0017136 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust_algebra_dispatcher.hpp [begin_description] algebra_dispatcher specialization for thrust [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_DISPATCHER_HPP_DEFINED #include <thrust/host_vector.h> #include <thrust/device_vector.h> #include <boost/numeric/odeint/external/thrust/thrust_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> // specializations for the standard thrust containers namespace boost { namespace numeric { namespace odeint { // specialization for thrust host_vector template< class T , class A > struct algebra_dispatcher< thrust::host_vector< T , A > > { typedef thrust_algebra algebra_type; }; // specialization for thrust device_vector template< class T , class A > struct algebra_dispatcher< thrust::device_vector< T , A > > { typedef thrust_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost // add support for thrust backend vectors, if available #include <thrust/version.h> #if THRUST_VERSION >= 100600 // specialization for thrust cpp vector #include <thrust/system/cpp/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct algebra_dispatcher< thrust::cpp::vector< T , A > > { typedef thrust_algebra algebra_type; }; } } } // specialization for thrust omp vector #ifdef _OPENMP #include <thrust/system/omp/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct algebra_dispatcher< thrust::omp::vector< T , A > > { typedef thrust_algebra algebra_type; }; } } } #endif // _OPENMP // specialization for thrust tbb vector #ifdef TBB_VERSION_MAJOR #include <thrust/system/tbb/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct algebra_dispatcher< thrust::tbb::vector< T , A > > { typedef thrust_algebra algebra_type; }; } } } #endif // TBB_VERSION_MAJOR // specialization for thrust cuda vector #ifdef __CUDACC__ #include <thrust/system/cuda/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct algebra_dispatcher< thrust::cuda::vector< T , A > > { typedef thrust_algebra algebra_type; }; } } } #endif // __CUDACC__ #endif // THRUST_VERSION >= 100600 #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_ALGEBRA_DISPATCHER_HPP_DEFINED odeint/external/thrust/thrust_operations_dispatcher.hpp 0000644 00000005566 15125237305 0017733 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust_operations_dispatcher.hpp [begin_description] operations_dispatcher specialization for thrust [end_description] Copyright 2013-2014 Karsten Ahnert Copyright 2013-2014 Mario Mulansky 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_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_DISPATCHER_HPP_DEFINED #include <thrust/host_vector.h> #include <thrust/device_vector.h> #include <boost/numeric/odeint/external/thrust/thrust_operations.hpp> #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp> // support for the standard thrust containers namespace boost { namespace numeric { namespace odeint { // specialization for thrust host_vector template< class T , class A > struct operations_dispatcher< thrust::host_vector< T , A > > { typedef thrust_operations operations_type; }; // specialization for thrust device_vector template< class T , class A > struct operations_dispatcher< thrust::device_vector< T , A > > { typedef thrust_operations operations_type; }; } // namespace odeint } // namespace numeric } // namespace boost // add support for thrust backend vectors, if available #include <thrust/version.h> #if THRUST_VERSION >= 100600 // specialization for thrust cpp vector #include <thrust/system/cpp/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct operations_dispatcher< thrust::cpp::vector< T , A > > { typedef thrust_operations operations_type; }; } } } // specialization for thrust omp vector #ifdef _OPENMP #include <thrust/system/omp/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct operations_dispatcher< thrust::omp::vector< T , A > > { typedef thrust_operations operations_type; }; } } } #endif // _OPENMP // specialization for thrust tbb vector #ifdef TBB_VERSION_MAJOR #include <thrust/system/tbb/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct operations_dispatcher< thrust::tbb::vector< T , A > > { typedef thrust_operations operations_type; }; } } } #endif // TBB_VERSION_MAJOR // specialization for thrust cuda vector #ifdef __CUDACC__ #include <thrust/system/cuda/vector.h> namespace boost { namespace numeric { namespace odeint { template< class T , class A > struct operations_dispatcher< thrust::cuda::vector< T , A > > { typedef thrust_operations operations_type; }; } } } #endif // __CUDACC__ #endif // THRUST_VERSION >= 100600 #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_OPERATIONS_DISPATCHER_HPP_DEFINED odeint/external/thrust/thrust_resize.hpp 0000644 00000020446 15125237305 0014635 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/thrust/thrust_resize.hpp [begin_description] Enable resizing for thrusts device and host_vector. [end_description] Copyright 2010-2014 Mario Mulansky Copyright 2010-2011 Karsten Ahnert 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_ODEINT_EXTERNAL_THRUST_THRUST_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_RESIZE_HPP_INCLUDED #include <boost/range.hpp> #include <thrust/device_vector.h> #include <thrust/host_vector.h> #include <thrust/distance.h> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/numeric/odeint/util/copy.hpp> namespace boost { namespace numeric { namespace odeint { // some macros that define the necessary utilities #define ODEINT_THRUST_VECTOR_IS_RESIZEABLE( THRUST_VECTOR ) \ template< class T , class A > \ struct is_resizeable< THRUST_VECTOR<T,A> > \ { \ struct type : public boost::true_type { }; \ const static bool value = type::value; \ }; \ #define ODEINT_TRHUST_VECTOR_RESIZE_IMPL( THRUST_VECTOR ) \ template< class T, class A > \ struct resize_impl< THRUST_VECTOR<T,A> , THRUST_VECTOR<T,A> > \ { \ static void resize( THRUST_VECTOR<T,A> &x , \ const THRUST_VECTOR<T,A> &y ) \ { \ x.resize( y.size() ); \ } \ }; \ template< class T, class A, typename Range > \ struct resize_impl< THRUST_VECTOR<T,A> , Range > \ { \ static void resize( THRUST_VECTOR<T,A> &x , \ const Range &y ) \ { \ x.resize( thrust::distance(boost::begin(y), \ boost::end(y))); \ } \ }; \ #define ODEINT_THRUST_SAME_SIZE_IMPL( THRUST_VECTOR ) \ template< class T , class A > \ struct same_size_impl< THRUST_VECTOR<T,A> , THRUST_VECTOR<T,A> > \ { \ static bool same_size( const THRUST_VECTOR<T,A> &x , \ const THRUST_VECTOR<T,A> &y ) \ { \ return x.size() == y.size(); \ } \ }; \ template< class T , class A, typename Range > \ struct same_size_impl< THRUST_VECTOR<T,A> , Range > \ { \ static bool same_size( const THRUST_VECTOR<T,A> &x , \ const Range &y ) \ { \ return x.size() == thrust::distance(boost::begin(y), \ boost::end(y)); \ } \ }; \ #define ODEINT_THRUST_COPY_IMPL( THRUST_VECTOR ) \ template< class Container1 , class T , class A > \ struct copy_impl< Container1 , THRUST_VECTOR<T,A> > \ { \ static void copy( const Container1 &from , THRUST_VECTOR<T,A> &to ) \ { \ thrust::copy( boost::begin( from ) , boost::end( from ) , \ boost::begin( to ) ); \ } \ }; \ \ template< class T , class A , class Container2 > \ struct copy_impl< THRUST_VECTOR<T,A> , Container2 > \ { \ static void copy( const THRUST_VECTOR<T,A> &from , Container2 &to ) \ { \ thrust::copy( boost::begin( from ) , boost::end( from ) , \ boost::begin( to ) ); \ } \ }; \ \ template< class T , class A > \ struct copy_impl< THRUST_VECTOR<T,A> , THRUST_VECTOR<T,A> > \ { \ static void copy( const THRUST_VECTOR<T,A> &from , \ THRUST_VECTOR<T,A> &to ) \ { \ thrust::copy( boost::begin( from ) , boost::end( from ) , \ boost::begin( to ) ); \ } \ }; \ // add support for the standard thrust containers ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::device_vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::device_vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::device_vector ) ODEINT_THRUST_COPY_IMPL( thrust::device_vector ) ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::host_vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::host_vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::host_vector ) ODEINT_THRUST_COPY_IMPL( thrust::host_vector ) } // odeint } // numeric } // boost // add support for thrust backend vectors, if available #include <thrust/version.h> #if THRUST_VERSION >= 100600 #include <thrust/system/cpp/vector.h> namespace boost { namespace numeric { namespace odeint { ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::cpp::vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::cpp::vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::cpp::vector ) ODEINT_THRUST_COPY_IMPL( thrust::cpp::vector ) } } } #ifdef _OPENMP #include <thrust/system/omp/vector.h> namespace boost { namespace numeric { namespace odeint { ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::omp::vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::omp::vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::omp::vector ) ODEINT_THRUST_COPY_IMPL( thrust::omp::vector ) } } } #endif // _OPENMP #ifdef TBB_VERSION_MAJOR #include <thrust/system/tbb/vector.h> namespace boost { namespace numeric { namespace odeint { ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::tbb::vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::tbb::vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::tbb::vector ) ODEINT_THRUST_COPY_IMPL( thrust::tbb::vector ) } } } #endif // TBB_VERSION_MAJOR #ifdef __CUDACC__ #include <thrust/system/cuda/vector.h> namespace boost { namespace numeric { namespace odeint { ODEINT_THRUST_VECTOR_IS_RESIZEABLE( thrust::cuda::vector ) ODEINT_TRHUST_VECTOR_RESIZE_IMPL( thrust::cuda::vector ) ODEINT_THRUST_SAME_SIZE_IMPL( thrust::cuda::vector ) ODEINT_THRUST_COPY_IMPL( thrust::cuda::vector ) } } } #endif // __CUDACC__ #endif // THRUST_VERSION >= 100600 #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_THRUST_THRUST_RESIZE_HPP_INCLUDED odeint/external/mpi/mpi_state.hpp 0000644 00000005622 15125237305 0013143 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mpi/mpi_state.hpp [begin_description] A generic split state, storing partial data on each node. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_MPI_MPI_STATE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_STATE_HPP_INCLUDED #include <vector> #include <algorithm> #include <boost/mpi.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/split.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/mpi/mpi_nested_algebra.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief A container which has its contents distributed among the nodes. */ template< class InnerState > struct mpi_state { typedef InnerState value_type; // the node's local data. InnerState m_data; boost::mpi::communicator world; mpi_state() {} mpi_state(boost::mpi::communicator comm) : world(comm) {} inline InnerState &operator()() { return m_data; } inline const InnerState &operator()() const { return m_data; } }; template< class InnerState > struct is_resizeable< mpi_state< InnerState > > : is_resizeable< InnerState > { }; template< class InnerState1 , class InnerState2 > struct same_size_impl< mpi_state< InnerState1 > , mpi_state< InnerState2 > > { static bool same_size( const mpi_state< InnerState1 > &x , const mpi_state< InnerState2 > &y ) { const bool local = boost::numeric::odeint::same_size(x(), y()); return boost::mpi::all_reduce(x.world, local, mpi::bitwise_and<bool>()); } }; template< class InnerState1 , class InnerState2 > struct resize_impl< mpi_state< InnerState1 > , mpi_state< InnerState2 > > { static void resize( mpi_state< InnerState1 > &x , const mpi_state< InnerState2 > &y ) { // resize local parts on each node. boost::numeric::odeint::resize(x(), y()); } }; /** \brief Copy data between mpi_states of same size. */ template< class InnerState1 , class InnerState2 > struct copy_impl< mpi_state< InnerState1 > , mpi_state< InnerState2 > > { static void copy( const mpi_state< InnerState1 > &from , mpi_state< InnerState2 > &to ) { // copy local parts on each node. boost::numeric::odeint::copy(from(), to()); } }; /** \brief Use `mpi_algebra` for `mpi_state`. */ template< class InnerState > struct algebra_dispatcher< mpi_state< InnerState > > { typedef mpi_nested_algebra< typename algebra_dispatcher< InnerState >::algebra_type > algebra_type; }; } } } #endif odeint/external/mpi/mpi.hpp 0000644 00000001175 15125237305 0011742 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mpi/mpi.hpp [begin_description] Wrappers for MPI. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_MPI_MPI_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_HPP_INCLUDED #include <boost/numeric/odeint/external/mpi/mpi_vector_state.hpp> #include <boost/numeric/odeint/external/mpi/mpi_nested_algebra.hpp> #endif odeint/external/mpi/mpi_nested_algebra.hpp 0000644 00000003134 15125237305 0014756 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mpi/mpi_nested_algebra.hpp [begin_description] Nested parallelized algebra for MPI. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_MPI_MPI_NESTED_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_NESTED_ALGEBRA_HPP_INCLUDED #include <boost/numeric/odeint/algebra/norm_result_type.hpp> #include <boost/numeric/odeint/util/n_ary_helper.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief MPI-parallelized algebra, wrapping another algebra. */ template< class InnerAlgebra > struct mpi_nested_algebra { // execute the InnerAlgebra on each node's local data. #define BOOST_ODEINT_GEN_BODY(n) \ InnerAlgebra::for_each##n( \ BOOST_PP_ENUM_BINARY_PARAMS(n, s, () BOOST_PP_INTERCEPT) , \ op \ ); BOOST_ODEINT_GEN_FOR_EACH(BOOST_ODEINT_GEN_BODY) #undef BOOST_ODEINT_GEN_BODY template< class NestedState > static typename norm_result_type< typename NestedState::value_type >::type norm_inf( const NestedState &s ) { typedef typename norm_result_type< typename NestedState::value_type >::type result_type; // local maximum result_type value = InnerAlgebra::norm_inf( s() ); // global maximum return boost::mpi::all_reduce(s.world, value, boost::mpi::maximum<result_type>()); } }; } } } #endif odeint/external/mpi/mpi_vector_state.hpp 0000644 00000005656 15125237305 0014534 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mpi/mpi_vector_state.hpp [begin_description] Copying a container from/to an mpi_state splits/joins it. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED #include <vector> #include <algorithm> #include <boost/mpi.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/split_adaptor.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/mpi/mpi_state.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief Split data from some container on node 0 to the slaves. * Source must be a model of Random Access Range. */ template< class Source , class InnerState > struct split_impl< Source, mpi_state< InnerState >, typename boost::enable_if< boost::has_range_const_iterator<Source> >::type > { typedef typename boost::range_iterator<const Source>::type iterator; static void split( const Source &from, mpi_state< InnerState > &to ) { std::vector< InnerState > pieces; if(to.world.rank() == 0) { const size_t num = static_cast<size_t>(to.world.size()); pieces.resize(num); for(size_t i = 0 ; i < num ; i++) { iterator_range<iterator> part = detail::make_split_range(from, i, num); boost::numeric::odeint::resize(pieces[i], part); boost::numeric::odeint::copy(part, pieces[i]); } } // send to nodes boost::mpi::scatter(to.world, pieces, to(), 0); } }; /** \brief Merge data from an mpi_state to some container on node 0. * Target must be a model Single Pass Range. */ template< class Target, class InnerState > struct unsplit_impl< mpi_state< InnerState >, Target, typename boost::enable_if< boost::has_range_iterator<Target> >::type > { typedef typename boost::range_iterator<Target>::type iterator; static void unsplit( const mpi_state< InnerState > &from , Target &to ) { std::vector< InnerState > pieces; // send data to root boost::mpi::gather(from.world, from(), pieces, 0); if(from.world.rank() == 0) { // check target size size_t total_size = 0; for(size_t i = 0 ; i < pieces.size() ; i++) total_size += boost::size(pieces[i]); BOOST_ASSERT( total_size <= boost::size(to) ); // copy parts iterator out = boost::begin(to); for(size_t i = 0 ; i < pieces.size() ; i++) out = boost::copy(pieces[i], out); } } }; } } } #endif odeint/external/viennacl/viennacl_operations.hpp 0000644 00000017136 15125237305 0016235 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/viennacl_operations.hpp [begin_description] ViennaCL operations. [end_description] Copyright 2012 Denis Demidov Copyright 2012 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_EXTERNAL_VIENNACL_VIENNACL_OPERATIONS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VIENNACL_VIENNACL_OPERATIONS_HPP_INCLUDED #include <viennacl/vector.hpp> #ifdef VIENNACL_WITH_OPENCL # include <viennacl/generator/custom_operation.hpp> #endif namespace boost { namespace numeric { namespace odeint { #ifdef VIENNACL_WITH_OPENCL struct viennacl_operations { template< class Fac1 = double , class Fac2 = Fac1 > struct scale_sum2 { const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum2( Fac1 alpha1 , Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class T1 , class T2 , class T3 > void operator()( viennacl::vector<T1> &v1 , const viennacl::vector<T2> &v2 , const viennacl::vector<T3> &v3 ) const { using namespace viennacl; static generator::symbolic_vector <0, T1> sym_v1; static generator::symbolic_vector <1, T2> sym_v2; static generator::symbolic_vector <2, T3> sym_v3; static generator::cpu_symbolic_scalar<3, Fac1> sym_a1; static generator::cpu_symbolic_scalar<4, Fac2> sym_a2; static generator::custom_operation op( sym_v1 = sym_a1 * sym_v2 + sym_a2 * sym_v3, "scale_sum2" ); ocl::enqueue( op(v1, v2, v3, m_alpha1, m_alpha2) ); } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 > struct scale_sum3 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; scale_sum3( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) { } template< class T1 , class T2 , class T3 , class T4 > void operator()( viennacl::vector<T1> &v1 , const viennacl::vector<T2> &v2 , const viennacl::vector<T3> &v3 , const viennacl::vector<T4> &v4 ) const { using namespace viennacl; static generator::symbolic_vector <0, T1> sym_v1; static generator::symbolic_vector <1, T2> sym_v2; static generator::symbolic_vector <2, T3> sym_v3; static generator::symbolic_vector <3, T4> sym_v4; static generator::cpu_symbolic_scalar<4, Fac1> sym_a1; static generator::cpu_symbolic_scalar<5, Fac2> sym_a2; static generator::cpu_symbolic_scalar<6, Fac3> sym_a3; static generator::custom_operation op( sym_v1 = sym_a1 * sym_v2 + sym_a2 * sym_v3 + sym_a3 * sym_v4, "scale_sum3" ); ocl::enqueue( op(v1, v2, v3, v4, m_alpha1, m_alpha2, m_alpha3) ); } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 > struct scale_sum4 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; scale_sum4( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 > void operator()( viennacl::vector<T1> &v1 , const viennacl::vector<T2> &v2 , const viennacl::vector<T3> &v3 , const viennacl::vector<T4> &v4 , const viennacl::vector<T5> &v5 ) const { using namespace viennacl; static generator::symbolic_vector <0, T1> sym_v1; static generator::symbolic_vector <1, T2> sym_v2; static generator::symbolic_vector <2, T3> sym_v3; static generator::symbolic_vector <3, T4> sym_v4; static generator::symbolic_vector <4, T5> sym_v5; static generator::cpu_symbolic_scalar<5, Fac1> sym_a1; static generator::cpu_symbolic_scalar<6, Fac2> sym_a2; static generator::cpu_symbolic_scalar<7, Fac3> sym_a3; static generator::cpu_symbolic_scalar<8, Fac4> sym_a4; static generator::custom_operation op( sym_v1 = sym_a1 * sym_v2 + sym_a2 * sym_v3 + sym_a3 * sym_v4 + sym_a4 * sym_v5, "scale_sum4" ); ocl::enqueue( op(v1, v2, v3, v4, v5, m_alpha1, m_alpha2, m_alpha3, m_alpha4) ); } typedef void result_type; }; template< class Fac1 = double , class Fac2 = Fac1 , class Fac3 = Fac2 , class Fac4 = Fac3 , class Fac5 = Fac4 > struct scale_sum5 { const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; scale_sum5( Fac1 alpha1 , Fac2 alpha2 , Fac3 alpha3 , Fac4 alpha4 , Fac5 alpha5 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 > void operator()( viennacl::vector<T1> &v1 , const viennacl::vector<T2> &v2 , const viennacl::vector<T3> &v3 , const viennacl::vector<T4> &v4 , const viennacl::vector<T5> &v5 , const viennacl::vector<T6> &v6 ) const { using namespace viennacl; static generator::symbolic_vector < 0, T1> sym_v1; static generator::symbolic_vector < 1, T2> sym_v2; static generator::symbolic_vector < 2, T3> sym_v3; static generator::symbolic_vector < 3, T4> sym_v4; static generator::symbolic_vector < 4, T5> sym_v5; static generator::symbolic_vector < 5, T6> sym_v6; static generator::cpu_symbolic_scalar< 6, Fac1> sym_a1; static generator::cpu_symbolic_scalar< 7, Fac2> sym_a2; static generator::cpu_symbolic_scalar< 8, Fac3> sym_a3; static generator::cpu_symbolic_scalar< 9, Fac4> sym_a4; static generator::cpu_symbolic_scalar<10, Fac5> sym_a5; static generator::custom_operation op( sym_v1 = sym_a1 * sym_v2 + sym_a2 * sym_v3 + sym_a3 * sym_v4 + sym_a4 * sym_v5 + sym_a5 * sym_v6, "scale_sum5" ); ocl::enqueue( op(v1, v2, v3, v4, v5, v6, m_alpha1, m_alpha2, m_alpha3, m_alpha4, m_alpha5) ); } typedef void result_type; }; }; #else struct viennacl_operations : public default_operations {}; #endif } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VIENNACL_VIENNACL_OPERATIONS_HPP_INCLUDED odeint/external/viennacl/viennacl_resize.hpp 0000644 00000003062 15125237305 0015344 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/viennacl/viennacl_resize.hpp [begin_description] Enable resizing for viennacl vector. [end_description] Copyright 2012 Denis Demidov Copyright 2012 Karsten Ahnert Copyright 2012 Mario Mulansky 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_ODEINT_EXTERNAL_VIENNACL_VIENNACL_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VIENNACL_VIENNACL_RESIZE_HPP_INCLUDED #include <viennacl/vector.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> namespace boost { namespace numeric { namespace odeint { /* * specializations for viennacl::vector< T > */ template< typename T > struct is_resizeable< viennacl::vector< T > > : boost::true_type { }; template< typename T > struct resize_impl< viennacl::vector< T > , viennacl::vector< T > > { static void resize( viennacl::vector< T > &x1 , const viennacl::vector< T > &x2 ) { x1.resize( x2.size() , false ); } }; template< typename T > struct same_size_impl< viennacl::vector< T > , viennacl::vector< T > > { static bool same_size( const viennacl::vector< T > &x1 , const viennacl::vector< T > &x2 ) { return x1.size() == x2.size(); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VIENNACL_VIENNACL_RESIZE_HPP_INCLUDED odeint/external/openmp/openmp_nested_algebra.hpp 0000644 00000044677 15125237305 0016221 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp [begin_description] Nested parallelized algebra for OpenMP. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_OPENMP_OPENMP_NESTED_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_NESTED_ALGEBRA_HPP_INCLUDED #include <boost/assert.hpp> #include <boost/range.hpp> #include <boost/numeric/odeint/algebra/norm_result_type.hpp> #include <boost/numeric/odeint/util/n_ary_helper.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief OpenMP-parallelized algebra, wrapping another, non-parallelized algebra. * * NestedState must be a model of Random Access Range, where the elements are sub-states * which will be processed in parallel. */ template< class InnerAlgebra > struct openmp_nested_algebra { #if __cplusplus >= 201103L // C++11 supports _Pragma #define BOOST_ODEINT_GEN_LOCAL(z, n, unused) \ BOOST_ASSERT_MSG( len == boost::size(s ## n), "All nested state ranges must have the same size." ); \ typename boost::range_iterator<S ## n>::type beg ## n = boost::begin(s ## n); #define BOOST_ODEINT_GEN_BODY(n) \ const size_t len = boost::size(s0); \ BOOST_PP_REPEAT(n, BOOST_ODEINT_GEN_LOCAL, ~) \ _Pragma("omp parallel for schedule(runtime)") \ for( size_t i = 0 ; i < len ; i++ ) \ InnerAlgebra::for_each##n( \ BOOST_PP_ENUM_BINARY_PARAMS(n, beg, [i] BOOST_PP_INTERCEPT) , \ op \ ); BOOST_ODEINT_GEN_FOR_EACH(BOOST_ODEINT_GEN_BODY) #undef BOOST_ODEINT_GEN_BODY #undef BOOST_ODEINT_GEN_LOCAL #else template< class S0 , class Op > static void for_each1 ( S0 &s0 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each1( beg0 [i] , op ); } template< class S0 , class S1 , class Op > static void for_each2 ( S0 &s0 , S1 &s1 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each2( beg0 [i] , beg1 [i] , op ); } template< class S0 , class S1 , class S2 , class Op > static void for_each3 ( S0 &s0 , S1 &s1 , S2 &s2 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each3( beg0 [i] , beg1 [i] , beg2 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class Op > static void for_each4 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each4( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class Op > static void for_each5 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each5( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each6 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each6( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each7 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each7( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class Op > static void for_each8 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each8( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class Op > static void for_each9 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each9( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class Op > static void for_each10 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each10( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class Op > static void for_each11 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each11( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each12 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each12( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each13 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each13( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each14 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); typename boost::range_iterator<S13>::type beg13 = boost::begin(s13); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each14( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] , op ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each15 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); typename boost::range_iterator<S13>::type beg13 = boost::begin(s13); typename boost::range_iterator<S14>::type beg14 = boost::begin(s14); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each15( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] , beg14 [i] , op ); } #endif template< class NestedState > static typename norm_result_type< typename NestedState::value_type >::type norm_inf( const NestedState &s ) { typedef typename boost::range_iterator<const NestedState>::type iterator; typedef typename std::iterator_traits<iterator>::value_type value_type; typedef typename norm_result_type<value_type>::type result_type; result_type init = static_cast< result_type >( 0 ); const size_t len = boost::size(s); iterator beg = boost::begin(s); # pragma omp parallel for reduction(max: init) schedule(dynamic) for( size_t i = 0 ; i < len ; i++ ) init = (std::max)( init , InnerAlgebra::norm_inf( beg[i] ) ); return init; } }; } } } #endif odeint/external/openmp/openmp.hpp 0000644 00000001604 15125237305 0013161 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/openmp/openmp.hpp [begin_description] Wrappers for OpenMP. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_OPENMP_OPENMP_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_HPP_INCLUDED // level 1: parallel iteration over random access container #include <boost/numeric/odeint/external/openmp/openmp_range_algebra.hpp> // level 2: split range state #include <boost/numeric/odeint/external/openmp/openmp_state.hpp> // level 3: process a random access container of sub-states in parallel #include <boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp> #endif odeint/external/openmp/openmp_state.hpp 0000644 00000012124 15125237305 0014360 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/openmp/openmp_state.hpp [begin_description] Wrappers for OpenMP. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED #include <omp.h> #include <vector> #include <algorithm> #include <boost/range/adaptor/sliced.hpp> #include <boost/numeric/odeint/util/copy.hpp> #include <boost/numeric/odeint/util/split.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief A container that is split into distinct parts, for threading. * Just a wrapper for vector<vector<T>>, use `copy` for splitting/joining. */ template< class T > struct openmp_state : public std::vector< std::vector< T > > { openmp_state() {} openmp_state(size_t n, const std::vector<T>& val = std::vector<T>()) : std::vector< std::vector< T > >(n, val) {} template<class InputIterator> openmp_state(InputIterator first, InputIterator last) : std::vector< std::vector< T > >(first, last) {} openmp_state(const std::vector< std::vector< T > > &orig) : std::vector< std::vector< T > >(orig) {} }; template< class T > struct is_resizeable< openmp_state< T > > : boost::true_type { }; template< class T > struct same_size_impl< openmp_state< T > , openmp_state< T > > { static bool same_size( const openmp_state< T > &x , const openmp_state< T > &y ) { if( x.size() != y.size() ) return false; for( size_t i = 0 ; i != x.size() ; i++ ) if( x[i].size() != y[i].size() ) return false; return true; } }; template< class T > struct resize_impl< openmp_state< T > , openmp_state< T > > { static void resize( openmp_state< T > &x , const openmp_state< T > &y ) { x.resize( y.size() ); # pragma omp parallel for schedule(dynamic) for(size_t i = 0 ; i < x.size() ; i++) x[i].resize( y[i].size() ); } }; /** \brief Copy data between openmp_states of same size. */ template< class T > struct copy_impl< openmp_state< T >, openmp_state< T > > { static void copy( const openmp_state< T > &from, openmp_state< T > &to ) { # pragma omp parallel for schedule(dynamic) for(size_t i = 0 ; i < from.size() ; i++) std::copy( from[i].begin() , from[i].end() , to.begin() ); } }; /** \brief Copy data from some container to an openmp_state and resize it. * Target container size will determine number of blocks to split into. * If it is empty, it will be resized to the maximum number of OpenMP threads. * SourceContainer must support `s::value_type`, `s::const_iterator`, `s.begin()`, `s.end()` and `s.size()`, * with Random Access Iterators; i.e. it must be a Random Access Container. */ template< class SourceContainer > struct split_impl< SourceContainer, openmp_state< typename SourceContainer::value_type > > { static void split( const SourceContainer &from, openmp_state< typename SourceContainer::value_type > &to ) { if(to.size() == 0) to.resize( omp_get_max_threads() ); const size_t part = from.size() / to.size(); # pragma omp parallel for schedule(dynamic) for(size_t i = 0 ; i < to.size() ; i++) { typedef typename SourceContainer::const_iterator it_t; const it_t begin = from.begin() + i * part; it_t end = begin + part; // for cases where from.size() % to.size() > 0 if(i + 1 == to.size() || end > from.end()) end = from.end(); to[i].resize(end - begin); std::copy(begin, end, to[i].begin()); } } }; /** \brief Copy data from an openmp_state to some container and resize it. * TargetContainer must support `s::value_type`, `s::iterator`, `s.begin()` and `s.resize(n)`, * i.e. it must be a `std::vector`. */ template< class TargetContainer > struct unsplit_impl< openmp_state< typename TargetContainer::value_type >, TargetContainer > { static void unsplit( const openmp_state< typename TargetContainer::value_type > &from , TargetContainer &to ) { // resize target size_t total_size = 0; for(size_t i = 0 ; i < from.size() ; i++) total_size += from[i].size(); to.resize( total_size ); // copy parts typename TargetContainer::iterator out = to.begin(); for(size_t i = 0 ; i < from.size() ; i++) out = std::copy(from[i].begin(), from[i].end(), out); } }; /** \brief OpenMP-parallelized algebra. * For use with openmp_state. */ typedef openmp_nested_algebra< range_algebra > openmp_algebra; /** \brief Use `openmp_algebra` for `openmp_state`. */ template< class T > struct algebra_dispatcher< openmp_state< T > > { typedef openmp_algebra algebra_type; }; } } } #endif odeint/external/openmp/openmp_range_algebra.hpp 0000644 00000043242 15125237305 0016016 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/openmp/openmp_range_algebra.hpp [begin_description] Range algebra for OpenMP. [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky Copyright 2013 Pascal Germroth 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_ODEINT_EXTERNAL_OPENMP_OPENMP_RANGE_ALGEBRA_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_RANGE_ALGEBRA_HPP_INCLUDED #include <boost/assert.hpp> #include <boost/range.hpp> #include <boost/numeric/odeint/algebra/norm_result_type.hpp> #include <boost/numeric/odeint/util/n_ary_helper.hpp> namespace boost { namespace numeric { namespace odeint { /** \brief OpenMP-parallelized range algebra. * * State must be a model of Random Access Range. */ struct openmp_range_algebra { #if __cplusplus >= 201103L // C++11 supports _Pragma #define BOOST_ODEINT_GEN_LOCAL(z, n, unused) \ BOOST_ASSERT_MSG( len == boost::size(s ## n), "All state ranges must have the same size." ); \ typename boost::range_iterator<S ## n>::type beg ## n = boost::begin(s ## n); #define BOOST_ODEINT_GEN_BODY(n) \ const size_t len = boost::size(s0); \ BOOST_PP_REPEAT(n, BOOST_ODEINT_GEN_LOCAL, ~) \ _Pragma("omp parallel for schedule(runtime)") \ for( size_t i = 0 ; i < len ; i++ ) \ op( BOOST_PP_ENUM_BINARY_PARAMS(n, beg, [i] BOOST_PP_INTERCEPT) ); BOOST_ODEINT_GEN_FOR_EACH(BOOST_ODEINT_GEN_BODY) #undef BOOST_ODEINT_GEN_BODY #undef BOOST_ODEINT_GEN_LOCAL #else template< class S0 , class Op > static void for_each1 ( S0 &s0 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] ); } template< class S0 , class S1 , class Op > static void for_each2 ( S0 &s0 , S1 &s1 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] ); } template< class S0 , class S1 , class S2 , class Op > static void for_each3 ( S0 &s0 , S1 &s1 , S2 &s2 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class Op > static void for_each4 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class Op > static void for_each5 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each6 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each7 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class Op > static void for_each8 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class Op > static void for_each9 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class Op > static void for_each10 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class Op > static void for_each11 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each12 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each13 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each14 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); typename boost::range_iterator<S13>::type beg13 = boost::begin(s13); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] ); } template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each15 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) { const size_t len = boost::size(s0); typename boost::range_iterator<S0>::type beg0 = boost::begin(s0); typename boost::range_iterator<S1>::type beg1 = boost::begin(s1); typename boost::range_iterator<S2>::type beg2 = boost::begin(s2); typename boost::range_iterator<S3>::type beg3 = boost::begin(s3); typename boost::range_iterator<S4>::type beg4 = boost::begin(s4); typename boost::range_iterator<S5>::type beg5 = boost::begin(s5); typename boost::range_iterator<S6>::type beg6 = boost::begin(s6); typename boost::range_iterator<S7>::type beg7 = boost::begin(s7); typename boost::range_iterator<S8>::type beg8 = boost::begin(s8); typename boost::range_iterator<S9>::type beg9 = boost::begin(s9); typename boost::range_iterator<S10>::type beg10 = boost::begin(s10); typename boost::range_iterator<S11>::type beg11 = boost::begin(s11); typename boost::range_iterator<S12>::type beg12 = boost::begin(s12); typename boost::range_iterator<S13>::type beg13 = boost::begin(s13); typename boost::range_iterator<S14>::type beg14 = boost::begin(s14); #pragma omp parallel for schedule(runtime) for( size_t i = 0 ; i < len ; i++ ) op( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] , beg14 [i] ); } #endif template< class S > static typename norm_result_type< S >::type norm_inf( const S &s ) { using std::max; using std::abs; typedef typename norm_result_type< S >::type result_type; result_type init = static_cast< result_type >( 0 ); const size_t len = boost::size(s); typename boost::range_iterator<const S>::type beg = boost::begin(s); # pragma omp parallel for reduction(max: init) schedule(dynamic) for( size_t i = 0 ; i < len ; ++i ) init = max( init , abs( beg[i] ) ); return init; } }; } } } #endif odeint/external/mkl/mkl_operations.hpp 0000644 00000015113 15125237305 0014176 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mkl/mkl_operations.hpp [begin_description] Wrapper classes for intel math kernel library types. Get a free, non-commercial download of MKL at http://software.intel.com/en-us/articles/non-commercial-software-download/ [end_description] Copyright 2010-2011 Mario Mulansky Copyright 2011-2013 Karsten Ahnert 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_ODEINT_EXTERNAL_MKL_MKL_OPERATIONS_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MKL_MKL_OPERATIONS_HPP_INCLUDED #include <iostream> #include <mkl_cblas.h> #include <boost/numeric/odeint/algebra/default_operations.hpp> /* exemplary example for writing bindings to the Intel MKL library * see test/mkl for how to use mkl with odeint * this is a quick and dirty implementation showing the general possibility. * It works only with containers based on double and sequential memory allocation. */ namespace boost { namespace numeric { namespace odeint { /* only defined for doubles */ struct mkl_operations { //template< class Fac1 , class Fac2 > struct scale_sum2; template< class F1 = double , class F2 = F1 > struct scale_sum2 { typedef double Fac1; typedef double Fac2; const Fac1 m_alpha1; const Fac2 m_alpha2; scale_sum2( const Fac1 alpha1 , const Fac2 alpha2 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) { } template< class T1 , class T2 , class T3 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3) const { // t1 = m_alpha1 * t2 + m_alpha2 * t3; // we get Containers that have size() and [i]-access const int n = t1.size(); //boost::numeric::odeint::copy( t1 , t3 ); if( &(t2[0]) != &(t1[0]) ) { cblas_dcopy( n , &(t2[0]) , 1 , &(t1[0]) , 1 ); } cblas_dscal( n , m_alpha1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha2 , &(t3[0]) , 1 , &(t1[0]) , 1 ); //daxpby( &n , &m_alpha2 , &(t3[0]) , &one , &m_alpha1 , &(t1[0]) , &one ); } }; template< class F1 = double , class F2 = F1 , class F3 = F2 > struct scale_sum3 { typedef double Fac1; typedef double Fac2; typedef double Fac3; const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; scale_sum3( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) { } template< class T1 , class T2 , class T3 , class T4 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 ) const { // t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4; // we get Containers that have size() and [i]-access const int n = t1.size(); //boost::numeric::odeint::copy( t1 , t3 ); if( &(t2[0]) != &(t1[0]) ) { cblas_dcopy( n , &(t2[0]) , 1 , &(t1[0]) , 1 ); } cblas_dscal( n , m_alpha1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha2 , &(t3[0]) , 1 , &(t1[0]) , 1 ); //daxpby( &n , &m_alpha2 , &(t3[0]) , &one , &m_alpha1 , &(t1[0]) , &one ); cblas_daxpy( n , m_alpha3 , &(t4[0]) , 1 , &(t1[0]) , 1 ); } }; template< class F1 = double , class F2 = F1 , class F3 = F2 , class F4 = F3 > struct scale_sum4 { typedef double Fac1; typedef double Fac2; typedef double Fac3; typedef double Fac4; const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; scale_sum4( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 ) const { // t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5; // we get Containers that have size() and [i]-access const int n = t1.size(); //boost::numeric::odeint::copy( t1 , t3 ); if( &(t2[0]) != &(t1[0]) ) { cblas_dcopy( n , &(t2[0]) , 1 , &(t1[0]) , 1 ); } cblas_dscal( n , m_alpha1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha2 , &(t3[0]) , 1 , &(t1[0]) , 1 ); //daxpby( &n , &m_alpha2 , &(t3[0]) , &one , &m_alpha1 , &(t1[0]) , &one ); cblas_daxpy( n , m_alpha3 , &(t4[0]) , 1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha4 , &(t5[0]) , 1 , &(t1[0]) , 1 ); } }; template< class F1 = double , class F2 = F1 , class F3 = F2 , class F4 = F3 , class F5 = F4 > struct scale_sum5 { typedef double Fac1; typedef double Fac2; typedef double Fac3; typedef double Fac4; typedef double Fac5; const Fac1 m_alpha1; const Fac2 m_alpha2; const Fac3 m_alpha3; const Fac4 m_alpha4; const Fac5 m_alpha5; scale_sum5( const Fac1 alpha1 , const Fac2 alpha2 , const Fac3 alpha3 , const Fac4 alpha4 , const Fac5 alpha5 ) : m_alpha1( alpha1 ) , m_alpha2( alpha2 ) , m_alpha3( alpha3 ) , m_alpha4( alpha4 ) , m_alpha5( alpha5 ) { } template< class T1 , class T2 , class T3 , class T4 , class T5 , class T6 > void operator()( T1 &t1 , const T2 &t2 , const T3 &t3 , const T4 &t4 , const T5 &t5 , const T6 &t6 ) const { // t1 = m_alpha1 * t2 + m_alpha2 * t3 + m_alpha3 * t4 + m_alpha4 * t5 + m_alpha5 * t6; // we get Containers that have size() and [i]-access const int n = t1.size(); //boost::numeric::odeint::copy( t1 , t3 ); if( &(t2[0]) != &(t1[0]) ) { cblas_dcopy( n , &(t2[0]) , 1 , &(t1[0]) , 1 ); } cblas_dscal( n , m_alpha1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha2 , &(t3[0]) , 1 , &(t1[0]) , 1 ); //daxpby( &n , &m_alpha2 , &(t3[0]) , &one , &m_alpha1 , &(t1[0]) , &one ); cblas_daxpy( n , m_alpha3 , &(t4[0]) , 1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha4 , &(t5[0]) , 1 , &(t1[0]) , 1 ); cblas_daxpy( n , m_alpha5 , &(t6[0]) , 1 , &(t1[0]) , 1 ); } }; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_MKL_MKL_OPERATIONS_HPP_INCLUDED odeint/external/nt2/nt2_resize.hpp 0000644 00000003146 15125237305 0013157 0 ustar 00 //============================================================================== // Copyright 2014 LRI UMR 8623 CNRS/Univ Paris Sud XI // Copyright 2014 NumScale SAS // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE.txt or copy at // http://www.boost.org/LICENSE_1_0.txt //============================================================================== #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_RESIZE_HPP_INCLUDED #include <nt2/core/container/table/table.hpp> #include <boost/numeric/odeint/util/same_size.hpp> namespace boost { namespace numeric { namespace odeint { template<typename T, typename S> struct is_resizeable< nt2::container::table<T,S> > { typedef boost::true_type type; static const bool value = type::value; }; template<typename T, typename S> struct same_size_impl< nt2::container::table<T,S> , nt2::container::table<T,S> > { static bool same_size ( const nt2::container::table<T,S> &v1 , const nt2::container::table<T,S> &v2 ) { return v1.extent() == v2.extent(); } }; template<typename T, typename S> struct resize_impl< nt2::container::table<T,S> , nt2::container::table<T,S> > { static void resize ( nt2::container::table<T,S> &v1 , const nt2::container::table<T,S> &v2 ) { v1.resize( v2.extent() ); } }; } } } #endif odeint/external/nt2/nt2_copy.hpp 0000644 00000002176 15125237305 0012632 0 ustar 00 //============================================================================== // Copyright 2014 LASMEA UMR 6602 CNRS/Univ. Clermont II // Copyright 2014 LRI UMR 8623 CNRS/Univ Paris Sud XI // Copyright 2014 MetaScale SAS // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE.txt or copy at // http://www.boost.org/LICENSE_1_0.txt //============================================================================== #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_COPY_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_COPY_HPP_INCLUDED #include <nt2/core/container/table/table.hpp> #include <boost/numeric/odeint/util/copy.hpp> namespace boost { namespace numeric { namespace odeint { template<typename T, typename S> struct copy_impl< nt2::container::table<T,S> , nt2::container::table<T,S> > { static void copy ( const nt2::container::table<T,S> &v1 , nt2::container::table<T,S> &v2 ) { v2 = v1; } }; } } } #endif odeint/external/nt2/nt2_algebra_dispatcher.hpp 0000644 00000002000 15125237305 0015445 0 ustar 00 //============================================================================== // Copyright 2014 LRI UMR 8623 CNRS/Univ Paris Sud XI // Copyright 2014 NumScale SAS // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE.txt or copy at // http://www.boost.org/LICENSE_1_0.txt //============================================================================== #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_ALGEBRA_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_ALGEBRA_DISPATCHER_HPP_INCLUDED #include <nt2/core/container/table/table.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { template<typename T, typename S> struct algebra_dispatcher<nt2::container::table<T,S> > { typedef vector_space_algebra algebra_type; }; } } } #endif odeint/external/nt2/nt2_norm_inf.hpp 0000644 00000002174 15125237305 0013465 0 ustar 00 //============================================================================== // Copyright 2014 LRI UMR 8623 CNRS/Univ Paris Sud XI // Copyright 2014 NumScale SAS // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE.txt or copy at // http://www.boost.org/LICENSE_1_0.txt //============================================================================== #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_NORM_INF_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_NT2_NT2_NORM_INF_HPP_INCLUDED #include <nt2/core/container/table/table.hpp> #include <nt2/include/functions/globalmax.hpp> #include <nt2/include/functions/abs.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> namespace boost { namespace numeric { namespace odeint { template<typename T, typename S> struct vector_space_norm_inf<nt2::container::table<T,S> > { typedef T result_type; result_type operator()(const nt2::container::table<T,S> &v1) const { return nt2::globalmax(nt2::abs(v1)); } }; } } } #endif odeint/external/vexcl/vexcl_copy.hpp 0000644 00000002365 15125237305 0013666 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_copy.hpp [begin_description] copy_impl specializations for vexcl [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_COPY_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_COPY_HPP_INCLUDED #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <boost/numeric/odeint/util/copy.hpp> namespace boost { namespace numeric { namespace odeint { template< typename T1, typename T2 > struct copy_impl< vex::vector<T1>, vex::vector<T2> > { static void copy( const vex::vector<T1> &from , vex::vector<T2> &to ) { to = from; } }; template< typename T1, typename T2, size_t N > struct copy_impl< vex::multivector<T1, N>, vex::multivector<T2, N> > { static void copy( const vex::multivector<T1, N> &from , vex::multivector<T2, N> &to ) { to = from; } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_COPY_HPP_INCLUDED odeint/external/vexcl/vexcl_norm_inf.hpp 0000644 00000003325 15125237305 0014520 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_norm_inf.hpp [begin_description] vector_space_norm_inf specialization for vexcl [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_NORM_INF_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_NORM_INF_HPP_DEFINED #include <map> #include <algorithm> #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <vexcl/reductor.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> namespace boost { namespace numeric { namespace odeint { // specialization for vexcl vector template <typename T> struct vector_space_norm_inf< vex::vector<T> > { typedef T result_type; T operator()( const vex::vector<T> &x ) const { const auto &max = vex::get_reductor<T, vex::MAX>(x.queue_list()); return max( fabs(x) ); } }; // specialization for vexcl multivector template <typename T, size_t N> struct vector_space_norm_inf< vex::multivector<T, N> > { typedef T result_type; T operator()( const vex::multivector<T, N> &x ) const { const auto &max = vex::get_reductor<T, vex::MAX>(x.queue_list()); // Reducing a multivector results in std::array<T, N>: auto m = max( fabs(x) ); // We will need to reduce it even further: return *std::max_element(m.begin(), m.end()); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_NORM_INF_HPP_DEFINED odeint/external/vexcl/vexcl_abs.hpp 0000644 00000003047 15125237305 0013457 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_abs.hpp [begin_description] abs() specialization for vexcl [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2009-2013 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_ABS_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_ABS_HPP_DEFINED #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <vexcl/operations.hpp> namespace vex { template <typename T, size_t N> typename std::enable_if< std::is_integral<T>::value, typename boost::proto::result_of::make_expr< boost::proto::tag::function, abs_func, const vex::multivector<T, N>& >::type const >::type abs(const multivector<T, N> &arg) { return boost::proto::make_expr<boost::proto::tag::function>( abs_func(), boost::ref(arg) ); } template <typename T, size_t N> typename std::enable_if< !std::is_integral<T>::value, typename boost::proto::result_of::make_expr< boost::proto::tag::function, fabs_func, const vex::multivector<T, N>& >::type const >::type abs(const multivector<T, N> &arg) { return boost::proto::make_expr<boost::proto::tag::function>( fabs_func(), boost::ref(arg) ); } } // namespace vex #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_ABS_HPP_DEFINED odeint/external/vexcl/vexcl_algebra_dispatcher.hpp 0000644 00000002431 15125237305 0016511 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_algebra_dispatcher.hpp [begin_description] algebra_dispatcher specialization for vexcl [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_ALGEBRA_DISPATCHER_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_ALGEBRA_DISPATCHER_HPP_DEFINED #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { // specialization for vexcl vector template< typename T > struct algebra_dispatcher< vex::vector< T > > { typedef vector_space_algebra algebra_type; }; // specialization for vexcl multivector template< typename T , size_t N > struct algebra_dispatcher< vex::multivector< T , N > > { typedef vector_space_algebra algebra_type; }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_ALGEBRA_DISPATCHER_HPP_DEFINED odeint/external/vexcl/vexcl_same_instance.hpp 0000644 00000003032 15125237305 0015515 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_same_instance.hpp [begin_description] Check if two VexCL containers are the same instance. [end_description] Copyright 2009-2011 Karsten Ahnert Copyright 2009-2011 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_SAME_INSTANCE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_SAME_INSTANCE_HPP_INCLUDED #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <boost/numeric/odeint/util/same_instance.hpp> namespace boost { namespace numeric { namespace odeint { template <typename T> struct same_instance_impl< vex::vector<T> , vex::vector<T> > { static bool same_instance( const vex::vector<T> &x1 , const vex::vector<T> &x2 ) { return static_cast<const vex::vector<T>*>(&x1) == static_cast<const vex::vector<T>*>(&x2); } }; template <typename T, size_t N> struct same_instance_impl< vex::multivector<T, N> , vex::multivector<T, N> > { static bool same_instance( const vex::multivector<T, N> &x1 , const vex::multivector<T, N> &x2 ) { return static_cast<const vex::multivector<T, N>*>(&x1) == static_cast<const vex::multivector<T, N>*>(&x2); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_SAME_INSTANCE_HPP_INCLUDED odeint/external/vexcl/vexcl_resize.hpp 0000644 00000004342 15125237305 0014212 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl_resize.hpp [begin_description] Enable resizing for vexcl vector and multivector. [end_description] Copyright 2012 Karsten Ahnert Copyright 2012 Mario Mulansky Copyright 2012 Denis Demidov 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_ODEINT_EXTERNAL_VEXCL_VEXCL_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_RESIZE_HPP_INCLUDED #include <vexcl/vector.hpp> #include <vexcl/multivector.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> namespace boost { namespace numeric { namespace odeint { /* * specializations for vex::vector< T > */ template< typename T > struct is_resizeable< vex::vector< T > > : boost::true_type { }; template< typename T > struct resize_impl< vex::vector< T > , vex::vector< T > > { static void resize( vex::vector< T > &x1 , const vex::vector< T > &x2 ) { x1.resize( x2.queue_list() , x2.size() ); } }; template< typename T > struct same_size_impl< vex::vector< T > , vex::vector< T > > { static bool same_size( const vex::vector< T > &x1 , const vex::vector< T > &x2 ) { return x1.size() == x2.size(); } }; /* * specializations for vex::multivector< T > */ template< typename T , size_t N > struct is_resizeable< vex::multivector< T , N > > : boost::true_type { }; template< typename T , size_t N > struct resize_impl< vex::multivector< T , N > , vex::multivector< T , N > > { static void resize( vex::multivector< T , N > &x1 , const vex::multivector< T , N > &x2 ) { x1.resize( x2.queue_list() , x2.size() ); } }; template< typename T , size_t N > struct same_size_impl< vex::multivector< T , N > , vex::multivector< T , N > > { static bool same_size( const vex::multivector< T , N > &x1 , const vex::multivector< T , N > &x2 ) { return x1.size() == x2.size(); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_RESIZE_HPP_INCLUDED odeint/external/vexcl/vexcl.hpp 0000644 00000001731 15125237305 0012630 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/vexcl/vexcl.hpp [begin_description] includes all headers required for using vexcl in odeint [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_EXTERNAL_VEXCL_VEXCL_HPP_DEFINED #define BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_HPP_DEFINED #include <boost/numeric/odeint/external/vexcl/vexcl_algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/vexcl/vexcl_resize.hpp> #include <boost/numeric/odeint/external/vexcl/vexcl_same_instance.hpp> #include <boost/numeric/odeint/external/vexcl/vexcl_norm_inf.hpp> #include <boost/numeric/odeint/external/vexcl/vexcl_abs.hpp> #include <boost/numeric/odeint/external/vexcl/vexcl_copy.hpp> #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_VEXCL_VEXCL_HPP_DEFINED odeint/external/blaze/blaze_resize.hpp 0000644 00000003254 15125237305 0014143 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/blaze/blaze_resize.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_EXTERNAL_BLAZE_BLAZE_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_BLAZE_BLAZE_RESIZE_HPP_INCLUDED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <blaze/math/dense/DynamicVector.h> namespace boost { namespace numeric { namespace odeint { template< typename T , bool TF > struct is_resizeable< blaze::DynamicVector< T , TF > > { typedef boost::true_type type; const static bool value = type::value; }; template< typename T1 , bool TF1, typename T2 , bool TF2 > struct same_size_impl< blaze::DynamicVector< T1 , TF1 > , blaze::DynamicVector< T2 , TF2 > > { static bool same_size( const blaze::DynamicVector< T1 , TF1 > &x1 , const blaze::DynamicVector< T2 , TF2 > &x2 ) { return x1.size() == x2.size(); } }; template< typename T1 , bool TF1, typename T2 , bool TF2 > struct resize_impl< blaze::DynamicVector< T1 , TF1 > , blaze::DynamicVector< T2 , TF2 > > { static void resize( blaze::DynamicVector< T1 , TF1 > &x1 , const blaze::DynamicVector< T2 , TF2 > &x2 ) { x1.resize( x2.size() ); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_BLAZE_BLAZE_RESIZE_HPP_INCLUDED odeint/external/blaze/blaze_algebra_dispatcher.hpp 0000644 00000002203 15125237305 0016436 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/blaze/blaze_algebra_dispatcher.hpp [begin_description] tba. [end_description] Copyright 2009-2012 Karsten Ahnert Copyright 2009-2012 Mario Mulansky 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_ODEINT_EXTERNAL_BLAZE_BLAZE_ALGEBRA_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_BLAZE_BLAZE_ALGEBRA_DISPATCHER_HPP_INCLUDED #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <blaze/math/dense/StaticVector.h> #include <blaze/math/dense/DynamicVector.h> namespace boost { namespace numeric { namespace odeint { template< typename T , size_t N , bool TF > struct algebra_dispatcher< blaze::StaticVector< T , N , TF > > { typedef vector_space_algebra algebra_type; }; template< typename T , bool TF > struct algebra_dispatcher< blaze::DynamicVector< T , TF > > { typedef vector_space_algebra algebra_type; }; } } } #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_BLAZE_BLAZE_ALGEBRA_DISPATCHER_HPP_INCLUDED odeint/external/gsl/gsl_wrapper.hpp 0000644 00000012200 15125237305 0013471 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/gsl/gsl_wrapper.hpp [begin_description] Wrapper for gsl_vector. [end_description] Copyright 2011-2012 Mario Mulansky Copyright 2011 Karsten Ahnert 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_ODEINT_EXTERNAL_GSL_GSL_WRAPPER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_GSL_GSL_WRAPPER_HPP_INCLUDED #include <new> #include <gsl/gsl_vector.h> #include <boost/type_traits/integral_constant.hpp> #include <boost/range.hpp> #include <boost/iterator/iterator_facade.hpp> #include <boost/numeric/odeint/util/state_wrapper.hpp> #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/copy.hpp> class const_gsl_vector_iterator; /* * defines an iterator for gsl_vector */ class gsl_vector_iterator : public boost::iterator_facade< gsl_vector_iterator , double , boost::random_access_traversal_tag > { public : gsl_vector_iterator( void ): m_p(0) , m_stride( 0 ) { } explicit gsl_vector_iterator( gsl_vector *p ) : m_p( p->data ) , m_stride( p->stride ) { } friend gsl_vector_iterator end_iterator( gsl_vector * ); private : friend class boost::iterator_core_access; friend class const_gsl_vector_iterator; void increment( void ) { m_p += m_stride; } void decrement( void ) { m_p -= m_stride; } void advance( ptrdiff_t n ) { m_p += n*m_stride; } bool equal( const gsl_vector_iterator &other ) const { return this->m_p == other.m_p; } bool equal( const const_gsl_vector_iterator &other ) const; double& dereference( void ) const { return *m_p; } double *m_p; size_t m_stride; }; /* * defines an const iterator for gsl_vector */ class const_gsl_vector_iterator : public boost::iterator_facade< const_gsl_vector_iterator , const double , boost::random_access_traversal_tag > { public : const_gsl_vector_iterator( void ): m_p(0) , m_stride( 0 ) { } explicit const_gsl_vector_iterator( const gsl_vector *p ) : m_p( p->data ) , m_stride( p->stride ) { } const_gsl_vector_iterator( const gsl_vector_iterator &p ) : m_p( p.m_p ) , m_stride( p.m_stride ) { } private : friend class boost::iterator_core_access; friend class gsl_vector_iterator; friend const_gsl_vector_iterator end_iterator( const gsl_vector * ); void increment( void ) { m_p += m_stride; } void decrement( void ) { m_p -= m_stride; } void advance( ptrdiff_t n ) { m_p += n*m_stride; } bool equal( const const_gsl_vector_iterator &other ) const { return this->m_p == other.m_p; } bool equal( const gsl_vector_iterator &other ) const { return this->m_p == other.m_p; } const double& dereference( void ) const { return *m_p; } const double *m_p; size_t m_stride; }; bool gsl_vector_iterator::equal( const const_gsl_vector_iterator &other ) const { return this->m_p == other.m_p; } gsl_vector_iterator end_iterator( gsl_vector *x ) { gsl_vector_iterator iter( x ); iter.m_p += iter.m_stride * x->size; return iter; } const_gsl_vector_iterator end_iterator( const gsl_vector *x ) { const_gsl_vector_iterator iter( x ); iter.m_p += iter.m_stride * x->size; return iter; } namespace boost { template<> struct range_mutable_iterator< gsl_vector* > { typedef gsl_vector_iterator type; }; template<> struct range_const_iterator< gsl_vector* > { typedef const_gsl_vector_iterator type; }; } // namespace boost // template<> inline gsl_vector_iterator range_begin( gsl_vector *x ) { return gsl_vector_iterator( x ); } // template<> inline const_gsl_vector_iterator range_begin( const gsl_vector *x ) { return const_gsl_vector_iterator( x ); } // template<> inline gsl_vector_iterator range_end( gsl_vector *x ) { return end_iterator( x ); } // template<> inline const_gsl_vector_iterator range_end( const gsl_vector *x ) { return end_iterator( x ); } namespace boost { namespace numeric { namespace odeint { template<> struct is_resizeable< gsl_vector* > { //struct type : public boost::true_type { }; typedef boost::true_type type; const static bool value = type::value; }; template <> struct same_size_impl< gsl_vector* , gsl_vector* > { static bool same_size( const gsl_vector* x , const gsl_vector* y ) { return x->size == y->size; } }; template <> struct resize_impl< gsl_vector* , gsl_vector* > { static void resize( gsl_vector* &x , const gsl_vector* y ) { gsl_vector_free( x ); x = gsl_vector_alloc( y->size ); } }; template<> struct state_wrapper< gsl_vector* > { typedef double value_type; typedef gsl_vector* state_type; typedef state_wrapper< gsl_vector* > state_wrapper_type; state_type m_v; state_wrapper( ) { m_v = gsl_vector_alloc( 1 ); } state_wrapper( const state_wrapper_type &x ) { resize( m_v , x.m_v ); gsl_vector_memcpy( m_v , x.m_v ); } ~state_wrapper() { gsl_vector_free( m_v ); } }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_GSL_GSL_WRAPPER_HPP_INCLUDED odeint/external/mtl4/mtl4.hpp 0000644 00000001300 15125237305 0012116 0 ustar 00 /* [auto_generated] /boost/numeric/odeint/external/mtl4/mtl4.hpp [begin_description] includes all headers required for using mtl4 with odeint [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_EXTERNAL_MTL4_MTL4_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MTL4_MTL4_HPP_INCLUDED #include <boost/numeric/odeint/external/mtl4/mtl4_algebra_dispatcher.hpp> #include <boost/numeric/odeint/external/mtl4/mtl4_resize.hpp> #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_MTL4_MTL4_INCLUDED odeint/external/mtl4/mtl4_algebra_dispatcher.hpp 0000644 00000005272 15125237305 0016015 0 ustar 00 /* [auto_generated] boost/numeric/odeint/external/mtl4/mtl4_algebra_dispatcher.hpp [begin_description] specialization of the algebra dispatcher for mtl4 [end_description] Copyright 2013 Karsten Ahnert Copyright 2013 Mario Mulansky 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_ODEINT_MTL4_MTL4_ALGEBRA_DISPATCHER_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_MTL4_MTL4_ALGEBRA_DISPATCHER_HPP_INCLUDED #include <boost/numeric/mtl/mtl.hpp> #include <boost/numeric/odeint/algebra/vector_space_algebra.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> namespace boost { namespace numeric { namespace odeint { template<typename Value, typename Parameters> struct algebra_dispatcher< mtl::dense_vector< Value , Parameters > > { typedef vector_space_algebra algebra_type; }; template<typename Value, typename Parameters> struct algebra_dispatcher< mtl::dense2D< Value , Parameters > > { typedef vector_space_algebra algebra_type; }; template<typename Value , size_t BitMask , typename Parameters> struct algebra_dispatcher< mtl::morton_dense< Value , BitMask, Parameters > > { typedef vector_space_algebra algebra_type; }; template<typename Value, typename Parameters> struct algebra_dispatcher< mtl::compressed2D< Value , Parameters > > { typedef vector_space_algebra algebra_type; }; // specialization of infinity norm calculation template<typename Value, typename Parameters> struct vector_space_norm_inf< mtl::dense_vector< Value , Parameters > > { typedef Value result_type; Value operator()( const mtl::dense_vector< Value , Parameters > &x ) const { return mtl::infinity_norm(x); } }; template<typename Value, typename Parameters> struct vector_space_norm_inf< mtl::dense2D< Value , Parameters > > { typedef Value result_type; Value operator()( const mtl::dense2D< Value , Parameters > &x ) const { return mtl::infinity_norm(x); } }; template<typename Value , size_t BitMask , typename Parameters> struct vector_space_norm_inf< mtl::morton_dense< Value , BitMask , Parameters > > { typedef Value result_type; Value operator()( const mtl::morton_dense< Value , BitMask , Parameters > &x ) const { return mtl::infinity_norm(x); } }; template<typename Value, typename Parameters> struct vector_space_norm_inf< mtl::compressed2D< Value , Parameters > > { typedef Value result_type; Value operator()( const mtl::compressed2D< Value , Parameters > &x ) const { return mtl::infinity_norm(x); } }; } } } #endif // BOOST_NUMERIC_ODEINT_MTL4_MTL4_ALGEBRA_DISPATCHER_INCLUDED odeint/external/mtl4/mtl4_resize.hpp 0000644 00000010020 15125237305 0013476 0 ustar 00 /* [begin_description] Modification of the implicit Euler method, works with the MTL4 matrix library only. [end_description] Copyright 2012-2013 Andreas Angelopoulos Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_EXTERNAL_MTL4_RESIZE_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_MTL4_RESIZE_HPP_INCLUDED #include <boost/numeric/odeint/util/is_resizeable.hpp> #include <boost/numeric/odeint/util/resize.hpp> #include <boost/numeric/odeint/util/same_size.hpp> #include <boost/numeric/mtl/vector/dense_vector.hpp> #include <boost/numeric/mtl/matrix/dense2D.hpp> #include <boost/numeric/mtl/matrix/compressed2D.hpp> namespace boost { namespace numeric { namespace odeint { template< class Value , class Parameters > struct is_resizeable< mtl::dense_vector< Value , Parameters > > { typedef boost::true_type type; const static bool value = type::value; }; template< class Value , class Parameters > struct is_resizeable< mtl::dense2D< Value , Parameters > > { typedef boost::true_type type; const static bool value = type::value; }; template< class Value , class Parameters > struct is_resizeable< mtl::compressed2D< Value , Parameters > > { typedef boost::true_type type; const static bool value = type::value; }; template< class Value , class Parameters > struct same_size_impl< mtl::dense_vector< Value , Parameters > , mtl::dense_vector< Value , Parameters > > { static bool same_size( const mtl::dense_vector< Value , Parameters > &v1 , const mtl::dense_vector< Value , Parameters > &v2 ) { return mtl::size( v1 ) == mtl::size( v2 ); } }; template< class Value , class Parameters > struct resize_impl< mtl::dense_vector< Value , Parameters > , mtl::dense_vector< Value , Parameters > > { static void resize( mtl::dense_vector< Value , Parameters > &v1 , const mtl::dense_vector< Value , Parameters > &v2 ) { v1.change_dim( mtl::size( v2 ) ); } }; template< class Value , class MatrixParameters , class VectorParameters > struct same_size_impl< mtl::dense2D< Value , MatrixParameters > , mtl::dense_vector< Value , VectorParameters > > { static bool same_size( const mtl::dense2D< Value , MatrixParameters > &m , const mtl::dense_vector< Value , VectorParameters > &v ) { return ( ( mtl::size( v ) == m.num_cols() ) && ( mtl::size( v ) == m.num_rows() ) ); } }; template< class Value , class MatrixParameters , class VectorParameters > struct resize_impl< mtl::dense2D< Value , MatrixParameters > , mtl::dense_vector< Value , VectorParameters > > { static void resize( mtl::dense2D< Value , MatrixParameters > &m , const mtl::dense_vector< Value , VectorParameters > &v ) { m.change_dim( mtl::size( v ) , mtl::size( v ) , false ); } }; template< class Value , class MatrixParameters , class VectorParameters > struct same_size_impl< mtl::compressed2D< Value , MatrixParameters > , mtl::dense_vector< Value , VectorParameters > > { static bool same_size( const mtl::compressed2D< Value , MatrixParameters > &m , const mtl::dense_vector< Value , VectorParameters > &v ) { return ( ( mtl::size( v ) == m.num_cols() ) && ( mtl::size( v ) == m.num_rows() ) ); } }; template< class Value , class MatrixParameters , class VectorParameters > struct resize_impl< mtl::compressed2D< Value , MatrixParameters > , mtl::dense_vector< Value , VectorParameters > > { static void resize( mtl::compressed2D< Value , MatrixParameters > &m , const mtl::dense_vector< Value , VectorParameters > &v ) { m.change_dim( mtl::size( v ) , mtl::size( v ) ); } }; } // namespace odeint } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_MTL4_RESIZE_HPP_INCLUDED odeint/external/mtl4/implicit_euler_mtl4.hpp 0000644 00000011042 15125237305 0015210 0 ustar 00 /* [begin_description] Modification of the implicit Euler method, works with the MTL4 matrix library only. [end_description] Copyright 2012-2013 Andreas Angelopoulos Copyright 2012-2013 Karsten Ahnert Copyright 2012-2013 Mario Mulansky 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_ODEINT_EXTERNAL_IMPLICIT_EULER_MTL4_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_EXTERNAL_IMPLICIT_EULER_MTL4_HPP_INCLUDED #include <utility> #include <boost/numeric/odeint/util/bind.hpp> #include <boost/numeric/odeint/util/unwrap_reference.hpp> #include <boost/numeric/odeint/stepper/stepper_categories.hpp> #include <boost/numeric/odeint/external/mtl4/mtl4_resize.hpp> #include <boost/numeric/mtl/mtl.hpp> #include <boost/numeric/itl/itl.hpp> namespace boost { namespace numeric { namespace odeint { template< class ValueType , class Resizer = initially_resizer > class implicit_euler_mtl4 { public: typedef ValueType value_type; typedef value_type time_type; typedef mtl::dense_vector<value_type> state_type; typedef state_wrapper< state_type > wrapped_state_type; typedef state_type deriv_type; typedef state_wrapper< deriv_type > wrapped_deriv_type; typedef mtl::compressed2D< value_type > matrix_type; typedef state_wrapper< matrix_type > wrapped_matrix_type; typedef Resizer resizer_type; typedef stepper_tag stepper_category; typedef implicit_euler_mtl4< ValueType , Resizer > stepper_type; implicit_euler_mtl4( const value_type epsilon = 1E-6 ) : m_epsilon( epsilon ) , m_resizer() , m_dxdt() , m_x() , m_identity() , m_jacobi() { } template< class System > void do_step( System system , state_type &x , time_type t , time_type dt ) { typedef typename odeint::unwrap_reference< System >::type system_type; typedef typename odeint::unwrap_reference< typename system_type::first_type >::type deriv_func_type; typedef typename odeint::unwrap_reference< typename system_type::second_type >::type jacobi_func_type; system_type &sys = system; deriv_func_type &deriv_func = sys.first; jacobi_func_type &jacobi_func = sys.second; m_resizer.adjust_size( x , detail::bind( &stepper_type::template resize_impl< state_type > , detail::ref( *this ) , detail::_1 ) ); m_identity.m_v = 1; t += dt; m_x.m_v = x; deriv_func( x , m_dxdt.m_v , t ); jacobi_func( x , m_jacobi.m_v , t ); m_dxdt.m_v *= -dt; m_jacobi.m_v *= dt; m_jacobi.m_v -= m_identity.m_v ; // using ilu_0 preconditioning -incomplete LU factorisation // itl::pc::diagonal<matrix_type,double> L(m_jacobi.m_v); itl::pc::ilu_0<matrix_type> L( m_jacobi.m_v ); solve( m_jacobi.m_v , m_x.m_v , m_dxdt.m_v , L ); x+= m_x.m_v; } template< class StateType > void adjust_size( const StateType &x ) { resize_impl( x ); } private: /* Applying approximate iterative linear solvers default solver is Biconjugate gradient stabilized method itl::bicgstab(A, x, b, L, iter); */ template < class LinearOperator, class HilbertSpaceX, class HilbertSpaceB, class Preconditioner> void solve(const LinearOperator& A, HilbertSpaceX& x, const HilbertSpaceB& b, const Preconditioner& L, int max_iteractions =500) { // Termination criterion: r < 1e-6 * b or N iterations itl::basic_iteration< double > iter( b , max_iteractions , 1e-6 ); itl::bicgstab( A , x , b , L , iter ); } template< class StateIn > bool resize_impl( const StateIn &x ) { bool resized = false; resized |= adjust_size_by_resizeability( m_dxdt , x , typename is_resizeable<deriv_type>::type() ); resized |= adjust_size_by_resizeability( m_x , x , typename is_resizeable<state_type>::type() ); resized |= adjust_size_by_resizeability( m_identity , x , typename is_resizeable<matrix_type>::type() ); resized |= adjust_size_by_resizeability( m_jacobi , x , typename is_resizeable<matrix_type>::type() ); return resized; } private: value_type m_epsilon; resizer_type m_resizer; wrapped_deriv_type m_dxdt; wrapped_state_type m_x; wrapped_matrix_type m_identity; wrapped_matrix_type m_jacobi; }; } // odeint } // numeric } // boost #endif // BOOST_NUMERIC_ODEINT_EXTERNAL_IMPLICIT_EULER_MTL4_HPP_INCLUDED interval.hpp 0000644 00000002042 15125237305 0007102 0 ustar 00 /* 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 ublas/expression_types.hpp 0000644 00000044043 15125237305 0012016 0 ustar 00 // Copyright (c) 2000-2013 // 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 ublas/matrix_proxy.hpp 0000644 00000611426 15125237305 0011145 0 ustar 00 // // 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/tags.hpp 0000644 00000001333 15125237305 0007324 0 ustar 00 /** * -*- 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 ublas/doxydoc.hpp 0000644 00000007767 15125237305 0010060 0 ustar 00 // Copyright (c) 2010-2011 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) /** \mainpage BOOST uBLAS: a Linear Algebra Library * * This is the API Reference Documentation. * * \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 */ ublas/operation_blocked.hpp 0000644 00000032765 15125237305 0012066 0 ustar 00 // // 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 ublas/functional.hpp 0000644 00000235741 15125237305 0010544 0 ustar 00 // // 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/core/ignore_unused.hpp> #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) { typedef typename E::size_type vector_size_type; vector_size_type size (e ().size ()); #ifndef BOOST_UBLAS_SCALED_NORM real_type t = real_type (); for (vector_size_type i = 0; i < size; ++ i) { real_type u (type_traits<value_type>::norm_2 (e () (i))); t += u * u; } return static_cast<result_type>(type_traits<real_type>::type_sqrt (t)); #else real_type scale = real_type (); real_type sum_squares (1); for (vector_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 static_cast<result_type>(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 static_cast<result_type>(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 static_cast<result_type>(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 static_cast<result_type>(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 static_cast<result_type>(scale * type_traits<real_type>::type_sqrt (sum_squares)); #endif } }; template<class V> struct vector_norm_2_square : 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_2 (e () (i))); t += u * 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_2 (*it)); t += u * 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_2 (*it)); t += u * u; ++ it; } return t; } }; 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) { for (;;) { 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 (); for (;;) { 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 (); for (;;) { 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 boost::ignore_unused(j); 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 (); for (;;) { 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 ()); boost::ignore_unused(size_i, size_j); // 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 ublas/fwd.hpp 0000644 00000016057 15125237305 0007157 0 ustar 00 // // 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> #ifdef BOOST_UBLAS_CPP_GE_2011 #include <array> #endif 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; #ifdef BOOST_UBLAS_CPP_GE_2011 template<class T, std::size_t N, class A = std::array<T, N> > class fixed_vector; #endif template<class T, std::size_t N> class bounded_vector; 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; #ifdef BOOST_UBLAS_CPP_GE_2011 template<class T, std::size_t M, std::size_t N, class L = row_major, class A = std::array<T, M*N> > class fixed_matrix; #endif template<class T, std::size_t M, std::size_t N, class L = row_major> class bounded_matrix; 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 ublas/opencl/misc.hpp 0000644 00000013713 15125237305 0010606 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_misc_hpp_ #define boost_numeric_ublas_opencl_misc_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/opencl/vector.hpp> #include <boost/numeric/ublas/opencl/matrix.hpp> namespace boost { namespace numeric { namespace ublas { namespace opencl { template <typename T> typename std::enable_if<is_numeric<T>::value, T>::type a_sum(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue) { compute::vector<T> scratch_buffer(v.size(), queue.get_context()); compute::vector<T> result_buffer(1, queue.get_context()); cl_event event; if (std::is_same<T, float>::value) clblasSasum(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, double>::value) clblasDasum(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, std::complex<float>>::value) clblasScasum(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, std::complex<double>>::value) clblasDzasum(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event clWaitForEvents(1, &event); return result_buffer[0]; } template <typename T, typename A> typename std::enable_if<is_numeric<T>::value, T>::type a_sum(ublas::vector<T, A> const &v, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); return a_sum(vdev, queue); } template <typename T> typename std::enable_if<std::is_same<T, float>::value | std::is_same<T, double>::value, T>::type norm_1(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue) { return a_sum(v, queue); } template <typename T, typename A> typename std::enable_if<std::is_same<T, float>::value | std::is_same<T, double>::value, T>::type norm_1(ublas::vector<T, A> const &v, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); return norm_1(vdev, queue); } template <typename T> typename std::enable_if<is_numeric<T>::value, T>::type norm_2(ublas::vector<T, opencl::storage> const &v, compute::command_queue& queue) { compute::vector<T> scratch_buffer(2*v.size(), queue.get_context()); compute::vector<T> result_buffer(1, queue.get_context()); cl_event event; if (std::is_same<T, float>::value) clblasSnrm2(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, double>::value) clblasDnrm2(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, std::complex<float>>::value) clblasScnrm2(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event else if (std::is_same<T, std::complex<double>>::value) clblasDznrm2(v.size(), result_buffer.begin().get_buffer().get(), //result buffer 0, //offset in result buffer v.begin().get_buffer().get(), //input buffer 0, //offset in input buffer 1, //increment in input buffer scratch_buffer.begin().get_buffer().get(), 1, //number of command queues &(queue.get()), //queue 0, // number of events waiting list NULL, //event waiting list &event); //event clWaitForEvents(1, &event); return result_buffer[0]; } template <typename T, typename A> typename std::enable_if<is_numeric<T>::value, T>::type norm_2(ublas::vector<T, A> const &v, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); return norm_2(vdev, queue); } }}}} #endif ublas/opencl/operations.hpp 0000644 00000001060 15125237305 0012026 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_operations_hpp_ #define boost_numeric_ublas_opencl_operations_hpp_ #include <boost/numeric/ublas/opencl/transpose.hpp> #include <boost/numeric/ublas/opencl/prod.hpp> #include <boost/numeric/ublas/opencl/elementwise.hpp> #include <boost/numeric/ublas/opencl/misc.hpp> #endif ublas/opencl/prod.hpp 0000644 00000032111 15125237305 0010610 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_prod_hpp_ #define boost_numeric_ublas_opencl_prod_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/opencl/vector.hpp> #include <boost/numeric/ublas/opencl/matrix.hpp> #include <boost/numeric/ublas/opencl/transpose.hpp> #include <boost/compute/buffer.hpp> namespace boost { namespace numeric { namespace ublas { namespace opencl { #define ONE_DOUBLE_COMPLEX {{1.0, 00.0}} #define ONE_FLOAT_COMPLEX {{1.0f, 00.0f}} template <typename T, typename L1, typename L2> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L1, opencl::storage> &result, compute::command_queue &queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); assert(a.size2() == b.size1()); result.fill(0, queue); //to hold matrix b with layout 1 if the b has different layout std::unique_ptr<ublas::matrix<T, L1, opencl::storage>> bl1; cl_event event = NULL; cl_mem buffer_a = a.begin().get_buffer().get(); cl_mem buffer_b = b.begin().get_buffer().get(); cl_mem buffer_result = result.begin().get_buffer().get(); if (!(std::is_same<L1, L2>::value)) { bl1.reset(new ublas::matrix<T, L1, opencl::storage>(b.size1(), b.size2(), queue.get_context())); change_layout(b, *bl1, queue); buffer_b = bl1->begin().get_buffer().get(); } clblasOrder Order = std::is_same<L1, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor; size_t lda = Order == clblasRowMajor ? a.size2() : a.size1(); size_t ldb = Order == clblasRowMajor ? b.size2() : a.size2(); size_t ldc = Order == clblasRowMajor ? b.size2() : a.size1(); if (std::is_same<T, float>::value) clblasSgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), b.size2(), a.size2(), 1, buffer_a, 0, lda, buffer_b, 0, ldb, 1, buffer_result, 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, double>::value) clblasDgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), b.size2(), a.size2(), 1, buffer_a, 0, lda, buffer_b, 0, ldb, 1, buffer_result, 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<float>>::value) clblasCgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), b.size2(), a.size2(), ONE_FLOAT_COMPLEX, buffer_a, 0, lda, buffer_b, 0, ldb, ONE_FLOAT_COMPLEX, buffer_result, 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<double>>::value) clblasZgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), b.size2(), a.size2(), ONE_DOUBLE_COMPLEX, buffer_a, 0, lda, buffer_b, 0, ldb, ONE_DOUBLE_COMPLEX, buffer_result, 0, ldc, 1, &(queue.get()), 0, NULL, &event); clWaitForEvents(1, &event); } template <typename T, typename L1, typename L2, typename A> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L1, A> &result, compute::command_queue &queue) { ublas::matrix<T, L1, opencl::storage> adev(a, queue); ublas::matrix<T, L2, opencl::storage> bdev(b, queue); ublas::matrix<T, L1, opencl::storage> rdev(a.size1(), b.size2(), queue.get_context()); prod(adev, bdev, rdev, queue); rdev.to_host(result,queue); } template <typename T, typename L1, typename L2, typename A> typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L1, A>>::type prod(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, compute::command_queue &queue) { ublas::matrix<T, L1, A> result(a.size1(), b.size2()); prod(a, b, result, queue); return result; } template <typename T, typename L> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::matrix<T, L, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue &queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); assert(a.size2() == b.size()); result.fill(0, queue); cl_event event = NULL; clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor; int lda = Order == clblasRowMajor ? a.size2() : a.size1(); int ldb = Order == clblasRowMajor ? 1 : a.size2(); int ldc = Order == clblasRowMajor ? 1 : a.size1(); if (std::is_same<T, float>::value) clblasSgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), 1, a.size2(), 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, double>::value) clblasDgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), 1, a.size2(), 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<float>>::value) clblasCgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), 1, a.size2(), ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<double>>::value) clblasZgemm(Order, clblasNoTrans, clblasNoTrans, a.size1(), 1, a.size2(), ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); clWaitForEvents(1, &event); } template <typename T, typename L, typename A> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::matrix<T, L, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { ublas::matrix<T, L, opencl::storage> adev(a, queue); ublas::vector<T, opencl::storage> bdev(b, queue); ublas::vector<T, opencl::storage> rdev(a.size1(), queue.get_context()); prod(adev, bdev, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename L, typename A> typename std::enable_if<is_numeric<T>::value, ublas::vector<T, A>>::type prod(ublas::matrix<T, L, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { ublas::vector<T, A> result(a.size1()); prod(a, b, result, queue); return result; } template <typename T, typename L> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::vector<T, opencl::storage> const &a, ublas::matrix<T, L, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue &queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); assert(a.size() == b.size1()); result.fill(0, queue); cl_event event = NULL; clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor; size_t lda = Order == clblasRowMajor ? a.size() : 1; size_t ldb = Order == clblasRowMajor ? b.size2() : a.size(); size_t ldc = Order == clblasRowMajor ? b.size2() : 1; if (std::is_same<T, float>::value) clblasSgemm(Order, clblasNoTrans, clblasNoTrans, 1, b.size2(), a.size(), 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, double>::value) clblasDgemm(Order, clblasNoTrans, clblasNoTrans, 1, b.size2(), a.size(), 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<float>>::value) clblasCgemm(Order, clblasNoTrans, clblasNoTrans, 1, b.size2(), a.size(), ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<double>>::value) clblasZgemm(Order, clblasNoTrans, clblasNoTrans, 1, b.size2(), a.size(), ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); clWaitForEvents(1, &event); } template <class T, class L, class A> typename std::enable_if<is_numeric<T>::value>::type prod(ublas::vector<T, A> const &a, ublas::matrix<T, L, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { ublas::vector<T, opencl::storage> adev(a, queue); ublas::matrix<T, L, opencl::storage> bdev(b, queue); ublas::vector<T, opencl::storage> rdev(b.size2(), queue.get_context()); prod(adev, bdev, rdev, queue); rdev.to_host(result, queue); } template <class T, class L, class A> typename std::enable_if<is_numeric<T>::value, ublas::vector<T, A>>::type prod(ublas::vector<T, A> const &a, ublas::matrix<T, L, A> const &b, compute::command_queue &queue) { ublas::vector<T, A> result(b.size2()); prod(a, b, result, queue); return result; } template<class T> typename std::enable_if<std::is_fundamental<T>::value, T>::type inner_prod(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, compute::command_queue &queue) { assert(a.device() == b.device() && a.device() == queue.get_device()); assert(a.size() == b.size()); return compute::inner_product(a.begin(), a.end(), b.begin(), T(0), queue); } template<class T, class A> typename std::enable_if<std::is_fundamental<T>::value, T>::type inner_prod(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue& queue) { ublas::vector<T, opencl::storage> adev(a, queue); ublas::vector<T, opencl::storage> bdev(b, queue); return inner_prod(adev, bdev, queue); } template <class T, class L> typename std::enable_if<is_numeric<T>::value>::type outer_prod(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::matrix<T, L, opencl::storage> &result, compute::command_queue & queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); result.fill(0, queue); cl_event event = NULL; clblasOrder Order = std::is_same<L, ublas::basic_row_major<> >::value ? clblasRowMajor : clblasColumnMajor; size_t lda = Order == clblasRowMajor ? 1 : a.size(); size_t ldb = Order == clblasRowMajor ? b.size() : 1; size_t ldc = Order == clblasRowMajor ? b.size() : a.size(); if (std::is_same<T, float>::value) clblasSgemm(Order, clblasNoTrans, clblasNoTrans, a.size(), b.size(), 1, 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, double>::value) clblasDgemm(Order, clblasNoTrans, clblasNoTrans, a.size(), b.size(), 1, 1, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, 1, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<float>>::value) clblasCgemm(Order, clblasNoTrans, clblasNoTrans, a.size(), b.size(), 1, ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); else if (std::is_same<T, std::complex<double>>::value) clblasZgemm(Order, clblasNoTrans, clblasNoTrans, a.size(), b.size(), 1, ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, result.begin().get_buffer().get(), 0, ldc, 1, &(queue.get()), 0, NULL, &event); clWaitForEvents(1, &event); } template <class T, class L, class A> typename std::enable_if<is_numeric<T>::value>::type outer_prod(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::matrix<T, L, A> &result, compute::command_queue &queue) { ublas::vector<T, opencl::storage> adev(a, queue); ublas::vector<T, opencl::storage> bdev(b, queue); ublas::matrix<T, L, opencl::storage> rdev(a.size(), b.size(), queue.get_context()); outer_prod(adev, bdev, rdev, queue); rdev.to_host(result, queue); } template <class T,class L = ublas::basic_row_major<>, class A> typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L, A>>::type outer_prod(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { ublas::matrix<T, L, A> result(a.size(), b.size()); outer_prod(a, b, result, queue); return result; } #undef ONE_DOUBLE_COMPLEX #undef ONE_FLOAT_COMPLEX }}}} #endif ublas/opencl/transpose.hpp 0000644 00000013742 15125237305 0011673 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_transpose_hpp_ #define boost_numeric_ublas_opencl_transpose_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/opencl/vector.hpp> #include <boost/numeric/ublas/opencl/matrix.hpp> // Kernel for transposition of various data types #define OPENCL_TRANSPOSITION_KERNEL(DATA_TYPE) \ "__kernel void transpose(__global " #DATA_TYPE "* in, __global " #DATA_TYPE "* result, unsigned int width, unsigned int height) \n" \ "{ \n" \ " unsigned int column_index = get_global_id(0); \n" \ " unsigned int row_index = get_global_id(1); \n" \ " if (column_index < width && row_index < height) \n" \ " { \n" \ " unsigned int index_in = column_index + width * row_index; \n" \ " unsigned int index_result = row_index + height * column_index; \n" \ " result[index_result] = in[index_in]; \n" \ " } \n" \ "} \n" namespace boost { namespace numeric { namespace ublas { namespace opencl { template<class T, class L1, class L2> typename std::enable_if<is_numeric<T>::value>::type change_layout(ublas::matrix<T, L1, opencl::storage> const &m, ublas::matrix<T, L2, opencl::storage> &result, compute::command_queue& queue) { assert(m.size1() == result.size1() && m.size2() == result.size2()); assert(m.device() == result.device() && m.device() == queue.get_device()); assert(!(std::is_same<L1, L2>::value)); char const *kernel; if (std::is_same<T, float>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(float); else if (std::is_same<T, double>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(double); else if (std::is_same<T, std::complex<float>>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(float2); else if (std::is_same<T, std::complex<double>>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(double2); size_t len = strlen(kernel); cl_int err; cl_context c_context = queue.get_context().get(); cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err); clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL); cl_kernel c_kernel = clCreateKernel(program, "transpose", &err); size_t width = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size2() : m.size1(); size_t height = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size1() : m.size2(); size_t global_size[2] = { width , height }; clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get()); clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get()); clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width); clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height); cl_command_queue c_queue = queue.get(); cl_event event = NULL; clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event); clWaitForEvents(1, &event); } template<class T, class L1, class L2, class A> typename std::enable_if<is_numeric<T>::value>::type change_layout(ublas::matrix<T, L1, A> const &m, ublas::matrix<T, L2, A> &result, compute::command_queue& queue) { ublas::matrix<T, L1, opencl::storage> mdev(m, queue); ublas::matrix<T, L2, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context()); change_layout(mdev, rdev, queue); rdev.to_host(result, queue); } template<class T, class L> typename std::enable_if<is_numeric<T>::value>::type trans(ublas::matrix<T, L, opencl::storage> const &m, ublas::matrix<T, L, opencl::storage> &result, compute::command_queue& queue) { assert(m.size1() == result.size2() && m.size2() == result.size1()); assert(m.device() == result.device() && m.device() == queue.get_device()); char const *kernel; if (std::is_same<T, float>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(float); else if (std::is_same<T, double>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(double); else if (std::is_same<T, std::complex<float>>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(float2); else if (std::is_same<T, std::complex<double>>::value) kernel = OPENCL_TRANSPOSITION_KERNEL(double2); size_t len = strlen(kernel); cl_int err; cl_context c_context = queue.get_context().get(); cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err); clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL); cl_kernel c_kernel = clCreateKernel(program, "transpose", &err); size_t width = std::is_same <L, ublas::basic_row_major<>>::value ? m.size2() : m.size1(); size_t height = std::is_same <L, ublas::basic_row_major<>>::value ? m.size1() : m.size2(); size_t global_size[2] = { width , height }; clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get()); clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get()); clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width); clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height); cl_command_queue c_queue = queue.get(); cl_event event = NULL; clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event); clWaitForEvents(1, &event); } template<class T, class L, class A> typename std::enable_if<is_numeric<T>::value>::type trans(ublas::matrix<T, L, A> const &m, ublas::matrix<T, L, A> &result, compute::command_queue& queue) { ublas::matrix<T, L, opencl::storage> mdev(m, queue); ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context()); trans(mdev, rdev, queue); rdev.to_host(result, queue); } template<class T, class L, class A> typename std::enable_if<is_numeric<T>::value, ublas::matrix<T, L, A>>::type trans(ublas::matrix<T, L, A>& m, compute::command_queue& queue) { ublas::matrix<T, L, A> result(m.size2(), m.size1()); trans(m, result, queue); return result; } }}}} #endif ublas/opencl/vector.hpp 0000644 00000004317 15125237305 0011155 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_vector_hpp_ #define boost_numeric_ublas_opencl_vector_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/functional.hpp> #include <boost/compute/core.hpp> #include <boost/compute/algorithm.hpp> #include <boost/compute/buffer.hpp> #include <boost/compute/container/vector.hpp> namespace boost { namespace numeric { namespace ublas { namespace opencl { class storage; namespace compute = boost::compute; } // namespace opencl template <class T> class vector<T, opencl::storage> : public boost::compute::vector<T> { typedef std::size_t size_type; public: vector() : compute::vector<T>() {} vector(size_type size, compute::context context) : compute::vector<T>(size, context) { device_ = context.get_device();} vector(size_type size, T value, compute::command_queue queue) : compute::vector<T>(size, value, queue.get_context()) { queue.finish(); device_ = queue.get_device(); } template <typename A> vector(vector<T, A> const &v, compute::command_queue &queue) : vector(v.size(), queue.get_context()) { this->from_host(v, queue); } const compute::device device() const { return device_;} compute::device device() { return device_;} template<class A> void from_host(ublas::vector<T, A> const &v, compute::command_queue & queue) { assert(this->device() == queue.get_device()); compute::copy(v.begin(), v.end(), this->begin(), queue); queue.finish(); } template<class A> void to_host(ublas::vector<T, A>& v, compute::command_queue& queue) const { assert(this->device() == queue.get_device()); compute::copy(this->begin(), this->end(), v.begin(), queue); queue.finish(); } void fill(T value, compute::command_queue & queue) { assert(this->device() == queue.get_device()); compute::fill(this->begin(), this->end(), value, queue); queue.finish(); } private: compute::device device_; }; }}} #endif ublas/opencl/library.hpp 0000644 00000001505 15125237305 0011313 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_library_hpp_ #define boost_numeric_ublas_opencl_library_hpp_ #include <clBLAS.h> #include <type_traits> #include <complex> namespace boost { namespace numeric { namespace ublas { namespace opencl { class library { public: library() { clblasSetup();} ~library() { clblasTeardown();} }; template <typename T> struct is_numeric { static bool const value = std::is_same<T, float>::value | std::is_same<T, double>::value | std::is_same<T, std::complex<float>>::value | std::is_same<T, std::complex<double>>::value; }; }}}} #endif ublas/opencl/elementwise.hpp 0000644 00000040046 15125237305 0012173 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_elementwise_hpp_ #define boost_numeric_ublas_opencl_elementwise_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/opencl/vector.hpp> #include <boost/numeric/ublas/opencl/matrix.hpp> namespace boost { namespace numeric { namespace ublas { namespace opencl { namespace compute = boost::compute; namespace lambda = boost::compute::lambda; template <typename T, typename L1, typename L2, typename L3, class O> void element_wise(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L3, opencl::storage> &result, O op, compute::command_queue& queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); assert(a.size1() == b.size1() && a.size2() == b.size2()); compute::transform(a.begin(), a.end(), b.begin(), result.begin(), op, queue); queue.finish(); } template <typename T, typename L1, typename L2, typename L3, typename A, class O> void element_wise(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L3, A> &result, O op, compute::command_queue &queue) { ublas::matrix<T, L1, opencl::storage> adev(a, queue); ublas::matrix<T, L2, opencl::storage> bdev(b, queue); ublas::matrix<T, L3, opencl::storage> rdev(a.size1(), b.size2(), queue.get_context()); element_wise(adev, bdev, rdev, op, queue); rdev.to_host(result, queue); } template <typename T, typename L1, typename L2, typename A, typename O> ublas::matrix<T, L1, A> element_wise(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, O op, compute::command_queue &queue) { ublas::matrix<T, L1, A> result(a.size1(), b.size2()); element_wise(a, b, result, op, queue); return result; } template <typename T, typename O> void element_wise(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, O op, compute::command_queue& queue) { assert(a.device() == b.device() && a.device() == result.device() && a.device() == queue.get_device()); assert(a.size() == b.size()); compute::transform(a.begin(), a.end(), b.begin(), result.begin(), op, queue); queue.finish(); } template <typename T, typename A, typename O> void element_wise(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A>& result, O op, compute::command_queue &queue) { ublas::vector<T, opencl::storage> adev(a, queue); ublas::vector<T, opencl::storage> bdev(b, queue); ublas::vector<T, opencl::storage> rdev(a.size(), queue.get_context()); element_wise(adev, bdev, rdev, op, queue); rdev.to_host(result, queue); } template <typename T, typename A, typename O> ublas::vector<T, A> element_wise(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, O op, compute::command_queue &queue) { ublas::vector<T, A> result(a.size()); element_wise(a, b, result, op, queue); return result; } template <typename T, typename L1, typename L2, typename L3> void element_add(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L3, opencl::storage> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::plus<T>(), queue); } template <typename T, typename L1, typename L2, typename L3, typename A> void element_add(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L3, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::plus<T>(), queue); } template <typename T, typename L1, typename L2, typename A> ublas::matrix<T, L1, A> element_add(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::plus<T>(), queue); } template <typename T> void element_add(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::plus<T>(), queue); } template <typename T, typename A> void element_add(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::plus<T>(), queue); } template <typename T, typename A> ublas::vector<T, A> element_add(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::plus<T>(), queue); } template<typename T, typename L> void element_add(ublas::matrix<T, L, opencl::storage> const &m, T value, ublas::matrix<T, L, opencl::storage> &result, compute::command_queue& queue) { assert(m.device() == result.device() && m.device() == queue.get_device()); assert(m.size1() == result.size1() && m.size2() == result.size2()); compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 + value, queue); queue.finish(); } template<typename T, typename L, typename A> void element_add(ublas::matrix<T, L, A> const &m, T value, ublas::matrix<T, L, A> &result, compute::command_queue& queue) { ublas::matrix<T, L, opencl::storage> mdev(m, queue); ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context()); element_add(mdev, value, rdev, queue); rdev.to_host(result, queue); } template<typename T, typename L, typename A> ublas::matrix<T, L, A> element_add(ublas::matrix<T, L, A> const &m, T value, compute::command_queue& queue) { ublas::matrix<T, L, A> result(m.size1(), m.size2()); element_add(m, value, result, queue); return result; } template<typename T> void element_add(ublas::vector<T, opencl::storage> const &v, T value, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { assert(v.device() == result.device() && v.device() == queue.get_device()); assert(v.size() == result.size()); compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 + value, queue); queue.finish(); } template<typename T, typename A> void element_add(ublas::vector<T, A> const &v, T value, ublas::vector<T, A> &result, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context()); element_add(vdev, value, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename A> ublas::vector<T, A> element_add(ublas::vector<T, A> const &v, T value, compute::command_queue& queue) { ublas::vector<T, A> result(v.size()); element_add(v, value, result, queue); return result; } template <typename T, typename L1, typename L2, typename L3> void element_sub(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L3, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, compute::minus<T>(), result, queue); } template <typename T, typename L1, typename L2, typename L3, typename A> void element_sub(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L3, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::minus<T>(), queue); } template <typename T, typename L1, typename L2, typename A> ublas::matrix<T, L1, A> element_sub(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::minus<T>(), queue); } template <typename T> void element_sub(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::minus<T>(), queue); } template <typename T, typename A> void element_sub(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::minus<T>(), queue); } template <typename T, typename A> ublas::vector<T, A> element_sub(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::minus<T>(), queue); } template <typename T, typename L> void element_sub(ublas::matrix<T, L, opencl::storage> const &m, T value, ublas::matrix<T, L, opencl::storage> &result, compute::command_queue& queue) { assert(m.device() == result.device() && m.device() == queue.get_device()); assert(m.size1() == result.size1() && m.size2() == result.size2()); compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 - value, queue); queue.finish(); } template <typename T, typename L, typename A> void element_sub(ublas::matrix<T, L, A> const &m, T value, ublas::matrix<T, L, A> &result, compute::command_queue& queue) { ublas::matrix<T, L, opencl::storage> mdev(m, queue); ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context()); element_sub(mdev, value, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename L, typename A> ublas::matrix<T, L, A> element_sub(ublas::matrix<T, L, A> const &m, T value, compute::command_queue& queue) { ublas::matrix<T, L, A> result(m.size1(), m.size2()); element_sub(m, value, result, queue); return result; } template <typename T> void element_sub(ublas::vector<T, opencl::storage> const &v, T value, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { assert(v.device() == result.device() && v.device() == queue.get_device()); assert(v.size() == result.size()); compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 - value, queue); queue.finish(); } template <typename T, typename A> void element_sub(ublas::vector<T, A> const &v, T value, ublas::vector<T, A> &result, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context()); element_sub(vdev, value, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename A> ublas::vector<T, A> element_sub(ublas::vector<T, A> const &v, T value, compute::command_queue& queue) { ublas::vector<T, A> result(v.size()); element_sub(v, value, result, queue); return result; } template <typename T, typename L1, typename L2, typename L3> void element_prod(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L3, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::multiplies<T>(), queue); } template <typename T, typename L1, typename L2, typename L3, typename A> void element_prod(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L3, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::multiplies<T>(), queue); } template <typename T, typename L1, typename L2, typename A> ublas::matrix<T, L1, A> element_prod(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::multiplies<T>(), queue); } template <typename T> void element_prod(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::multiplies<T>(), queue); } template <typename T, typename A> void element_prod(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::multiplies<T>(), queue); } template <typename T, typename A> ublas::vector<T, A> element_prod(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::multiplies<T>(), queue); } template <typename T, typename L> void element_scale(ublas::matrix<T, L, opencl::storage> const &m, T value, ublas::matrix<T, L, opencl::storage> &result, compute::command_queue& queue) { assert(m.device() == result.device() && m.device() == queue.get_device()); assert(m.size1() == result.size1() && m.size2() == result.size2()); compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 * value, queue); queue.finish(); } template <typename T, typename L, typename A> void element_scale(ublas::matrix<T, L, A> const &m, T value, ublas::matrix<T, L, A> &result, compute::command_queue& queue) { ublas::matrix<T, L, opencl::storage> mdev(m, queue); ublas::matrix<T, L, opencl::storage> rdev(result.size1(), result.size2(), queue.get_context()); element_scale(mdev, value, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename L, typename A> ublas::matrix<T, L, A> element_scale(ublas::matrix<T, L, A> const &m, T value, compute::command_queue& queue) { ublas::matrix<T, L, A> result(m.size1(), m.size2()); element_scale(m, value, result, queue); return result; } template <typename T> void element_scale(ublas::vector<T, opencl::storage> const &v, T value, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { assert(v.device() == result.device() && v.device() == queue.get_device()); assert(v.size() == result.size()); compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 * value, queue); queue.finish(); } template <typename T, typename A> void element_scale(ublas::vector<T, A> const &v, T value, ublas::vector<T, A> & result, compute::command_queue& queue) { ublas::vector<T, opencl::storage> vdev(v, queue); ublas::vector<T, opencl::storage> rdev(v.size(), queue.get_context()); element_scale(vdev, value, rdev, queue); rdev.to_host(result, queue); } template <typename T, typename A> ublas::vector<T,A> element_scale(ublas::vector<T, A> const &v, T value, compute::command_queue& queue) { ublas::vector<T, A> result(v.size()); element_scale(v, value, result, queue); return result; } template <typename T, typename L1, typename L2, typename L3> void element_div(ublas::matrix<T, L1, opencl::storage> const &a, ublas::matrix<T, L2, opencl::storage> const &b, ublas::matrix<T, L3, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::divides<T>(), queue); } template <typename T, typename L1, typename L2, typename L3, typename A> void element_div(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, ublas::matrix<T, L3, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::divides<T>(), queue); } template <typename T, typename L1, typename L2, typename A> ublas::matrix<T, L1, A> element_div(ublas::matrix<T, L1, A> const &a, ublas::matrix<T, L2, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::divides<T>(), queue); } template <typename T> void element_div(ublas::vector<T, opencl::storage> const &a, ublas::vector<T, opencl::storage> const &b, ublas::vector<T, opencl::storage> &result, compute::command_queue& queue) { element_wise(a, b, result, compute::divides<T>(), queue); } template <typename T, typename A> void element_div(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, ublas::vector<T, A> &result, compute::command_queue &queue) { element_wise(a, b, result, compute::divides<T>(), queue); } template <typename T, typename A> ublas::vector<T, A> element_div(ublas::vector<T, A> const &a, ublas::vector<T, A> const &b, compute::command_queue &queue) { return element_wise(a, b, compute::divides<T>(), queue); } }}}} #endif ublas/opencl/matrix.hpp 0000644 00000007521 15125237305 0011157 0 ustar 00 // Boost.uBLAS // // Copyright (c) 2018 Fady Essam // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_matrix_hpp_ #define boost_numeric_ublas_opencl_matrix_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/functional.hpp> #include <boost/compute/core.hpp> #include <boost/compute/algorithm.hpp> #include <boost/compute/buffer.hpp> namespace boost { namespace numeric { namespace ublas { namespace opencl { class storage; namespace compute = boost::compute; } // namespace opencl template<class T, class L> class matrix<T, L, opencl::storage> : public matrix_container<matrix<T, L, opencl::storage> > { typedef typename boost::compute::buffer_allocator<T>::size_type size_type; typedef L layout_type; typedef matrix<T, L, opencl::storage> self_type; public: matrix() : matrix_container<self_type>(), size1_(0), size2_(0), data_() , device_() {} matrix(size_type size1, size_type size2, compute::context c) : matrix_container<self_type>(), size1_(size1), size2_(size2), device_(c.get_device()) { compute::buffer_allocator<T> allocator(c); data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer(); } matrix(size_type size1, size_type size2, T const &value, compute::command_queue &q) : matrix_container<self_type>(), size1_(size1), size2_(size2), device_(q.get_device()) { compute::buffer_allocator<T> allocator(q.get_context()); data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer(); compute::fill(this->begin(), this->end(), value, q); q.finish(); } template <typename A> matrix(matrix<T, L, A> const &m, compute::command_queue &queue) : matrix(m.size1(), m.size2(), queue.get_context()) { this->from_host(m, queue); } size_type size1() const { return size1_;} size_type size2() const { return size2_;} const compute::buffer_iterator<T> begin() const { return compute::make_buffer_iterator<T>(data_);} compute::buffer_iterator<T> begin() { return compute::make_buffer_iterator<T>(data_);} compute::buffer_iterator<T> end() { return compute::make_buffer_iterator<T>(data_, layout_type::storage_size(size1_, size2_));} const compute::buffer_iterator<T> end() const { return compute::make_buffer_iterator<T>(data_, layout_type::storage_size(size1_, size2_));} const compute::device &device() const { return device_;} compute::device &device() { return device_;} void fill(T value, compute::command_queue &queue) { assert(device_ == queue.get_device()); compute::fill(this->begin(), this->end(), value, queue); queue.finish(); } /** Copies a matrix to a device * \param m is a matrix that is not on the device _device and it is copied to it * \param queue is the command queue that will execute the operation */ template<class A> void from_host(ublas::matrix<T, L, A> const &m, compute::command_queue &queue) { assert(device_ == queue.get_device()); compute::copy(m.data().begin(), m.data().end(), this->begin(), queue); queue.finish(); } /** Copies a matrix from a device * \param m is a matrix that will be reized to (size1_,size2) and the values of (*this) will be copied in it * \param queue is the command queue that will execute the operation */ template<class A> void to_host(ublas::matrix<T, L, A> &m, compute::command_queue &queue) const { assert(device_ == queue.get_device()); compute::copy(this->begin(), this->end(), m.data().begin(), queue); queue.finish(); } private: size_type size1_; size_type size2_; compute::buffer data_; compute::device device_; }; }}} #endif ublas/matrix_vector.hpp 0000644 00000026323 15125237305 0011262 0 ustar 00 // Copyright (c) 2012 Oswin Krause // Copyright (c) 2013 Joaquim Duran // // 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_MATRIX_VECTOR_HPP #define BOOST_UBLAS_MATRIX_VECTOR_HPP #include <boost/numeric/ublas/matrix_proxy.hpp> //for matrix_row, matrix_column and matrix_expression #include <boost/numeric/ublas/vector.hpp> #include <boost/iterator/iterator_facade.hpp> #include <boost/range/iterator_range.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/utility/enable_if.hpp> namespace boost { namespace numeric { namespace ublas { namespace detail{ /** \brief Iterator used in the represention of a matrix as a vector of rows or columns * * Iterator used in the represention of a matrix as a vector of rows/columns. It refers * to the i-th element of the matrix, a column or a row depending of Reference type. * * The type of Reference should provide a constructor Reference(matrix, i) * * This iterator is invalidated when the underlying matrix is resized. * * \tparameter Matrix type of matrix that is represented as a vector of row/column * \tparameter Reference Matrix row or matrix column type. */ template<class Matrix, class Reference> class matrix_vector_iterator: public boost::iterator_facade< matrix_vector_iterator<Matrix,Reference>, typename vector_temporary_traits<Reference>::type, boost::random_access_traversal_tag, Reference >{ public: matrix_vector_iterator(){} ///\brief constructs a matrix_vector_iterator as pointing to the i-th proxy BOOST_UBLAS_INLINE matrix_vector_iterator(Matrix& matrix, std::size_t position) : matrix_(&matrix),position_(position) {} template<class M, class R> BOOST_UBLAS_INLINE matrix_vector_iterator(matrix_vector_iterator<M,R> const& other) : matrix_(other.matrix_),position_(other.position_) {} private: friend class boost::iterator_core_access; template <class M,class R> friend class matrix_vector_iterator; BOOST_UBLAS_INLINE void increment() { ++position_; } BOOST_UBLAS_INLINE void decrement() { --position_; } BOOST_UBLAS_INLINE void advance(std::ptrdiff_t n){ position_ += n; } template<class M,class R> BOOST_UBLAS_INLINE std::ptrdiff_t distance_to(matrix_vector_iterator<M,R> const& other) const{ BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ()); return (std::ptrdiff_t)other.position_ - (std::ptrdiff_t)position_; } template<class M,class R> BOOST_UBLAS_INLINE bool equal(matrix_vector_iterator<M,R> const& other) const{ BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ()); return (position_ == other.position_); } BOOST_UBLAS_INLINE Reference dereference() const { return Reference(*matrix_,position_); } Matrix* matrix_;//no matrix_closure here to ensure easy usage std::size_t position_; }; } /** \brief Represents a \c Matrix as a vector of rows. * * Implements an interface to Matrix that the underlaying matrix is represented as a * vector of rows. * * The vector could be resized which causes the resize of the number of rows of * the underlaying matrix. */ template<class Matrix> class matrix_row_vector { public: typedef ublas::matrix_row<Matrix> value_type; typedef ublas::matrix_row<Matrix> reference; typedef ublas::matrix_row<Matrix const> const_reference; typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_row<Matrix> > iterator; typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_row<Matrix const> const> const_iterator; typedef boost::reverse_iterator<iterator> reverse_iterator; typedef boost::reverse_iterator<const_iterator> const_reverse_iterator; typedef typename boost::iterator_difference<iterator>::type difference_type; typedef typename Matrix::size_type size_type; BOOST_UBLAS_INLINE explicit matrix_row_vector(Matrix& matrix) : matrix_(&matrix) { } BOOST_UBLAS_INLINE iterator begin(){ return iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator begin() const { return const_iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator cbegin() const { return begin(); } BOOST_UBLAS_INLINE iterator end() { return iterator(*matrix_, matrix_->size1()); } BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator(*matrix_, matrix_->size1()); } BOOST_UBLAS_INLINE const_iterator cend() const { return end(); } BOOST_UBLAS_INLINE reverse_iterator rbegin() { return reverse_iterator(end()); } BOOST_UBLAS_INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } BOOST_UBLAS_INLINE const_reverse_iterator crbegin() const { return rbegin(); } BOOST_UBLAS_INLINE reverse_iterator rend() { return reverse_iterator(begin()); } BOOST_UBLAS_INLINE const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } BOOST_UBLAS_INLINE const_reverse_iterator crend() const { return end(); } BOOST_UBLAS_INLINE value_type operator()(size_type index) { return value_type(*matrix_, index); } BOOST_UBLAS_INLINE value_type operator()(size_type index) const { return value_type(*matrix_, index); } BOOST_UBLAS_INLINE reference operator[](size_type index){ return (*this) (index); } BOOST_UBLAS_INLINE const_reference operator[](size_type index) const { return (*this) (index); } BOOST_UBLAS_INLINE size_type size() const { return matrix_->size1(); } BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { matrix_->resize(size, matrix_->size2(), preserve); } private: Matrix* matrix_; }; /** \brief Convenience function to create \c matrix_row_vector. * * Function to create \c matrix_row_vector objects. * \param matrix the \c matrix_expression that generates the matrix that \c matrix_row_vector is referring. * \return Created \c matrix_row_vector object. * * \tparam Matrix the type of matrix that \c matrix_row_vector is referring. */ template<class Matrix> BOOST_UBLAS_INLINE matrix_row_vector<Matrix> make_row_vector(matrix_expression<Matrix>& matrix){ return matrix_row_vector<Matrix>(matrix()); } /** \brief Convenience function to create \c matrix_row_vector. * * Function to create \c matrix_row_vector objects. * \param matrix the \c matrix_expression that generates the matrix that \c matrix_row_vector is referring. * \return Created \c matrix_row_vector object. * * \tparam Matrix the type of matrix that \c matrix_row_vector is referring. */ template<class Matrix> BOOST_UBLAS_INLINE matrix_row_vector<Matrix const> make_row_vector(matrix_expression<Matrix> const& matrix){ return matrix_row_vector<Matrix const>(matrix()); } /** \brief Represents a \c Matrix as a vector of columns. * * Implements an interface to Matrix that the underlaying matrix is represented as a * vector of columns. * * The vector could be resized which causes the resize of the number of columns of * the underlaying matrix. */ template<class Matrix> class matrix_column_vector { public: typedef ublas::matrix_column<Matrix> value_type; typedef ublas::matrix_column<Matrix> reference; typedef const ublas::matrix_column<Matrix const> const_reference; typedef ublas::detail::matrix_vector_iterator<Matrix, ublas::matrix_column<Matrix> > iterator; typedef ublas::detail::matrix_vector_iterator<Matrix const, ublas::matrix_column<Matrix const> const > const_iterator; typedef boost::reverse_iterator<iterator> reverse_iterator; typedef boost::reverse_iterator<const_iterator> const_reverse_iterator; typedef typename boost::iterator_difference<iterator>::type difference_type; typedef typename Matrix::size_type size_type; BOOST_UBLAS_INLINE explicit matrix_column_vector(Matrix& matrix) : matrix_(&matrix){ } BOOST_UBLAS_INLINE iterator begin() { return iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator begin() const { return const_iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator cbegin() const { return begin(); } BOOST_UBLAS_INLINE iterator end() { return iterator(*matrix_, matrix_->size2()); } BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator(*matrix_, matrix_->size2()); } BOOST_UBLAS_INLINE const_iterator cend() const { return end(); } BOOST_UBLAS_INLINE reverse_iterator rbegin() { return reverse_iterator(end()); } BOOST_UBLAS_INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } BOOST_UBLAS_INLINE const_reverse_iterator crbegin() const { return rbegin(); } BOOST_UBLAS_INLINE reverse_iterator rend() { return reverse_iterator(begin()); } BOOST_UBLAS_INLINE const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } BOOST_UBLAS_INLINE const_reverse_iterator crend() const { return rend(); } BOOST_UBLAS_INLINE value_type operator()(size_type index) { return value_type(*matrix_, index); } BOOST_UBLAS_INLINE value_type operator()(size_type index) const { return value_type(*matrix_, index); } BOOST_UBLAS_INLINE reference operator[](size_type index) { return (*this) (index); } BOOST_UBLAS_INLINE const_reference operator[](size_type index) const { return (*this) (index); } BOOST_UBLAS_INLINE size_type size() const { return matrix_->size2(); } BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { matrix_->resize(matrix_->size1(), size, preserve); } private: Matrix* matrix_; }; /** \brief Convenience function to create \c matrix_column_vector. * * Function to create \c matrix_column_vector objects. * \param matrix the \c matrix_expression that generates the matrix that \c matrix_column_vector is referring. * \return Created \c matrix_column_vector object. * * \tparam Matrix the type of matrix that \c matrix_column_vector is referring. */ template<class Matrix> BOOST_UBLAS_INLINE matrix_column_vector<Matrix> make_column_vector(matrix_expression<Matrix>& matrix){ return matrix_column_vector<Matrix>(matrix()); } /** \brief Convenience function to create \c matrix_column_vector. * * Function to create \c matrix_column_vector objects. * \param matrix the \c matrix_expression that generates the matrix that \c matrix_column_vector is referring. * \return Created \c matrix_column_vector object. * * \tparam Matrix the type of matrix that \c matrix_column_vector is referring. */ template<class Matrix> BOOST_UBLAS_INLINE matrix_column_vector<Matrix const> make_column_vector(matrix_expression<Matrix> const& matrix){ return matrix_column_vector<Matrix const>(matrix()); } }}} #endif ublas/experimental/sparse_view.hpp 0000644 00000024324 15125237305 0013417 0 ustar 00 // // 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> #include <boost/numeric/ublas/storage.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_(o.size1_), size2_(o.size2_), nnz_(o.nnz_), index1_data_(o.index1_data_), index2_data_(o.index2_data_), value_data_(o.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 ublas/operations.hpp 0000644 00000001343 15125237305 0010552 0 ustar 00 /** * -*- 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 ublas/operation/begin.hpp 0000644 00000024103 15125237305 0011452 0 ustar 00 /** * -*- 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 ublas/operation/c_array.hpp 0000644 00000001675 15125237305 0012017 0 ustar 00 /** * -*- 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 ublas/operation/num_rows.hpp 0000644 00000002207 15125237305 0012240 0 ustar 00 /** * -*- c++ -*- * * \file num_rows.hpp * * \brief The \c num_rows operation. * * Copyright (c) 2009-2012, 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> #include <boost/numeric/ublas/expression_types.hpp> #include <boost/numeric/ublas/traits.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 matrix_traits<MatrixExprT>::size_type num_rows(matrix_expression<MatrixExprT> const& me) { return me().size1(); } }}} // Namespace boost::numeric::ublas #endif // BOOST_NUMERIC_UBLAS_OPERATION_NUM_ROWS_HPP ublas/operation/end.hpp 0000644 00000026032 15125237305 0011137 0 ustar 00 /** * -*- 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 ublas/operation/size.hpp 0000644 00000023603 15125237305 0011344 0 ustar 00 /** * \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>::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>::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>::apply(me); } }}} // Namespace boost::numeric::ublas #endif // BOOST_NUMERIC_UBLAS_OPERATION_SIZE_HPP ublas/operation/num_columns.hpp 0000644 00000002233 15125237305 0012725 0 ustar 00 /** * -*- 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> #include <boost/numeric/ublas/expression_types.hpp> #include <boost/numeric/ublas/traits.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 matrix_traits<MatrixExprT>::size_type num_columns(matrix_expression<MatrixExprT> const& me) { return me().size2(); } }}} // Namespace boost::numeric::ublas #endif // BOOST_NUMERIC_UBLAS_OPERATION_NUM_COLUMNS_HPP ublas/vector_of_vector.hpp 0000644 00000150026 15125237305 0011742 0 ustar 00 // // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/matrix_expression.hpp 0000644 00000512204 15125237305 0012155 0 ustar 00 // // 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 #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); } #else BOOST_UBLAS_INLINE reference operator () (size_type i) const { return expression () (i); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return expression ().end1 (); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return 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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return expression ().end2 (); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 == typename E2::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 : typename E2::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 == typename E1::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 : typename E1::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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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)); } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { return functor_type::apply (e_ (i)); } // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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); } // 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); } // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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)); } // Element access 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 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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); if (it1_.index1 () == i_) t1 = *it1_; } typename E2::value_type t2 = typename E2::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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); if (it1_.index1 () == i_) t1 = *it1_; } typename E2::value_type t2 = typename E2::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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); if (it1_.index2 () == j_) t1 = *it1_; } typename E2::value_type t2 = typename E2::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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); if (it1_.index2 () == j_) t1 = *it1_; } typename E2::value_type t2 = typename E2::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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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)); } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { return functor_type::apply (expression1_type (e1_), e2_ (i)); } // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 boost::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_)); } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { return functor_type::apply (e1_ (i), 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 boost::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 boost::enable_if< is_convertible<T2, typename E1::value_type>, typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<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_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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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); } // 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_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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/opencl.hpp 0000644 00000000752 15125237305 0007652 0 ustar 00 // // Copyright (c) 2018 Stefan Seefeld // // 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_ublas_opencl_hpp_ #define boost_numeric_ublas_opencl_hpp_ #include <boost/numeric/ublas/opencl/library.hpp> #include <boost/numeric/ublas/opencl/vector.hpp> #include <boost/numeric/ublas/opencl/matrix.hpp> #include <boost/numeric/ublas/opencl/operations.hpp> #endif ublas/operation_sparse.hpp 0000644 00000017722 15125237305 0011754 0 ustar 00 // // 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 ublas/traits/c_array.hpp 0000644 00000005426 15125237305 0011323 0 ustar 00 /** * -*- 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 ublas/traits/const_iterator_type.hpp 0000644 00000010255 15125237305 0013777 0 ustar 00 /** * -*- 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 ublas/traits/iterator_type.hpp 0000644 00000007716 15125237305 0012601 0 ustar 00 /** * -*- 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 ublas/blas.hpp 0000644 00000043324 15125237305 0007315 0 ustar 00 // Copyright (c) 2000-2011 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_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 ublas/vector_expression.hpp 0000644 00000200427 15125237305 0012154 0 ustar 00 // // 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return expression ().end (); } BOOST_UBLAS_INLINE const_iterator cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) if (it1_.index () == i_) t1 = *it1_; typename E2::value_type t2 = typename E2::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 { typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) if (it1_.index () == i_) t1 = *it1_; typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) if (it2_.index () == i_) t2 = *it2_; return static_cast<value_type>(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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return end (); } 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 boost::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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 boost::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 boost::enable_if< is_convertible<T2, typename E1::value_type >, typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<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_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_2_square v = sum(v [i] * v [i]) // complex: norm_2_square v = sum(v [i] * conj (v [i])) template<class E> BOOST_UBLAS_INLINE typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::result_type norm_2_square (const vector_expression<E> &e) { typedef typename vector_scalar_unary_traits<E, vector_norm_2_square<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 ublas/hermitian.hpp 0000644 00000307160 15125237305 0010355 0 ustar 00 // // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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_iterator1 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2(); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return end (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1(); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/vector.hpp 0000644 00000316705 15125237305 0007704 0 ustar 00 // // Copyright (c) 2000-2010 // Joerg Walter, Mathias Koch, David Bellot // Copyright (c) 2014, Athanasios Iliopoulos // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // 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/config.hpp> #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> #ifdef BOOST_UBLAS_CPP_GE_2011 #include <array> #include <initializer_list> #if defined(BOOST_MSVC) // For std::forward in fixed_vector #include <utility> #endif #endif // 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 on the first element of the vector BOOST_UBLAS_INLINE const_iterator cbegin () const { return begin (); } /// \brief return an iterator after the last element of the vector BOOST_UBLAS_INLINE const_iterator end () const { return find (data_.size ()); } /// \brief return an iterator after the last element of the vector BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 before the first element of the reversed vector (i.e. end() of normal vector) BOOST_UBLAS_INLINE const_reverse_iterator crbegin () const { return rbegin (); } /// \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 on the end of the reverse vector (i.e. first element of the normal vector) BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } /// \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_; }; #ifdef BOOST_UBLAS_CPP_GE_2011 /** \brief A dense vector of values of type \c T. * * For a \f$n\f$-dimensional vector \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped * to the \f$i\f$-th element of the container. A storage type \c A can be specified which defaults to \c std::array. * Elements are constructed by \c A, which need not initialise their value. * * \tparam T type of the objects stored in the vector (like int, double, complex,...) * \tparam A The type of the storage array of the vector. Default is \c std::array<T>. */ template<class T, std::size_t N, class A> class fixed_vector: public vector_container<fixed_vector<T, N, A> > { typedef fixed_vector<T, N, A> self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using vector_container<self_type>::operator (); #endif typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef T value_type; typedef typename type_traits<T>::const_reference const_reference; typedef T &reference; typedef T *pointer; typedef const T *const_pointer; typedef A array_type; typedef const vector_reference<const self_type> const_closure_type; typedef vector_reference<self_type> closure_type; typedef self_type vector_temporary_type; typedef dense_tag storage_category; // Construction and destruction /// \brief Constructor of a fixed_vector BOOST_UBLAS_INLINE fixed_vector (): vector_container<self_type> (), data_ () {} /// \brief Constructor of a fixed_vector by copying from another container /// This type uses the generic name \c array_type within the vector definition. /// \param data container of type \c A BOOST_UBLAS_INLINE fixed_vector (const array_type &data): vector_container<self_type> (), data_ (data) {} /// \brief Constructor of a fixed_vector with a unique initial value /// \param init value to assign to each element of the vector BOOST_UBLAS_INLINE fixed_vector (const value_type &init): vector_container<self_type> (), data_ () { data_.fill( init ); } /// \brief Copy-constructor of a fixed_vector /// \param v is the fixed_vector to be duplicated BOOST_UBLAS_INLINE fixed_vector (const fixed_vector &v): vector_container<self_type> (), data_ (v.data_) {} /// \brief Copy-constructor of a vector from a vector_expression /// Depending on the vector_expression, this constructor can have the cost of the computations /// of the expression (trivial to say it, but take it must be taken into account in your complexity calculations). /// \param ae the vector_expression which values will be duplicated into the vector template<class AE> BOOST_UBLAS_INLINE fixed_vector (const vector_expression<AE> &ae): vector_container<self_type> (), data_ ( ) { vector_assign<scalar_assign> (*this, ae); } /// \brief Construct a fixed_vector from a list of values /// This constructor enables initialization by using any of: /// fixed_vector<double, 3> v = { 1, 2, 3 } or fixed_vector<double,3> v( {1, 2, 3} ) or fixed_vector<double,3> v( 1, 2, 3 ) template <typename... Types> BOOST_UBLAS_INLINE fixed_vector(value_type v0, Types... vrest) : vector_container<self_type> (), data_( array_type{ v0, vrest... } ) {} // ----------------------- // Random Access Container // ----------------------- /// \brief Return the maximum size of the data container. /// Return the upper bound (maximum size) on the data container. Depending on the container, it can be bigger than the current size of the vector. BOOST_UBLAS_INLINE size_type max_size () const { return data_.max_size (); } /// \brief Return true if the vector is empty (\c size==0) /// \return \c true if empty, \c false otherwise BOOST_UBLAS_INLINE const bool &empty () const { return data_.empty(); } // --------- // Accessors // --------- /// \brief Return the size of the vector BOOST_UBLAS_INLINE BOOST_CONSTEXPR size_type size () const{ // should have a const after C++14 return data_.size (); } // ----------------- // Storage accessors // ----------------- /// \brief Return a \c const reference to the container. Useful to access data directly for specific type of container. BOOST_UBLAS_INLINE const array_type &data () const { return data_; } /// \brief Return a reference to the container. Useful to speed-up write operations to the data in very specific case. BOOST_UBLAS_INLINE array_type &data () { return data_; } // --------------- // Element support // --------------- /// \brief Return a pointer to the element \f$i\f$ /// \param i index of the element // XXX this semantic is not the one expected by the name of this method BOOST_UBLAS_INLINE pointer find_element (size_type i) { return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i)); } /// \brief Return a const pointer to the element \f$i\f$ /// \param i index of the element // XXX this semantic is not the one expected by the name of this method BOOST_UBLAS_INLINE const_pointer find_element (size_type i) const { BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); // Since std:array doesn't check for bounds return & (data () [i]); } // -------------- // Element access // -------------- /// \brief Return a const reference to the element \f$i\f$ /// Return a const reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i] /// \param i index of the element BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); return data () [i]; } /// \brief Return a reference to the element \f$i\f$ /// Return a reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i] /// \param i index of the element BOOST_UBLAS_INLINE reference operator () (size_type i) { BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); return data () [i]; } /// \brief Return a const reference to the element \f$i\f$ /// \param i index of the element BOOST_UBLAS_INLINE const_reference operator [] (size_type i) const { BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); return (*this) (i); } /// \brief Return a reference to the element \f$i\f$ /// \param i index of the element BOOST_UBLAS_INLINE reference operator [] (size_type i) { BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); return (*this) (i); } // ------------------ // Element assignment // ------------------ /// \brief Set element \f$i\f$ to the value \c t /// \param i index of the element /// \param t reference to the value to be set // XXX semantic of this is to insert a new element and therefore size=size+1 ? BOOST_UBLAS_INLINE reference insert_element (size_type i, const_reference t) { BOOST_UBLAS_CHECK (i < data_.size(), bad_index ()); return (data () [i] = t); } /// \brief Set element \f$i\f$ to the \e zero value /// \param i index of the element BOOST_UBLAS_INLINE void erase_element (size_type i) { BOOST_UBLAS_CHECK (i < data_.size(), bad_index ()); data () [i] = value_type/*zero*/(); } // ------- // Zeroing // ------- /// \brief Clear the vector, i.e. set all values to the \c zero value. BOOST_UBLAS_INLINE void clear () { std::fill (data ().begin (), data ().end (), value_type/*zero*/()); } // Assignment #ifdef BOOST_UBLAS_MOVE_SEMANTICS /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector) /// \param v is the source vector /// \return a reference to a fixed_vector (i.e. the destination vector) /*! @note "pass by value" the key idea to enable move semantics */ BOOST_UBLAS_INLINE fixed_vector &operator = (fixed_vector v) { assign_temporary(v); return *this; } #else /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector) /// \param v is the source fixed_vector /// \return a reference to a fixed_vector (i.e. the destination vector) BOOST_UBLAS_INLINE fixed_vector &operator = (const fixed_vector &v) { data () = v.data (); return *this; } #endif /// \brief Assign a full vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector) /// Assign a full vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector). This method does not create any temporary. /// \param v is the source vector container /// \return a reference to a vector (i.e. the destination vector) template<class C> // Container assignment without temporary BOOST_UBLAS_INLINE fixed_vector &operator = (const vector_container<C> &v) { assign (v); return *this; } /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector) /// \param v is the source fixed_vector /// \return a reference to a fixed_vector (i.e. the destination fixed_vector) BOOST_UBLAS_INLINE fixed_vector &assign_temporary (fixed_vector &v) { swap ( v ); return *this; } /// \brief Assign the result of a vector_expression to the fixed_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 fixed_vector template<class AE> BOOST_UBLAS_INLINE fixed_vector &operator = (const vector_expression<AE> &ae) { self_type temporary (ae); return assign_temporary (temporary); } /// \brief Assign the result of a vector_expression to the fixed_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 fixed_vector template<class AE> BOOST_UBLAS_INLINE fixed_vector &assign (const vector_expression<AE> &ae) { vector_assign<scalar_assign> (*this, ae); return *this; } // ------------------- // Computed assignment // ------------------- /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector /// Assign the sum of the fixed_vector and a vector_expression to the fixed_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 fixed_vector template<class AE> BOOST_UBLAS_INLINE fixed_vector &operator += (const vector_expression<AE> &ae) { self_type temporary (*this + ae); return assign_temporary (temporary); } /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector /// Assign the sum of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression. /// No temporary is created. Computations are done and stored directly into the resulting vector. /// \tparam AE is the type of the vector_expression /// \param ae is a const reference to the vector_expression /// \return a reference to the resulting vector template<class C> // Container assignment without temporary BOOST_UBLAS_INLINE fixed_vector &operator += (const vector_container<C> &v) { plus_assign (v); return *this; } /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector /// Assign the sum of the fixed_vector and a vector_expression to the fixed_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 fixed_vector. /// \tparam AE is the type of the vector_expression /// \param ae is a const reference to the vector_expression /// \return a reference to the resulting vector template<class AE> BOOST_UBLAS_INLINE fixed_vector &plus_assign (const vector_expression<AE> &ae) { vector_assign<scalar_plus_assign> (*this, ae); return *this; } /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector /// Assign the difference of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression. /// A temporary is created for the computations. /// \tparam AE is the type of the vector_expression /// \param ae is a const reference to the vector_expression template<class AE> BOOST_UBLAS_INLINE fixed_vector &operator -= (const vector_expression<AE> &ae) { self_type temporary (*this - ae); return assign_temporary (temporary); } /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector /// Assign the difference of the fixed_vector and a vector_expression to the fixed_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 fixed_vector. /// \tparam AE is the type of the vector_expression /// \param ae is a const reference to the vector_expression /// \return a reference to the resulting vector template<class C> // Container assignment without temporary BOOST_UBLAS_INLINE fixed_vector &operator -= (const vector_container<C> &v) { minus_assign (v); return *this; } /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector /// Assign the difference of the fixed_vector and a vector_expression to the fixed_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 fixed_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 fixed_vector template<class AE> BOOST_UBLAS_INLINE fixed_vector &minus_assign (const vector_expression<AE> &ae) { vector_assign<scalar_minus_assign> (*this, ae); return *this; } /// \brief Assign the product of the fixed_vector and a scalar to the fixed_vector /// Assign the product of the fixed_vector and a scalar to the fixed_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 fixed_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 fixed_vector template<class AT> BOOST_UBLAS_INLINE fixed_vector &operator *= (const AT &at) { vector_assign_scalar<scalar_multiplies_assign> (*this, at); return *this; } /// \brief Assign the division of the fixed_vector by a scalar to the fixed_vector /// Assign the division of the fixed_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 fixed_vector template<class AT> BOOST_UBLAS_INLINE fixed_vector &operator /= (const AT &at) { vector_assign_scalar<scalar_divides_assign> (*this, at); return *this; } // -------- // Swapping // -------- /// \brief Swap the content of the fixed_vector with another vector /// \param v is the fixed_vector to be swapped with BOOST_UBLAS_INLINE void swap (fixed_vector &v) { if (this != &v) { data ().swap (v.data ()); } } /// \brief Swap the content of two fixed_vectors /// \param v1 is the first fixed_vector. It takes values from v2 /// \param v2 is the second fixed_vector It takes values from v1 BOOST_UBLAS_INLINE friend void swap (fixed_vector &v1, fixed_vector &v2) { v1.swap (v2); } // Iterator types private: // Use the storage array iterator typedef typename A::const_iterator const_subiterator_type; typedef typename A::iterator subiterator_type; public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator<self_type, dense_random_access_iterator_tag> iterator; typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator; #else class const_iterator; class iterator; #endif // -------------- // Element lookup // -------------- /// \brief Return a const iterator to the element \e i /// \param i index of the element BOOST_UBLAS_INLINE const_iterator find (size_type i) const { #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, data ().begin () + i); #else return const_iterator (*this, i); #endif } /// \brief Return an iterator to the element \e i /// \param i index of the element BOOST_UBLAS_INLINE iterator find (size_type i) { #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, data ().begin () + i); #else return iterator (*this, i); #endif } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator: public container_const_reference<fixed_vector>, public random_access_iterator_base<dense_random_access_iterator_tag, const_iterator, value_type, difference_type> { public: typedef typename fixed_vector::difference_type difference_type; typedef typename fixed_vector::value_type value_type; typedef typename fixed_vector::const_reference reference; typedef const typename fixed_vector::pointer pointer; // ---------------------------- // Construction and destruction // ---------------------------- BOOST_UBLAS_INLINE const_iterator (): container_const_reference<self_type> (), it_ () {} BOOST_UBLAS_INLINE const_iterator (const self_type &v, const const_subiterator_type &it): container_const_reference<self_type> (v), it_ (it) {} BOOST_UBLAS_INLINE const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here container_const_reference<self_type> (it ()), it_ (it.it_) {} // ---------- // Arithmetic // ---------- /// \brief Increment by 1 the position of the iterator /// \return a reference to the const iterator BOOST_UBLAS_INLINE const_iterator &operator ++ () { ++ it_; return *this; } /// \brief Decrement by 1 the position of the iterator /// \return a reference to the const iterator BOOST_UBLAS_INLINE const_iterator &operator -- () { -- it_; return *this; } /// \brief Increment by \e n the position of the iterator /// \return a reference to the const iterator BOOST_UBLAS_INLINE const_iterator &operator += (difference_type n) { it_ += n; return *this; } /// \brief Decrement by \e n the position of the iterator /// \return a reference to the const iterator BOOST_UBLAS_INLINE const_iterator &operator -= (difference_type n) { it_ -= n; return *this; } /// \brief Return the different in number of positions between 2 iterators BOOST_UBLAS_INLINE difference_type operator - (const const_iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ - it.it_; } /// \brief Dereference an iterator /// Dereference an iterator: a bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds. /// \return a const reference to the value pointed by the iterator BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ()); return *it_; } /// \brief Dereference an iterator at the n-th forward value /// Dereference an iterator at the n-th forward value, that is the value pointed by iterator+n. /// A bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds. /// \return a const reference BOOST_UBLAS_INLINE const_reference operator [] (difference_type n) const { return *(it_ + n); } // Index /// \brief return the index of the element referenced by the iterator BOOST_UBLAS_INLINE size_type index () const { BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ()); return it_ - (*this) ().begin ().it_; } // Assignment BOOST_UBLAS_INLINE /// \brief assign the value of an iterator to the iterator const_iterator &operator = (const const_iterator &it) { container_const_reference<self_type>::assign (&it ()); it_ = it.it_; return *this; } // Comparison /// \brief compare the value of two itetarors /// \return true if they reference the same element BOOST_UBLAS_INLINE bool operator == (const const_iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ == it.it_; } /// \brief compare the value of two iterators /// \return return true if the left-hand-side iterator refers to a value placed before the right-hand-side iterator BOOST_UBLAS_INLINE bool operator < (const const_iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ < it.it_; } private: const_subiterator_type it_; friend class iterator; }; #endif /// \brief return an iterator on the first element of the fixed_vector BOOST_UBLAS_INLINE const_iterator begin () const { return find (0); } /// \brief return an iterator on the first element of the fixed_vector BOOST_UBLAS_INLINE const_iterator cbegin () const { return begin (); } /// \brief return an iterator after the last element of the fixed_vector BOOST_UBLAS_INLINE const_iterator end () const { return find (data_.size ()); } /// \brief return an iterator after the last element of the fixed_vector BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator: public container_reference<fixed_vector>, public random_access_iterator_base<dense_random_access_iterator_tag, iterator, value_type, difference_type> { public: typedef typename fixed_vector::difference_type difference_type; typedef typename fixed_vector::value_type value_type; typedef typename fixed_vector::reference reference; typedef typename fixed_vector::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE iterator (): container_reference<self_type> (), it_ () {} BOOST_UBLAS_INLINE iterator (self_type &v, const subiterator_type &it): container_reference<self_type> (v), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator &operator ++ () { ++ it_; return *this; } BOOST_UBLAS_INLINE iterator &operator -- () { -- it_; return *this; } BOOST_UBLAS_INLINE iterator &operator += (difference_type n) { it_ += n; return *this; } BOOST_UBLAS_INLINE iterator &operator -= (difference_type n) { it_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ - it.it_; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ()); return *it_; } BOOST_UBLAS_INLINE reference operator [] (difference_type n) const { return *(it_ + n); } // Index BOOST_UBLAS_INLINE size_type index () const { BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ()); return it_ - (*this) ().begin ().it_; } // Assignment BOOST_UBLAS_INLINE iterator &operator = (const iterator &it) { container_reference<self_type>::assign (&it ()); it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ == it.it_; } BOOST_UBLAS_INLINE bool operator < (const iterator &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); return it_ < it.it_; } private: subiterator_type it_; friend class const_iterator; }; #endif /// \brief Return an iterator on the first element of the fixed_vector BOOST_UBLAS_INLINE iterator begin () { return find (0); } /// \brief Return an iterator at the end of the fixed_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 fixed_vector (i.e. end() of normal fixed_vector) BOOST_UBLAS_INLINE const_reverse_iterator rbegin () const { return const_reverse_iterator (end ()); } /// \brief Return a const reverse iterator before the first element of the reversed fixed_vector (i.e. end() of normal fixed_vector) BOOST_UBLAS_INLINE const_reverse_iterator crbegin () const { return rbegin (); } /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector) BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector) BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } /// \brief Return a const reverse iterator before the first element of the reversed fixed_vector (i.e. end() of normal fixed_vector) BOOST_UBLAS_INLINE reverse_iterator rbegin () { return reverse_iterator (end ()); } /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector) BOOST_UBLAS_INLINE reverse_iterator rend () { return reverse_iterator (begin ()); } // ------------- // Serialization // ------------- /// Serialize a fixed_vector into and archive as defined in Boost /// \param ar Archive object. Can be a flat file, an XML file or any other stream /// \param file_version Optional file version (not yet used) template<class Archive> void serialize(Archive & ar, const unsigned int /* file_version */){ ar & serialization::make_nvp("data",data_); } private: array_type data_; }; #endif // BOOST_UBLAS_CPP_GE_2011 // -------------------- // 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } // 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this, false); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } // 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } // 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 ublas/vector_sparse.hpp 0000644 00000244274 15125237305 0011262 0 ustar 00 // // 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/config.hpp> // In debug mode, MSCV enables iterator debugging, which additional checks are // executed for consistency. So, when two iterators are compared, it is tested // that they point to elements of the same container. If the check fails, then // the program is aborted. // // When matrices MVOV are traversed by column and then by row, the previous // check fails. // // MVOV::iterator2 iter2 = mvov.begin2(); // for (; iter2 != mvov.end() ; iter2++) { // MVOV::iterator1 iter1 = iter2.begin(); // ..... // } // // These additional checks in iterators are disabled in this file, but their // status are restored at the end of file. // https://msdn.microsoft.com/en-us/library/hh697468.aspx #ifdef BOOST_MSVC #define _BACKUP_ITERATOR_DEBUG_LEVEL _ITERATOR_DEBUG_LEVEL #undef _ITERATOR_DEBUG_LEVEL #define _ITERATOR_DEBUG_LEVEL 0 #endif #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, 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this, data ().end ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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); } // replacement if STL lower bound algorithm for use of inplace_merge size_type lower_bound (size_type beg, size_type end, size_type target) const { while (end > beg) { size_type mid = (beg + end) / 2; if (index_data_[mid] < index_data_[target]) { beg = mid + 1; } else { end = mid; } } return beg; } // specialized replacement of STL inplace_merge to avoid compilation // problems with respect to the array_triple iterator void inplace_merge (size_type beg, size_type mid, size_type end) const { size_type len_lef = mid - beg; size_type len_rig = end - mid; if (len_lef == 1 && len_rig == 1) { if (index_data_[mid] < index_data_[beg]) { std::swap(index_data_[beg], index_data_[mid]); std::swap(value_data_[beg], value_data_[mid]); } } else if (len_lef > 0 && len_rig > 0) { size_type lef_mid, rig_mid; if (len_lef >= len_rig) { lef_mid = (beg + mid) / 2; rig_mid = lower_bound(mid, end, lef_mid); } else { rig_mid = (mid + end) / 2; lef_mid = lower_bound(beg, mid, rig_mid); } std::rotate(&index_data_[0] + lef_mid, &index_data_[0] + mid, &index_data_[0] + rig_mid); std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid); size_type new_mid = lef_mid + rig_mid - mid; inplace_merge(beg, lef_mid, new_mid); inplace_merge(new_mid, rig_mid, end); } } // 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_); #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT const typename array_pair::iterator iunsorted = ipa.begin () + sorted_filled_; // sort new elements and merge std::sort (iunsorted, ipa.end ()); inplace_merge(0, sorted_filled_, filled_); #else const typename array_pair::iterator iunsorted = ipa.begin (); std::sort (iunsorted, ipa.end ()); #endif // 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 cbegin () const { return begin(); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end(); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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*/(); }}} #ifdef BOOST_MSVC #undef _ITERATOR_DEBUG_LEVEL #define _ITERATOR_DEBUG_LEVEL _BACKUP_ITERATOR_DEBUG_LEVEL #undef _BACKUP_ITERATOR_DEBUG_LEVEL #endif #endif ublas/exception.hpp 0000644 00000021166 15125237305 0010372 0 ustar 00 // Copyright (c) 2000-2011 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) #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 ublas/io.hpp 0000644 00000032567 15125237305 0007012 0 ustar 00 // // 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 ublas/detail/concepts.hpp 0000644 00000212575 15125237305 0011462 0 ustar 00 // // 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 { // Replaced the ZeroElement and OneElement functions with the templated versions // because the former where giving warnings with clang template<class T> T ZeroElement (T) { return static_cast<T> (0); } template<class T> vector<T> ZeroElement (vector<T>) { return zero_vector<T> (); } template<class T> matrix<T> ZeroElement (matrix<T>) { return zero_matrix<T> (); } template<class T> T OneElement (T) { return static_cast<T> (1); } template<class T> matrix<T> OneElement (matrix<T>) { return identity_matrix<T> (); } 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); } }; inline 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<T> >(); function_requires< CommutativeRingWithIdentityConcept<T> >(); function_requires< FieldConcept<T> >(); function_requires< VectorSpaceConcept<T, vector<T> > >(); function_requires< Prod_RingWithIdentityConcept<matrix<T> > >(); function_requires< VectorSpaceConcept<T, matrix<T> > >(); function_requires< LinearOperatorConcept<T, vector<T>, matrix<T> > >(); function_requires< AdditiveAbelianGroupConcept<std::complex<T> > >(); function_requires< CommutativeRingWithIdentityConcept<std::complex<T> > >(); function_requires< FieldConcept<std::complex<T> > >(); function_requires< VectorSpaceConcept<std::complex<T>, vector<std::complex<T> > > >(); function_requires< Prod_RingWithIdentityConcept<matrix<std::complex<T> > > >(); function_requires< VectorSpaceConcept<std::complex<T>, matrix<std::complex<T> > > >(); function_requires< LinearOperatorConcept<std::complex<T>, vector<std::complex<T> >, matrix<std::complex<T> > > >(); #endif } } // end of anonymous namespace }}} #endif ublas/detail/matrix_assign.hpp 0000644 00000240277 15125237305 0012514 0 ustar 00 // // 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 (); for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 0) { ++ it2, ++ it2e; if (it2 != it2_end && it2e != it2e_end) { it2_index = it2.index2 (); it2e_index = it2e.index2 (); } else break; } else if (compare2 < 0) { increment (it2, it2_end, - compare2); if (it2 != it2_end) it2_index = it2.index2 (); else break; } else if (compare2 > 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 (); for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 0) { ++ it1, ++ it1e; if (it1 != it1_end && it1e != it1e_end) { it1_index = it1.index1 (); it1e_index = it1e.index1 (); } else break; } else if (compare2 < 0) { increment (it1, it1_end, - compare2); if (it1 != it1_end) it1_index = it1.index1 (); else break; } else if (compare2 > 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; BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif while (-- size2 >= 0) // zeroing functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2; } else { it2 += size2; } ++ it1, ++ it1e; } size1 = it1_size; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif while (-- size1 >= 0) // zeroing functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1; } else { it1 += size1; } ++ it2, ++ it2e; } size2 = it2_size; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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 //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif BOOST_STATIC_ASSERT ((!functor_type::computed)); #ifdef _MSC_VER #pragma warning(pop) #endif 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 //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif BOOST_STATIC_ASSERT ((!functor_type::computed)); #ifdef _MSC_VER #pragma warning(pop) #endif 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; BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 (); for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 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 (compare2 < 0) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif functor_type::apply (*it2, expr_value_type/*zero*/()); ++ it2; } else increment (it2, it2_end, - compare2); if (it2 != it2_end) it2_index = it2.index2 (); else break; } else if (compare2 > 0) { increment (it2e, it2e_end, compare2); if (it2e != it2e_end) it2e_index = it2e.index2 (); else break; } } } //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif while (it2 != it2_end) { // zeroing functor_type::apply (*it2, expr_value_type/*zero*/()); ++ it2; } } else { it2 = it2_end; } ++ it1, ++ it1e; } else if (compare < 0) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif #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); } } //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 (); for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 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 (compare2 < 0) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing ++ it1; } else increment (it1, it1_end, - compare2); if (it1 != it1_end) it1_index = it1.index1 (); else break; } else if (compare2 > 0) { increment (it1e, it1e_end, compare2); if (it1e != it1e_end) it1e_index = it1e.index1 (); else break; } } } //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif while (it1 != it1_end) { // zeroing functor_type::apply (*it1, expr_value_type/*zero*/()); ++ it1; } } else { it1 = it1_end; } ++ it2, ++ it2e; } else if (compare < 0) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif #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); } } //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; // gcc is complaining that this is not used, although this is not right 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 (), typename M::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 (), typename M::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 (), typename M::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; // gcc is complaining that this is not used, although this is not right 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 (), typename M::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 (), typename M::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 (), typename M::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::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::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; 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 (); for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 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 (compare2 < 0) { increment (it2, it2_end, - compare2); if (it2 != it2_end) it2_index = it2.index2 (); else break; } else if (compare2 > 0) { increment (it2e, it2e_end, compare2); 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; 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 (); for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 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 (compare2 < 0) { increment (it1, it1_end, - compare2); if (it1 != it1_end) it1_index = it1.index1 (); else break; } else if (compare2 > 0) { increment (it1e, it1e_end, compare2); 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 ublas/detail/config.hpp 0000644 00000017520 15125237305 0011102 0 ustar 00 // // 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> // C++11 #if defined(__cplusplus) && __cplusplus >= 201103L #define BOOST_UBLAS_CPP_GE_2011 #elif BOOST_MSVC >= 1800 #define BOOST_UBLAS_CPP_GE_2011 #else #undef BOOST_UBLAS_CPP_GE_2011 // Make sure no one defined it #endif // Microsoft Visual C++ #if defined (BOOST_MSVC) && ! defined (BOOST_STRICT_CONFIG) // 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 // PGI compiler #ifdef __PGIC__ #define BOOST_UBLAS_UNSUPPORTED_COMPILER 0 #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_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 ublas/detail/temporary.hpp 0000644 00000001475 15125237305 0011661 0 ustar 00 // // 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 ublas/detail/raw.hpp 0000644 00000073133 15125237305 0010430 0 ustar 00 // // 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 ublas/detail/returntype_deduction.hpp 0000644 00000011266 15125237305 0014115 0 ustar 00 /* * 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 boost::disable_if< is_basic<X>, x_value_type >::type test(X const&); template <typename X, typename Y> typename boost::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 ublas/detail/vector_assign.hpp 0000644 00000060553 15125237305 0012507 0 ustar 00 // // 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 (); for (;;) { 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif BOOST_STATIC_ASSERT ((!functor_type::computed)); #ifdef _MSC_VER #pragma warning(pop) #endif 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; #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 (); for (;;) { 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) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; } } } //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (!functor_type::computed) { #ifdef _MSC_VER #pragma warning(pop) #endif 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; 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 (); for (;;) { 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 ublas/detail/documentation.hpp 0000644 00000001563 15125237305 0012506 0 ustar 00 // // 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 */ ublas/detail/duff.hpp 0000644 00000002542 15125237305 0010557 0 ustar 00 // // 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 ublas/detail/iterator.hpp 0000644 00000142244 15125237305 0011470 0 ustar 00 // // 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 ublas/detail/definitions.hpp 0000644 00000014554 15125237305 0012154 0 ustar 00 // // 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 ublas/vector_proxy.hpp 0000644 00000176125 15125237305 0011145 0 ustar 00 // // 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } #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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 ublas/banded.hpp 0000644 00000251477 15125237305 0007623 0 ustar 00 // // Copyright (c) 2000-2013 // Joerg Walter, Mathias Koch, 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) // // 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 { namespace hidden { /** \brief A helper for band_matrix indexing. * * The indexing happens as per the netlib description: http://www.netlib.org/lapack/lug/node124.html. * In the case of a row_major matrix a different approach is followed; */ template <class LayoutType> class banded_indexing { }; /** \brief A helper for indexing column major banded matrices. * */ template <> class banded_indexing<column_major_tag> { public: template <class T> BOOST_UBLAS_INLINE static T size(T /*size1*/, T size2) { return size2; } // template <class T> // BOOST_UBLAS_INLINE static bool valid_index(T size1, T /*size2*/, T lower, T upper, T i, T j) { // return (upper+i >= j) && i <= std::min(size1 - 1, j + lower); // upper + i is used by get_index. Maybe find a way to consolidate the operations to increase performance // } template <class T> BOOST_UBLAS_INLINE static T get_index(T /*size1*/, T size2, T lower, T upper, T i, T j) { return column_major::element (upper + i - j, lower + 1 + upper, j, size2); } }; /** \brief A helper for indexing row major banded matrices. * */ template <> class banded_indexing<row_major_tag> { public: template <class T> BOOST_UBLAS_INLINE static T size(T size1, T /*size2*/) { return size1; } // template <class T> // BOOST_UBLAS_INLINE static bool valid_index(T /*size1*/, T size2, T lower, T upper, T i, T j) { // return (lower+j >= i) && j <= std::min(size2 - 1, i + upper); // lower + j is used by get_index. Maybe find a way to consolidate the operations to increase performance // } template <class T> BOOST_UBLAS_INLINE static T get_index(T size1, T /*size2*/, T lower, T upper, T i, T j) { return row_major::element (i, size1, lower + j - i, lower + 1 + upper); } }; } /** \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; private: public: // 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), #if defined(BOOST_UBLAS_OWN_BANDED) || (BOOST_UBLAS_LEGACY_BANDED) data_ ((std::max) (size1, size2) * (lower + 1 + upper)) #else data_ ( hidden::banded_indexing<orientation_category>::size(size1, size2) * (lower + 1 + upper)) // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html #endif { } 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), #if defined(BOOST_UBLAS_OWN_BANDED) || (BOOST_UBLAS_LEGACY_BANDED) data_ ((std::max) (size1_, size2_) * (lower_ + 1 + upper_)) #else data_ ( hidden::banded_indexing<orientation_category>::size(size1_, size2_) * (lower_ + 1 + upper_)) // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html #endif { 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_; } #if !defined (BOOST_UBLAS_OWN_BANDED)||(BOOST_UBLAS_LEGACY_BANDED) BOOST_UBLAS_INLINE bool is_element_in_band(size_type i, size_type j) const{ //return (upper_+i >= j) && i <= std::min(size1() - 1, j + lower_); // We don't need to check if i is outside because it is checked anyway in the accessors. return (upper_+i >= j) && i <= ( j + lower_); // Essentially this band has "infinite" positive dimensions } #endif // 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_) && // TODO: probably use BOOST_UBLAS_CHECK here instead of if l < lower_ + 1 + upper_) return data () [layout_type::element (k, (std::max) (size1_, size2_), l, lower_ + 1 + upper_)]; #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in 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_)]; #else // New default // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html if ( is_element_in_band( i, j) ) { return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)]; } #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; // TODO: Don't we need an if or BOOST_UBLAS_CHECK HERE? return data () [layout_type::element (k, (std::max) (size1_, size2_), l, lower_ + 1 + upper_)]; #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in 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_)]; #else // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html BOOST_UBLAS_CHECK(is_element_in_band( i, j) , bad_index()); return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)]; #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_) && // TODO: probably use BOOST_UBLAS_CHECK here instead of if l < lower_ + 1 + upper_) ) { bad_index ().raise (); // NEVER reached } return data () [layout_type::element (k, (std::max) (size1_, size2_), l, lower_ + 1 + upper_)]; #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in 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_)]; #else // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html BOOST_UBLAS_CHECK( is_element_in_band( i, j) , bad_index()); return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)]; #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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end(); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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_; } #if !defined (BOOST_UBLAS_OWN_BANDED)||(BOOST_UBLAS_LEGACY_BANDED) BOOST_UBLAS_INLINE bool is_element_in_band(size_type i, size_type j) const{ //return (upper_+i >= j) && i <= std::min(size1() - 1, j + lower_); // We don't need to check if i is outside because it is checked anyway in the accessors. return (upper_+i >= j) && i <= ( j + lower_); // Essentially this band has "infinite" positive dimensions } #endif // 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); #elif BOOST_UBLAS_LEGACY_BANDED size_type k = j; size_type l = upper_ + i - j; if (k < size2 () && l < lower_ + 1 + upper_) return data () (i, j); #else if (is_element_in_band( i, j)) 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); #elif BOOST_UBLAS_LEGACY_BANDED size_type k = j; size_type l = upper_ + i - j; if (k < size2 () && l < lower_ + 1 + upper_) return data () (i, j); #else if (is_element_in_band( i, j)) 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); #elif BOOST_UBLAS_LEGACY_BANDED size_type k = j; size_type l = upper_ + i - j; if (k < size2 () && l < lower_ + 1 + upper_) return data () (i, j); #else if (is_element_in_band( i, j)) 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/tensor.hpp 0000644 00000001440 15125237305 0007677 0 ustar 00 // Copyright (c) 2018-2019 // Cem Bassoy // // 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 // Fraunhofer and Google in producing this work // which started as a Google Summer of Code project. // /// \file tensor.hpp Definition for the class vector and its derivative #ifndef BOOST_NUMERIC_UBLAS_TENSOR_HPP #define BOOST_NUMERIC_UBLAS_TENSOR_HPP #include "tensor/functions.hpp" #include "tensor/operators_arithmetic.hpp" #include "tensor/operators_comparison.hpp" #include "tensor/extents.hpp" #include "tensor/strides.hpp" #include "tensor/ostream.hpp" #include "tensor/tensor.hpp" #endif // BOOST_NUMERIC_UBLAS_TENSOR_HPP ublas/matrix_sparse.hpp 0000644 00000703761 15125237305 0011265 0 ustar 00 // // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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> 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 (), false); 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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); } // replacement if STL lower bound algorithm for use of inplace_merge array_size_type lower_bound (array_size_type beg, array_size_type end, array_size_type target) const { while (end > beg) { array_size_type mid = (beg + end) / 2; if (((index1_data_[mid] < index1_data_[target]) || ((index1_data_[mid] == index1_data_[target]) && (index2_data_[mid] < index2_data_[target])))) { beg = mid + 1; } else { end = mid; } } return beg; } // specialized replacement of STL inplace_merge to avoid compilation // problems with respect to the array_triple iterator void inplace_merge (array_size_type beg, array_size_type mid, array_size_type end) const { array_size_type len_lef = mid - beg; array_size_type len_rig = end - mid; if (len_lef == 1 && len_rig == 1) { if ((index1_data_[mid] < index1_data_[beg]) || ((index1_data_[mid] == index1_data_[beg]) && (index2_data_[mid] < index2_data_[beg]))) { std::swap(index1_data_[beg], index1_data_[mid]); std::swap(index2_data_[beg], index2_data_[mid]); std::swap(value_data_[beg], value_data_[mid]); } } else if (len_lef > 0 && len_rig > 0) { array_size_type lef_mid, rig_mid; if (len_lef >= len_rig) { lef_mid = (beg + mid) / 2; rig_mid = lower_bound(mid, end, lef_mid); } else { rig_mid = (mid + end) / 2; lef_mid = lower_bound(beg, mid, rig_mid); } std::rotate(&index1_data_[0] + lef_mid, &index1_data_[0] + mid, &index1_data_[0] + rig_mid); std::rotate(&index2_data_[0] + lef_mid, &index2_data_[0] + mid, &index2_data_[0] + rig_mid); std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid); array_size_type new_mid = lef_mid + rig_mid - mid; inplace_merge(beg, lef_mid, new_mid); inplace_merge(new_mid, rig_mid, end); } } // 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_); #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_; // sort new elements and merge std::sort (iunsorted, ita.end ()); inplace_merge(0, sorted_filled_, filled_); #else const typename array_triple::iterator iunsorted = ita.begin (); std::sort (iunsorted, ita.end ()); #endif // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } 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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/triangular.hpp 0000644 00000315530 15125237305 0010545 0 ustar 00 // // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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::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::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; } } } // 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, row_major_tag, dense_proxy_tag) { typedef typename E2::size_type size_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, row_major_tag, packed_proxy_tag) { typedef typename E2::size_type size_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); typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0)); typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n)); while (it2e1 != it2e1_end) { t -= *it2e1 * e2 () (it2e1.index2()); ++ it2e1; } e2() (n) = t / e1 () (n, n); } } // 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, row_major_tag, unknown_storage_tag) { typedef typename E2::size_type size_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); typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0)); typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n)); while (it2e1 != it2e1_end) { t -= *it2e1 * e2 () (it2e1.index2()); ++ it2e1; } e2() (n) = t / e1 () (n, n); } } // 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 (e1, e2, 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, 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)); while (it1e1 != it1e1_rend) { 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; } } } } // 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, row_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 = e1 ().size1 (); 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); for (difference_type m = n + 1; m < static_cast<difference_type>(e1 ().size2()); ++ m) { t -= e1 () (n, m) * e2 () (m); } e2() (n) = t / e1 () (n, n); } } // 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, row_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 = e1 ().size1 (); 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); typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1)); typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ())); while (it2e1 != it2e1_end) { t -= *it2e1 * e2 () (it2e1.index2()); ++ it2e1; } e2() (n) = t / e1 () (n, n); } } // 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, row_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 = e1 ().size1 (); 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); typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1)); typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ())); while (it2e1 != it2e1_end) { t -= *it2e1 * e2 () (it2e1.index2()); ++ it2e1; } e2() (n) = t / e1 () (n, n); } } // 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 (e1, e2, 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, 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; } // 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 E2::storage_category storage_category; inplace_solve (trans(e2), e1, upper_tag (), column_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 E2::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 ()); } // 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 E2::storage_category storage_category; inplace_solve (trans(e2), e1, lower_tag (), column_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 E2::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::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::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 ublas/tensor/index.hpp 0000644 00000005000 15125237305 0011002 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_INDEX_HPP #define BOOST_UBLAS_TENSOR_INDEX_HPP #include <cstddef> #include <array> #include <vector> namespace boost { namespace numeric { namespace ublas { namespace index { /** @brief Proxy template class for the einstein summation notation * * @note index::index_type<K> for 0<=K<=16 is used in tensor::operator() * * @tparam I wrapped integer */ template<std::size_t I> struct index_type { static constexpr std::size_t value = I; constexpr bool operator == (std::size_t other) const { return value == other; } constexpr bool operator != (std::size_t other) const { return value != other; } template <std::size_t K> constexpr bool operator == (index_type<K> /*other*/) const { return I==K; } template <std::size_t K> constexpr bool operator != (index_type<K> /*other*/) const { return I!=K; } constexpr bool operator == (index_type /*other*/) const { return true; } constexpr bool operator != (index_type /*other*/) const { return false; } constexpr std::size_t operator()() const { return I; } }; /** @brief Proxy classes for the einstein summation notation * * @note index::_a ... index::_z is used in tensor::operator() */ static constexpr index_type< 0> _; static constexpr index_type< 1> _a; static constexpr index_type< 2> _b; static constexpr index_type< 3> _c; static constexpr index_type< 4> _d; static constexpr index_type< 5> _e; static constexpr index_type< 6> _f; static constexpr index_type< 7> _g; static constexpr index_type< 8> _h; static constexpr index_type< 9> _i; static constexpr index_type<10> _j; static constexpr index_type<11> _k; static constexpr index_type<12> _l; static constexpr index_type<13> _m; static constexpr index_type<14> _n; static constexpr index_type<15> _o; static constexpr index_type<16> _p; static constexpr index_type<17> _q; static constexpr index_type<18> _r; static constexpr index_type<19> _s; static constexpr index_type<20> _t; static constexpr index_type<21> _u; static constexpr index_type<22> _v; static constexpr index_type<23> _w; static constexpr index_type<24> _x; static constexpr index_type<25> _y; static constexpr index_type<26> _z; } // namespace indices } } } #endif // _BOOST_UBLAS_TENSOR_INDEX_HPP_ ublas/tensor/expression.hpp 0000644 00000011732 15125237305 0012103 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP #define BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP #include <cstddef> #include <boost/numeric/ublas/expression_types.hpp> namespace boost { namespace numeric { namespace ublas { template<class element_type, class storage_format, class storage_type> class tensor; template<class size_type> class basic_extents; //TODO: put in fwd.hpp struct tensor_tag {}; } } } namespace boost { namespace numeric { namespace ublas { namespace detail { /** @\brief base class for tensor expressions * * \note implements crtp - no use of virtual function calls * * \tparam T type of the tensor * \tparam E type of the derived expression (crtp) * **/ template<class T, class E> struct tensor_expression : public ublas_expression<E> { // static const unsigned complexity = 0; using expression_type = E; using type_category = tensor_tag; using tensor_type = T; BOOST_UBLAS_INLINE auto const& operator()() const { return *static_cast<const expression_type*> (this); } protected : explicit tensor_expression() = default; tensor_expression(const tensor_expression&) = delete; tensor_expression& operator=(const tensor_expression&) = delete; }; template<class T, class EL, class ER, class OP> struct binary_tensor_expression : public tensor_expression <T, binary_tensor_expression<T,EL,ER,OP>> { using self_type = binary_tensor_expression<T,EL,ER,OP>; using tensor_type = T; using binary_operation = OP; using expression_type_left = EL; using expression_type_right = ER; using derived_type = tensor_expression <tensor_type,self_type>; using size_type = typename tensor_type::size_type; explicit binary_tensor_expression(expression_type_left const& l, expression_type_right const& r, binary_operation o) : el(l) , er(r) , op(o) {} binary_tensor_expression() = delete; binary_tensor_expression(const binary_tensor_expression& l) = delete; binary_tensor_expression(binary_tensor_expression&& l) : el(l.el), er(l.er), op(l.op) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(el(i), er(i)); } expression_type_left const& el; expression_type_right const& er; binary_operation op; }; /// @brief helper function to simply instantiation of lambda proxy class template<class T, class EL, class ER, class OP> auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, tensor_expression<T,ER> const& er, OP op) { return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ; } template<class T, class EL, class ER, class OP> auto make_binary_tensor_expression( matrix_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op) { return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ; } template<class T, class EL, class ER, class OP> auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, matrix_expression<ER> const& er, OP op) { return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ; } template<class T, class EL, class ER, class OP> auto make_binary_tensor_expression( vector_expression<EL> const& el, tensor_expression<T,ER> const& er, OP op) { return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ; } template<class T, class EL, class ER, class OP> auto make_binary_tensor_expression( tensor_expression<T,EL> const& el, vector_expression<ER> const& er, OP op) { return binary_tensor_expression<T,EL,ER,OP>( el(), er(), op) ; } template<class T, class E, class OP> struct unary_tensor_expression : public tensor_expression <T, unary_tensor_expression<T,E,OP>> { using self_type = unary_tensor_expression<T,E,OP>; using tensor_type = T; using expression_type = E; using derived_type = tensor_expression <T, unary_tensor_expression<T,E,OP>>; using size_type = typename tensor_type::size_type; explicit unary_tensor_expression(E const& ee, OP o) : e(ee) , op(o) {} unary_tensor_expression() = delete; unary_tensor_expression(const unary_tensor_expression& l) = delete; unary_tensor_expression(unary_tensor_expression&& l) : e(l.e), op(op.l) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(e(i)); } E const& e; OP op; }; // \brief helper function to simply instantiation of lambda proxy class template<class T, class E, class OP> auto make_unary_tensor_expression( tensor_expression<T,E> const& e, OP op) { return unary_tensor_expression<T,E,OP>( e() , op); } template<class T, class E, class OP> auto make_unary_tensor_expression( matrix_expression<E> const& e, OP op) { return unary_tensor_expression<T,E,OP>( e() , op); } template<class T, class E, class OP> auto make_unary_tensor_expression( vector_expression<E> const& e, OP op) { return unary_tensor_expression<T,E,OP>( e() , op); } } } } } #endif ublas/tensor/multiplication.hpp 0000644 00000107437 15125237305 0012751 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_MULTIPLICATION #define BOOST_UBLAS_TENSOR_MULTIPLICATION #include <cassert> namespace boost { namespace numeric { namespace ublas { namespace detail { namespace recursive { /** @brief Computes the tensor-times-tensor product for q contraction modes * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * nc[x] = na[phia[x] ] for 1 <= x <= r * nc[r+x] = nb[phib[x] ] for 1 <= x <= s * na[phia[r+x]] = nb[phib[s+x]] for 1 <= x <= q * * @note is used in function ttt * * @param k zero-based recursion level starting with 0 * @param r number of non-contraction indices of A * @param s number of non-contraction indices of B * @param q number of contraction indices with q > 0 * @param phia pointer to the permutation tuple of length q+r for A * @param phib pointer to the permutation tuple of length q+s for B * @param c pointer to the output tensor C with rank(A)=r+s * @param nc pointer to the extents of tensor C * @param wc pointer to the strides of tensor C * @param a pointer to the first input tensor with rank(A)=r+q * @param na pointer to the extents of the first input tensor A * @param wa pointer to the strides of the first input tensor A * @param b pointer to the second input tensor B with rank(B)=s+q * @param nb pointer to the extents of the second input tensor B * @param wb pointer to the strides of the second input tensor B */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttt(SizeType const k, SizeType const r, SizeType const s, SizeType const q, SizeType const*const phia, SizeType const*const phib, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { assert(nc[k] == na[phia[k]-1]); for(size_t ic = 0u; ic < nc[k]; a += wa[phia[k]-1], c += wc[k], ++ic) ttt(k+1, r, s, q, phia,phib, c, nc, wc, a, na, wa, b, nb, wb); } else if(k < r+s) { assert(nc[k] == nb[phib[k-r]-1]); for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic) ttt(k+1, r, s, q, phia, phib, c, nc, wc, a, na, wa, b, nb, wb); } else if(k < r+s+q-1) { assert(na[phia[k-s]-1] == nb[phib[k-r]-1]); for(size_t ia = 0u; ia < na[phia[k-s]-1]; a += wa[phia[k-s]-1], b += wb[phib[k-r]-1], ++ia) ttt(k+1, r, s, q, phia, phib, c, nc, wc, a, na, wa, b, nb, wb); } else { assert(na[phia[k-s]-1] == nb[phib[k-r]-1]); for(size_t ia = 0u; ia < na[phia[k-s]-1]; a += wa[phia[k-s]-1], b += wb[phib[k-r]-1], ++ia) *c += *a * *b; } } /** @brief Computes the tensor-times-tensor product for q contraction modes * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * @note no permutation tuple is used * * nc[x] = na[x ] for 1 <= x <= r * nc[r+x] = nb[x ] for 1 <= x <= s * na[r+x] = nb[s+x] for 1 <= x <= q * * @note is used in function ttt * * @param k zero-based recursion level starting with 0 * @param r number of non-contraction indices of A * @param s number of non-contraction indices of B * @param q number of contraction indices with q > 0 * @param c pointer to the output tensor C with rank(A)=r+s * @param nc pointer to the extents of tensor C * @param wc pointer to the strides of tensor C * @param a pointer to the first input tensor with rank(A)=r+q * @param na pointer to the extents of the first input tensor A * @param wa pointer to the strides of the first input tensor A * @param b pointer to the second input tensor B with rank(B)=s+q * @param nb pointer to the extents of the second input tensor B * @param wb pointer to the strides of the second input tensor B */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttt(SizeType const k, SizeType const r, SizeType const s, SizeType const q, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { assert(nc[k] == na[k]); for(size_t ic = 0u; ic < nc[k]; a += wa[k], c += wc[k], ++ic) ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb); } else if(k < r+s) { assert(nc[k] == nb[k-r]); for(size_t ic = 0u; ic < nc[k]; b += wb[k-r], c += wc[k], ++ic) ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb); } else if(k < r+s+q-1) { assert(na[k-s] == nb[k-r]); for(size_t ia = 0u; ia < na[k-s]; a += wa[k-s], b += wb[k-r], ++ia) ttt(k+1, r, s, q, c, nc, wc, a, na, wa, b, nb, wb); } else { assert(na[k-s] == nb[k-r]); for(size_t ia = 0u; ia < na[k-s]; a += wa[k-s], b += wb[k-r], ++ia) *c += *a * *b; } } /** @brief Computes the tensor-times-matrix product for the contraction mode m > 0 * * Implements C[i1,i2,...,im-1,j,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * B[j,im]) * * @note is used in function ttm * * @param m zero-based contraction mode with 0<m<p * @param r zero-based recursion level starting with p-1 * @param c pointer to the output tensor * @param nc pointer to the extents of tensor c * @param wc pointer to the strides of tensor c * @param a pointer to the first input tensor * @param na pointer to the extents of input tensor a * @param wa pointer to the strides of input tensor a * @param b pointer to the second input tensor * @param nb pointer to the extents of input tensor b * @param wb pointer to the strides of input tensor b */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttm(SizeType const m, SizeType const r, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(r == m) { ttm(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); } else if(r == 0){ for(auto i0 = 0ul; i0 < nc[0]; c += wc[0], a += wa[0], ++i0) { auto cm = c; auto b0 = b; for(auto i0 = 0ul; i0 < nc[m]; cm += wc[m], b0 += wb[0], ++i0){ auto am = a; auto b1 = b0; for(auto i1 = 0ul; i1 < nb[1]; am += wa[m], b1 += wb[1], ++i1) *cm += *am * *b1; } } } else{ for(auto i = 0ul; i < na[r]; c += wc[r], a += wa[r], ++i) ttm(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); } } /** @brief Computes the tensor-times-matrix product for the contraction mode m = 0 * * Implements C[j,i2,...,ip] = sum(A[i1,i2,...,ip] * B[j,i1]) * * @note is used in function ttm * * @param m zero-based contraction mode with 0<m<p * @param r zero-based recursion level starting with p-1 * @param c pointer to the output tensor * @param nc pointer to the extents of tensor c * @param wc pointer to the strides of tensor c * @param a pointer to the first input tensor * @param na pointer to the extents of input tensor a * @param wa pointer to the strides of input tensor a * @param b pointer to the second input tensor * @param nb pointer to the extents of input tensor b * @param wb pointer to the strides of input tensor b */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttm0( SizeType const r, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(r > 1){ for(auto i = 0ul; i < na[r]; c += wc[r], a += wa[r], ++i) ttm0(r-1, c, nc, wc, a, na, wa, b, nb, wb); } else{ for(auto i1 = 0ul; i1 < nc[1]; c += wc[1], a += wa[1], ++i1) { auto cm = c; auto b0 = b; // r == m == 0 for(auto i0 = 0ul; i0 < nc[0]; cm += wc[0], b0 += wb[0], ++i0){ auto am = a; auto b1 = b0; for(auto i1 = 0u; i1 < nb[1]; am += wa[0], b1 += wb[1], ++i1){ *cm += *am * *b1; } } } } } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /** @brief Computes the tensor-times-vector product for the contraction mode m > 0 * * Implements C[i1,i2,...,im-1,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * b[im]) * * @note is used in function ttv * * @param m zero-based contraction mode with 0<m<p * @param r zero-based recursion level starting with p-1 for tensor A * @param q zero-based recursion level starting with p-1 for tensor C * @param c pointer to the output tensor * @param nc pointer to the extents of tensor c * @param wc pointer to the strides of tensor c * @param a pointer to the first input tensor * @param na pointer to the extents of input tensor a * @param wa pointer to the strides of input tensor a * @param b pointer to the second input tensor */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttv( SizeType const m, SizeType const r, SizeType const q, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b) { if(r == m) { ttv(m, r-1, q, c, nc, wc, a, na, wa, b); } else if(r == 0){ for(auto i0 = 0u; i0 < na[0]; c += wc[0], a += wa[0], ++i0) { auto c1 = c; auto a1 = a; auto b1 = b; for(auto im = 0u; im < na[m]; a1 += wa[m], ++b1, ++im) *c1 += *a1 * *b1; } } else{ for(auto i = 0u; i < na[r]; c += wc[q], a += wa[r], ++i) ttv(m, r-1, q-1, c, nc, wc, a, na, wa, b); } } /** @brief Computes the tensor-times-vector product for the contraction mode m = 0 * * Implements C[i2,...,ip] = sum(A[i1,...,ip] * b[i1]) * * @note is used in function ttv * * @param m zero-based contraction mode with m=0 * @param r zero-based recursion level starting with p-1 * @param c pointer to the output tensor * @param nc pointer to the extents of tensor c * @param wc pointer to the strides of tensor c * @param a pointer to the first input tensor * @param na pointer to the extents of input tensor a * @param wa pointer to the strides of input tensor a * @param b pointer to the second input tensor */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttv0(SizeType const r, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b) { if(r > 1){ for(auto i = 0u; i < na[r]; c += wc[r-1], a += wa[r], ++i) ttv0(r-1, c, nc, wc, a, na, wa, b); } else{ for(auto i1 = 0u; i1 < na[1]; c += wc[0], a += wa[1], ++i1) { auto c1 = c; auto a1 = a; auto b1 = b; for(auto i0 = 0u; i0 < na[0]; a1 += wa[0], ++b1, ++i0) *c1 += *a1 * *b1; } } } /** @brief Computes the matrix-times-vector product * * Implements C[i1] = sum(A[i1,i2] * b[i2]) or C[i2] = sum(A[i1,i2] * b[i1]) * * @note is used in function ttv * * @param[in] m zero-based contraction mode with m=0 or m=1 * @param[out] c pointer to the output tensor C * @param[in] nc pointer to the extents of tensor C * @param[in] wc pointer to the strides of tensor C * @param[in] a pointer to the first input tensor A * @param[in] na pointer to the extents of input tensor A * @param[in] wa pointer to the strides of input tensor A * @param[in] b pointer to the second input tensor B */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void mtv(SizeType const m, PointerOut c, SizeType const*const , SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b) { // decides whether matrix multiplied with vector or vector multiplied with matrix const auto o = (m == 0) ? 1 : 0; for(auto io = 0u; io < na[o]; c += wc[o], a += wa[o], ++io) { auto c1 = c; auto a1 = a; auto b1 = b; for(auto im = 0u; im < na[m]; a1 += wa[m], ++b1, ++im) *c1 += *a1 * *b1; } } /** @brief Computes the matrix-times-matrix product * * Implements C[i1,i3] = sum(A[i1,i2] * B[i2,i3]) * * @note is used in function ttm * * @param[out] c pointer to the output tensor C * @param[in] nc pointer to the extents of tensor C * @param[in] wc pointer to the strides of tensor C * @param[in] a pointer to the first input tensor A * @param[in] na pointer to the extents of input tensor A * @param[in] wa pointer to the strides of input tensor A * @param[in] b pointer to the second input tensor B * @param[in] nb pointer to the extents of input tensor B * @param[in] wb pointer to the strides of input tensor B */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void mtm(PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { // C(i,j) = A(i,k) * B(k,j) assert(nc[0] == na[0]); assert(nc[1] == nb[1]); assert(na[1] == nb[0]); auto cj = c; auto bj = b; for(auto j = 0u; j < nc[1]; cj += wc[1], bj += wb[1], ++j) { auto bk = bj; auto ak = a; for(auto k = 0u; k < na[1]; ak += wa[1], bk += wb[0], ++k) { auto ci = cj; auto ai = ak; for(auto i = 0u; i < na[0]; ai += wa[0], ci += wc[0], ++i){ *ci += *ai * *bk; } } } } /** @brief Computes the inner product of two tensors * * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,ip]) * * @note is used in function inner * * @param r zero-based recursion level starting with p-1 * @param n pointer to the extents of input or output tensor * @param a pointer to the first input tensor * @param wa pointer to the strides of input tensor a * @param b pointer to the second input tensor * @param wb pointer to the strides of tensor b * @param v previously computed value (start with v = 0). * @return inner product of two tensors. */ template <class PointerIn1, class PointerIn2, class value_t, class SizeType> value_t inner(SizeType const r, SizeType const*const n, PointerIn1 a, SizeType const*const wa, PointerIn2 b, SizeType const*const wb, value_t v) { if(r == 0) for(auto i0 = 0u; i0 < n[0]; a += wa[0], b += wb[0], ++i0) v += *a * *b; else for(auto ir = 0u; ir < n[r]; a += wa[r], b += wb[r], ++ir) v = inner(r-1, n, a, wa, b, wb, v); return v; } template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void outer_2x2(SizeType const pa, PointerOut c, SizeType const*const , SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { // assert(rc == 3); // assert(ra == 1); // assert(rb == 1); for(auto ib1 = 0u; ib1 < nb[1]; b += wb[1], c += wc[pa+1], ++ib1) { auto c2 = c; auto b0 = b; for(auto ib0 = 0u; ib0 < nb[0]; b0 += wb[0], c2 += wc[pa], ++ib0) { const auto b = *b0; auto c1 = c2; auto a1 = a; for(auto ia1 = 0u; ia1 < na[1]; a1 += wa[1], c1 += wc[1], ++ia1) { auto a0 = a1; auto c0 = c1; for(SizeType ia0 = 0u; ia0 < na[0]; a0 += wa[0], c0 += wc[0], ++ia0) *c0 = *a0 * b; } } } } /** @brief Computes the outer product of two tensors * * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq] * * @note called by outer * * * @param[in] pa number of dimensions (rank) of the first input tensor A with pa > 0 * * @param[in] rc recursion level for C that starts with pc-1 * @param[out] c pointer to the output tensor * @param[in] nc pointer to the extents of output tensor c * @param[in] wc pointer to the strides of output tensor c * * @param[in] ra recursion level for A that starts with pa-1 * @param[in] a pointer to the first input tensor * @param[in] na pointer to the extents of the first input tensor a * @param[in] wa pointer to the strides of the first input tensor a * * @param[in] rb recursion level for B that starts with pb-1 * @param[in] b pointer to the second input tensor * @param[in] nb pointer to the extents of the second input tensor b * @param[in] wb pointer to the strides of the second input tensor b */ template<class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void outer(SizeType const pa, SizeType const rc, PointerOut c, SizeType const*const nc, SizeType const*const wc, SizeType const ra, PointerIn1 a, SizeType const*const na, SizeType const*const wa, SizeType const rb, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(rb > 1) for(auto ib = 0u; ib < nb[rb]; b += wb[rb], c += wc[rc], ++ib) outer(pa, rc-1, c, nc, wc, ra, a, na, wa, rb-1, b, nb, wb); else if(ra > 1) for(auto ia = 0u; ia < na[ra]; a += wa[ra], c += wc[ra], ++ia) outer(pa, rc-1, c, nc, wc, ra-1, a, na, wa, rb, b, nb, wb); else outer_2x2(pa, c, nc, wc, a, na, wa, b, nb, wb); //assert(ra==1 && rb==1 && rc==3); } /** @brief Computes the outer product with permutation tuples * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir] * B[j1,...,js] ) * * nc[x] = na[phia[x]] for 1 <= x <= r * nc[r+x] = nb[phib[x]] for 1 <= x <= s * * @note maybe called by ttt function * * @param k zero-based recursion level starting with 0 * @param r number of non-contraction indices of A * @param s number of non-contraction indices of B * @param phia pointer to the permutation tuple of length r for A * @param phib pointer to the permutation tuple of length s for B * @param c pointer to the output tensor C with rank(A)=r+s * @param nc pointer to the extents of tensor C * @param wc pointer to the strides of tensor C * @param a pointer to the first input tensor with rank(A)=r * @param na pointer to the extents of the first input tensor A * @param wa pointer to the strides of the first input tensor A * @param b pointer to the second input tensor B with rank(B)=s * @param nb pointer to the extents of the second input tensor B * @param wb pointer to the strides of the second input tensor B */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void outer(SizeType const k, SizeType const r, SizeType const s, SizeType const*const phia, SizeType const*const phib, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { assert(nc[k] == na[phia[k]-1]); for(size_t ic = 0u; ic < nc[k]; a += wa[phia[k]-1], c += wc[k], ++ic) outer(k+1, r, s, phia,phib, c, nc, wc, a, na, wa, b, nb, wb); } else if(k < r+s-1) { assert(nc[k] == nb[phib[k-r]-1]); for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic) outer(k+1, r, s, phia, phib, c, nc, wc, a, na, wa, b, nb, wb); } else { assert(nc[k] == nb[phib[k-r]-1]); for(size_t ic = 0u; ic < nc[k]; b += wb[phib[k-r]-1], c += wc[k], ++ic) *c = *a * *b; } } } // namespace recursive } // namespace detail } // namespace ublas } // namespace numeric } // namespace boost ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// #include <stdexcept> namespace boost { namespace numeric { namespace ublas { /** @brief Computes the tensor-times-vector product * * Implements * C[i1,i2,...,im-1,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * b[im]) for m>1 and * C[i2,...,ip] = sum(A[i1,...,ip] * b[i1]) for m=1 * * @note calls detail::ttv, detail::ttv0 or detail::mtv * * @param[in] m contraction mode with 0 < m <= p * @param[in] p number of dimensions (rank) of the first input tensor with p > 0 * @param[out] c pointer to the output tensor with rank p-1 * @param[in] nc pointer to the extents of tensor c * @param[in] wc pointer to the strides of tensor c * @param[in] a pointer to the first input tensor * @param[in] na pointer to the extents of input tensor a * @param[in] wa pointer to the strides of input tensor a * @param[in] b pointer to the second input tensor * @param[in] nb pointer to the extents of input tensor b * @param[in] wb pointer to the strides of input tensor b */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void ttv(SizeType const m, SizeType const p, PointerOut c, SizeType const*const nc, SizeType const*const wc, const PointerIn1 a, SizeType const*const na, SizeType const*const wa, const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value, "Static error in boost::numeric::ublas::ttv: Argument types for pointers are not pointer types."); if( m == 0) throw std::length_error("Error in boost::numeric::ublas::ttv: Contraction mode must be greater than zero."); if( p < m ) throw std::length_error("Error in boost::numeric::ublas::ttv: Rank must be greater equal the modus."); if( p == 0) throw std::length_error("Error in boost::numeric::ublas::ttv: Rank must be greater than zero."); if(c == nullptr || a == nullptr || b == nullptr) throw std::length_error("Error in boost::numeric::ublas::ttv: Pointers shall not be null pointers."); for(auto i = 0u; i < m-1; ++i) if(na[i] != nc[i]) throw std::length_error("Error in boost::numeric::ublas::ttv: Extents (except of dimension mode) of A and C must be equal."); for(auto i = m; i < p; ++i) if(na[i] != nc[i-1]) throw std::length_error("Error in boost::numeric::ublas::ttv: Extents (except of dimension mode) of A and C must be equal."); const auto max = std::max(nb[0], nb[1]); if( na[m-1] != max) throw std::length_error("Error in boost::numeric::ublas::ttv: Extent of dimension mode of A and b must be equal."); if((m != 1) && (p > 2)) detail::recursive::ttv(m-1, p-1, p-2, c, nc, wc, a, na, wa, b); else if ((m == 1) && (p > 2)) detail::recursive::ttv0(p-1, c, nc, wc, a, na, wa, b); else if( p == 2 ) detail::recursive::mtv(m-1, c, nc, wc, a, na, wa, b); else /*if( p == 1 )*/{ auto v = std::remove_pointer_t<std::remove_cv_t<PointerOut>>{}; *c = detail::recursive::inner(SizeType(0), na, a, wa, b, wb, v); } } /** @brief Computes the tensor-times-matrix product * * Implements * C[i1,i2,...,im-1,j,im+1,...,ip] = sum(A[i1,i2,...,im,...,ip] * B[j,im]) for m>1 and * C[j,i2,...,ip] = sum(A[i1,i2,...,ip] * B[j,i1]) for m=1 * * @note calls detail::ttm or detail::ttm0 * * @param[in] m contraction mode with 0 < m <= p * @param[in] p number of dimensions (rank) of the first input tensor with p > 0 * @param[out] c pointer to the output tensor with rank p-1 * @param[in] nc pointer to the extents of tensor c * @param[in] wc pointer to the strides of tensor c * @param[in] a pointer to the first input tensor * @param[in] na pointer to the extents of input tensor a * @param[in] wa pointer to the strides of input tensor a * @param[in] b pointer to the second input tensor * @param[in] nb pointer to the extents of input tensor b * @param[in] wb pointer to the strides of input tensor b */ template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType> void ttm(SizeType const m, SizeType const p, PointerOut c, SizeType const*const nc, SizeType const*const wc, const PointerIn1 a, SizeType const*const na, SizeType const*const wa, const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value, "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( m == 0 ) throw std::length_error("Error in boost::numeric::ublas::ttm: Contraction mode must be greater than zero."); if( p < m ) throw std::length_error("Error in boost::numeric::ublas::ttm: Rank must be greater equal than the specified mode."); if( p == 0) throw std::length_error("Error in boost::numeric::ublas::ttm:Rank must be greater than zero."); if(c == nullptr || a == nullptr || b == nullptr) throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers."); for(auto i = 0u; i < m-1; ++i) if(na[i] != nc[i]) throw std::length_error("Error in boost::numeric::ublas::ttm: Extents (except of dimension mode) of A and C must be equal."); for(auto i = m; i < p; ++i) if(na[i] != nc[i]) throw std::length_error("Error in boost::numeric::ublas::ttm: Extents (except of dimension mode) of A and C must be equal."); if(na[m-1] != nb[1]) throw std::length_error("Error in boost::numeric::ublas::ttm: 2nd Extent of B and M-th Extent of A must be the equal."); if(nc[m-1] != nb[0]) throw std::length_error("Error in boost::numeric::ublas::ttm: 1nd Extent of B and M-th Extent of C must be the equal."); if ( m != 1 ) detail::recursive::ttm (m-1, p-1, c, nc, wc, a, na, wa, b, nb, wb); else /*if (m == 1 && p > 2)*/ detail::recursive::ttm0( p-1, c, nc, wc, a, na, wa, b, nb, wb); } /** @brief Computes the tensor-times-tensor product * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * @note calls detail::recursive::ttt or ttm or ttv or inner or outer * * nc[x] = na[phia[x] ] for 1 <= x <= r * nc[r+x] = nb[phib[x] ] for 1 <= x <= s * na[phia[r+x]] = nb[phib[s+x]] for 1 <= x <= q * * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0 * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0 * @param[in] q number of contraction dimensions with pa >= q and pb >= q and q >= 0 * @param[in] phia pointer to a permutation tuple for the first input tensor a * @param[in] phib pointer to a permutation tuple for the second input tensor b * @param[out] c pointer to the output tensor with rank p-1 * @param[in] nc pointer to the extents of tensor c * @param[in] wc pointer to the strides of tensor c * @param[in] a pointer to the first input tensor * @param[in] na pointer to the extents of input tensor a * @param[in] wa pointer to the strides of input tensor a * @param[in] b pointer to the second input tensor * @param[in] nb pointer to the extents of input tensor b * @param[in] wb pointer to the strides of input tensor b */ template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType> void ttt(SizeType const pa, SizeType const pb, SizeType const q, SizeType const*const phia, SizeType const*const phib, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value, "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( pa == 0 || pb == 0) throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero."); if( q > pa && q > pb) throw std::length_error("Error in boost::numeric::ublas::ttt: number of contraction must be smaller than or equal to the tensor order."); SizeType const r = pa - q; SizeType const s = pb - q; if(c == nullptr || a == nullptr || b == nullptr) throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers."); for(auto i = 0ul; i < r; ++i) if( na[phia[i]-1] != nc[i] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and res tensor not correct."); for(auto i = 0ul; i < s; ++i) if( nb[phib[i]-1] != nc[r+i] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of rhs and res not correct."); for(auto i = 0ul; i < q; ++i) if( nb[phib[s+i]-1] != na[phia[r+i]-1] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and rhs not correct."); if(q == 0ul) detail::recursive::outer(SizeType{0},r,s, phia,phib, c,nc,wc, a,na,wa, b,nb,wb); else detail::recursive::ttt(SizeType{0},r,s,q, phia,phib, c,nc,wc, a,na,wa, b,nb,wb); } /** @brief Computes the tensor-times-tensor product * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * @note calls detail::recursive::ttt or ttm or ttv or inner or outer * * nc[x] = na[x ] for 1 <= x <= r * nc[r+x] = nb[x ] for 1 <= x <= s * na[r+x] = nb[s+x] for 1 <= x <= q * * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0 * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0 * @param[in] q number of contraction dimensions with pa >= q and pb >= q and q >= 0 * @param[out] c pointer to the output tensor with rank p-1 * @param[in] nc pointer to the extents of tensor c * @param[in] wc pointer to the strides of tensor c * @param[in] a pointer to the first input tensor * @param[in] na pointer to the extents of input tensor a * @param[in] wa pointer to the strides of input tensor a * @param[in] b pointer to the second input tensor * @param[in] nb pointer to the extents of input tensor b * @param[in] wb pointer to the strides of input tensor b */ template <class PointerIn1, class PointerIn2, class PointerOut, class SizeType> void ttt(SizeType const pa, SizeType const pb, SizeType const q, PointerOut c, SizeType const*const nc, SizeType const*const wc, PointerIn1 a, SizeType const*const na, SizeType const*const wa, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value, "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( pa == 0 || pb == 0) throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero."); if( q > pa && q > pb) throw std::length_error("Error in boost::numeric::ublas::ttt: number of contraction must be smaller than or equal to the tensor order."); SizeType const r = pa - q; SizeType const s = pb - q; SizeType const pc = r+s; if(c == nullptr || a == nullptr || b == nullptr) throw std::length_error("Error in boost::numeric::ublas::ttm: Pointers shall not be null pointers."); for(auto i = 0ul; i < r; ++i) if( na[i] != nc[i] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and res tensor not correct."); for(auto i = 0ul; i < s; ++i) if( nb[i] != nc[r+i] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of rhs and res not correct."); for(auto i = 0ul; i < q; ++i) if( nb[s+i] != na[r+i] ) throw std::length_error("Error in boost::numeric::ublas::ttt: dimensions of lhs and rhs not correct."); using value_type = std::decay_t<decltype(*c)>; if(q == 0ul) detail::recursive::outer(pa, pc-1, c,nc,wc, pa-1, a,na,wa, pb-1, b,nb,wb); else if(r == 0ul && s == 0ul) *c = detail::recursive::inner(q-1, na, a,wa, b,wb, value_type(0) ); else detail::recursive::ttt(SizeType{0},r,s,q, c,nc,wc, a,na,wa, b,nb,wb); } /** @brief Computes the inner product of two tensors * * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,ip]) * * @note calls detail::inner * * @param[in] p number of dimensions (rank) of the first input tensor with p > 0 * @param[in] n pointer to the extents of input or output tensor * @param[in] a pointer to the first input tensor * @param[in] wa pointer to the strides of input tensor a * @param[in] b pointer to the second input tensor * @param[in] wb pointer to the strides of input tensor b * @param[in] v inital value * * @return inner product of two tensors. */ template <class PointerIn1, class PointerIn2, class value_t, class SizeType> auto inner(const SizeType p, SizeType const*const n, const PointerIn1 a, SizeType const*const wa, const PointerIn2 b, SizeType const*const wb, value_t v) { static_assert( std::is_pointer<PointerIn1>::value && std::is_pointer<PointerIn2>::value, "Static error in boost::numeric::ublas::inner: Argument types for pointers must be pointer types."); if(p<2) throw std::length_error("Error in boost::numeric::ublas::inner: Rank must be greater than zero."); if(a == nullptr || b == nullptr) throw std::length_error("Error in boost::numeric::ublas::inner: Pointers shall not be null pointers."); return detail::recursive::inner(p-1, n, a, wa, b, wb, v); } /** @brief Computes the outer product of two tensors * * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq] * * @note calls detail::outer * * @param[out] c pointer to the output tensor * @param[in] pc number of dimensions (rank) of the output tensor c with pc > 0 * @param[in] nc pointer to the extents of output tensor c * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the first input tensor * @param[in] pa number of dimensions (rank) of the first input tensor a with pa > 0 * @param[in] na pointer to the extents of the first input tensor a * @param[in] wa pointer to the strides of the first input tensor a * @param[in] b pointer to the second input tensor * @param[in] pb number of dimensions (rank) of the second input tensor b with pb > 0 * @param[in] nb pointer to the extents of the second input tensor b * @param[in] wb pointer to the strides of the second input tensor b */ template <class PointerOut, class PointerIn1, class PointerIn2, class SizeType> void outer(PointerOut c, SizeType const pc, SizeType const*const nc, SizeType const*const wc, const PointerIn1 a, SizeType const pa, SizeType const*const na, SizeType const*const wa, const PointerIn2 b, SizeType const pb, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer<PointerIn1>::value & std::is_pointer<PointerIn2>::value & std::is_pointer<PointerOut>::value, "Static error in boost::numeric::ublas::outer: argument types for pointers must be pointer types."); if(pa < 2u || pb < 2u) throw std::length_error("Error in boost::numeric::ublas::outer: number of extents of lhs and rhs tensor must be equal or greater than two."); if((pa + pb) != pc) throw std::length_error("Error in boost::numeric::ublas::outer: number of extents of lhs plus rhs tensor must be equal to the number of extents of C."); if(a == nullptr || b == nullptr || c == nullptr) throw std::length_error("Error in boost::numeric::ublas::outer: pointers shall not be null pointers."); detail::recursive::outer(pa, pc-1, c, nc, wc, pa-1, a, na, wa, pb-1, b, nb, wb); } } } } #endif ublas/tensor/storage_traits.hpp 0000644 00000004521 15125237305 0012734 0 ustar 00 // // Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen Germany // #ifndef _BOOST_STORAGE_TRAITS_HPP_ #define _BOOST_STORAGE_TRAITS_HPP_ #include <vector> #include <array> namespace boost { namespace numeric { namespace ublas { template <class A> struct storage_traits; template <class V, class A> struct storage_traits<std::vector<V,A>> { using array_type = std::vector<V,A>; using size_type = typename array_type::size_type; using difference_type = typename array_type::difference_type; using value_type = typename array_type::value_type; using reference = typename array_type::reference; using const_reference = typename array_type::const_reference; using pointer = typename array_type::pointer; using const_pointer = typename array_type::const_pointer; using iterator = typename array_type::iterator; using const_iterator = typename array_type::const_iterator; using reverse_iterator = typename array_type::reverse_iterator; using const_reverse_iterator = typename array_type::const_reverse_iterator; template<class U> using rebind = std::vector<U, typename std::allocator_traits<A>::template rebind_alloc<U>>; }; template <class V, std::size_t N> struct storage_traits<std::array<V,N>> { using array_type = std::array<V,N>; using size_type = typename array_type::size_type; using difference_type = typename array_type::difference_type; using value_type = typename array_type::value_type; using reference = typename array_type::reference; using const_reference = typename array_type::const_reference; using pointer = typename array_type::pointer; using const_pointer = typename array_type::const_pointer; using iterator = typename array_type::iterator; using const_iterator = typename array_type::const_iterator; using reverse_iterator = typename array_type::reverse_iterator; using const_reverse_iterator = typename array_type::const_reverse_iterator; template<class U> using rebind = std::array<U,N>; }; } // ublas } // numeric } // boost #endif // _BOOST_STORAGE_TRAITS_HPP_ ublas/tensor/ostream.hpp 0000644 00000004572 15125237305 0011362 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_OSTREAM_HPP #define BOOST_UBLAS_TENSOR_OSTREAM_HPP #include <ostream> #include <complex> namespace boost { namespace numeric { namespace ublas { namespace detail { template <class value_type> void print(std::ostream& out, value_type const& p) { out << p << " "; } template <class value_type> void print(std::ostream& out, const std::complex<value_type>& p) { out << std::real(p) << "+" << std::imag(p) << "i "; } template <class size_type, class value_type> void print(std::ostream& out, size_type r, const value_type* p, const size_type* w, const size_type* n) { if(r < 2) { out << "[ ... " << std::endl; for(auto row = 0u; row < n[0]; p += w[0], ++row) // iterate over one column { auto p1 = p; for(auto col = 0u; col < n[1]; p1 += w[1], ++col) // iterate over first row { print(out,*p1); } if(row < n[0]-1) out << "; " << std::endl; } out << "]"; } else { out << "cat("<< r+1 <<",..." << std::endl; for(auto d = 0u; d < n[r]-1; p += w[r], ++d){ print(out, r-1, p, w, n); out << ",..." << std::endl; } print(out, r-1, p, w, n); } if(r>1) out << ")"; } //////////////////////////// } } } } namespace boost { namespace numeric { namespace ublas { template<class T, class F, class A> class tensor; template<class T, class F, class A> class matrix; template<class T, class A> class vector; } } } template <class V, class F, class A> std::ostream& operator << (std::ostream& out, boost::numeric::ublas::tensor<V,F,A> const& t) { if(t.extents().is_scalar()){ out << '['; boost::numeric::ublas::detail::print(out,t[0]); out << ']'; } else if(t.extents().is_vector()) { const auto& cat = t.extents().at(0) > t.extents().at(1) ? ';' : ','; out << '['; for(auto i = 0u; i < t.size()-1; ++i){ boost::numeric::ublas::detail::print(out,t[i]); out << cat << ' '; } boost::numeric::ublas::detail::print(out,t[t.size()-1]); out << ']'; } else{ boost::numeric::ublas::detail::print(out, t.rank()-1, t.data(), t.strides().data(), t.extents().data()); } return out; } #endif ublas/tensor/multi_index_utility.hpp 0000644 00000025604 15125237305 0014013 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP #define BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP #include <tuple> #include <type_traits> namespace boost { namespace numeric { namespace ublas { namespace detail { template<class ... index_types> struct has_index_impl; template<class itype_left, class itype_right> struct has_index_impl<itype_left, itype_right> { static constexpr bool value = itype_left::value == itype_right::value; }; template<class itype_left> struct has_index_impl <itype_left, std::tuple<> > { static constexpr bool value = false; }; template<class itype_left, class itype_right> struct has_index_impl <itype_left, std::tuple<itype_right> > { static constexpr bool value = has_index_impl<itype_left,itype_right>::value; }; template<class itype_left, class itype_right, class ... index_types> struct has_index_impl <itype_left, std::tuple<itype_right, index_types...> > { using next_type = has_index_impl<itype_left, std::tuple<index_types...>>; static constexpr bool value = has_index_impl<itype_left,itype_right>::value || next_type::value; }; } // namespace detail /** @brief has_index is true if index occurs once or more in a multi-index * * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type * * @code auto has_index_value = has_index<index_type<1>, std::tuple<index_type<2>,index_type<1>> >::value; @endcode * * @tparam index_type type of index * @tparam tuple_type type of std::tuple representing a multi-index */ template<class index_type, class tuple_type> struct has_index { static constexpr bool value = detail::has_index_impl<std::decay_t<index_type>,std::decay_t<tuple_type>>::value; }; } // namespace ublas } // namespace numeric } // namespace boost //////////////////////////////////////////////// //////////////////////////////////////////////// namespace boost { namespace numeric { namespace ublas { namespace detail { template<class ... index_types> struct valid_multi_index_impl; template<> struct valid_multi_index_impl<std::tuple<>> { static constexpr bool value = true; }; template<class itype> struct valid_multi_index_impl<std::tuple<itype>> { static constexpr bool value = true; }; template<class itype, class ... index_types> struct valid_multi_index_impl<std::tuple<itype,index_types...>> { using ttype = std::tuple<index_types...>; using has_index_type = has_index<itype, ttype>; static constexpr bool is_index_zero = itype::value==0ul; static constexpr bool has_index_value = has_index_type::value && !is_index_zero; static constexpr bool value = !has_index_value && valid_multi_index_impl<ttype>::value; }; } // namespace detail /** @brief valid_multi_index is true if indexes occur only once in a multi-index * * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type * * @code auto valid = valid_multi_index< std::tuple<index_type<2>,index_type<1>> >::value; * @endcode * * @tparam tuple_type type of std::tuple representing a multi-index */ template<class tupe_type> struct valid_multi_index { static constexpr bool value = detail::valid_multi_index_impl<std::decay_t<tupe_type>>::value; }; } // namespace ublas } // namespace numeric } // namespace boost //////////////////////////////////////////////// //////////////////////////////////////////////// namespace boost { namespace numeric { namespace ublas { namespace detail { template<class ... index_types > struct number_equal_indexes_impl; template<class ... itypes_right > struct number_equal_indexes_impl < std::tuple<>, std::tuple<itypes_right...>> { static constexpr unsigned value = 0; }; template<class itype, class ... itypes_left, class ... itypes_right> struct number_equal_indexes_impl < std::tuple<itype,itypes_left...>, std::tuple<itypes_right...>> { using tuple_right = std::tuple<itypes_right...>; using has_index_type = has_index<itype, tuple_right>; static constexpr bool is_index_zero = itype::value==0ul; static constexpr bool has_index_value = has_index_type::value && !is_index_zero; using next_type = number_equal_indexes_impl< std::tuple<itypes_left...>, tuple_right >; static constexpr unsigned v = has_index_value ? 1 : 0; static constexpr unsigned value = v + next_type::value; }; } // namespace detail /** @brief number_equal_indexes contains the number of equal indexes of two multi-indexes * * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type * * * @code auto num = number_equal_indexes< * std::tuple<index_type<2>,index_type<1>>, * std::tuple<index_type<1>,index_type<3>> >::value; * @endcode * * @tparam tuple_type_left type of left std::tuple representing a multi-index * @tparam tuple_type_right type of right std::tuple representing a multi-index */ template<class tuple_left, class tuple_right> struct number_equal_indexes { static constexpr unsigned value = detail::number_equal_indexes_impl< std::decay_t<tuple_left>, std::decay_t<tuple_right>>::value; }; } // namespace ublas } // namespace numeric } // namespace boost //////////////////////////////////////////////// //////////////////////////////////////////////// namespace boost { namespace numeric { namespace ublas { namespace detail { template<std::size_t r, std::size_t m, class itype, class ttype> struct index_position_impl { static constexpr auto is_same = std::is_same< std::decay_t<itype>, std::decay_t<std::tuple_element_t<r,ttype>> >::value; static constexpr auto value = is_same ? r : index_position_impl<r+1,m,itype,ttype>::value; }; template<std::size_t m, class itype, class ttype> struct index_position_impl < m, m, itype, ttype> { static constexpr auto value = std::tuple_size<ttype>::value; }; } // namespace detail /** @brief index_position contains the zero-based index position of an index type within a multi-index * * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type * * @code auto num = index_position< * index_type<1>, * std::tuple<index_type<2>,index_type<1>> >::value; * @endcode * * @returns value returns 0 and N-1 if index_type is found, N otherwise where N is tuple_size_v<tuple_type>. * * @tparam index_type type of index * @tparam tuple_type type of std::tuple that is searched for index */ template<class index_type, class tuple_type> struct index_position { static constexpr auto value = detail::index_position_impl<0ul,std::tuple_size<tuple_type>::value,std::decay_t<index_type>,std::decay_t<tuple_type>>::value; }; } // namespace ublas } // namespace numeric } // namespace boost //////////////////////////////////////////////// //////////////////////////////////////////////// namespace boost { namespace numeric { namespace ublas { namespace detail { template<std::size_t r, std::size_t m> struct index_position_pairs_impl { template<class array_type, class tuple_left, class tuple_right> static constexpr void run(array_type& out, tuple_left const& lhs, tuple_right const& rhs, std::size_t p) { using index_type = std::tuple_element_t<r-1,tuple_left>; using has_index_type = has_index<index_type, tuple_right>; using get_index_type = index_position<index_type,tuple_right>; using next_type = index_position_pairs_impl<r+1,m>; if constexpr ( has_index_type::value && index_type::value != 0) out[p++] = std::make_pair(r-1,get_index_type::value); next_type::run( out, lhs, rhs, p ); } }; template<std::size_t m> struct index_position_pairs_impl<m,m> { template<class array_type, class tuple_left, class tuple_right> static constexpr void run(array_type& out, tuple_left const& , tuple_right const& , std::size_t p) { using index_type = std::tuple_element_t<m-1,tuple_left>; using has_index_type = has_index<index_type, tuple_right>; using get_index_type = index_position<index_type, tuple_right>; if constexpr ( has_index_type::value && index_type::value != 0 ) out[p] = std::make_pair(m-1,get_index_type::value); } }; template<std::size_t r> struct index_position_pairs_impl<r,0> { template<class array_type, class tuple_left, class tuple_right> static constexpr void run(array_type&, tuple_left const& , tuple_right const& , std::size_t) {} }; } // namespace detail /** @brief index_position_pairs returns zero-based index positions of matching indexes of two multi-indexes * * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type * * @code auto pairs = index_position_pairs(std::make_tuple(_a,_b), std::make_tuple(_b,_c)); * @endcode * * @returns a std::array instance containing index position pairs of type std::pair<std::size_t, std::size_t>. * * @param lhs left std::tuple instance representing a multi-index * @param rhs right std::tuple instance representing a multi-index */ template<class tuple_left, class tuple_right> auto index_position_pairs(tuple_left const& lhs, tuple_right const& rhs) { using pair_type = std::pair<std::size_t,std::size_t>; constexpr auto m = std::tuple_size<tuple_left >::value; constexpr auto p = number_equal_indexes<tuple_left, tuple_right>::value; auto array = std::array<pair_type,p>{}; detail::index_position_pairs_impl<1,m>::run(array, lhs, rhs,0); return array; } } // namespace ublas } // namespace numeric } // namespace boost //////////////////////////// //////////////////////////// //////////////////////////// //////////////////////////// namespace boost { namespace numeric { namespace ublas { namespace detail { template<class array_type, std::size_t ... R> constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence<R...> ) { return std::make_pair( std::vector<std::size_t>{std::get<0>( std::get<R>(array) )+1 ...} , std::vector<std::size_t>{std::get<1>( std::get<R>(array) )+1 ...} ); } } // namespace detail /** @brief array_to_vector converts a std::array of zero-based index position pairs into two std::vector of one-based index positions * * @code auto two_vectors = array_to_vector(std::make_array ( std::make_pair(1,2), std::make_pair(3,4) ) ) ; * @endcode * * @returns two std::vector of one-based index positions * * @param array std::array of zero-based index position pairs */ template<class pair_type, std::size_t N> constexpr auto array_to_vector( std::array<pair_type,N> const& array) { constexpr auto sequence = std::make_index_sequence<N>{}; return detail::array_to_vector_impl( array, sequence ); } } // namespace ublas } // namespace numeric } // namespace boost #endif // _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ ublas/tensor/strides.hpp 0000644 00000013733 15125237305 0011364 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // /// \file strides.hpp Definition for the basic_strides template class #ifndef BOOST_UBLAS_TENSOR_STRIDES_HPP #define BOOST_UBLAS_TENSOR_STRIDES_HPP #include <vector> #include <limits> #include <numeric> #include <stdexcept> #include <initializer_list> #include <algorithm> #include <cassert> #include <boost/numeric/ublas/functional.hpp> namespace boost { namespace numeric { namespace ublas { using first_order = column_major; using last_order = row_major; template<class T> class basic_extents; /** @brief Template class for storing tensor strides for iteration with runtime variable size. * * Proxy template class of std::vector<int_type>. * */ template<class __int_type, class __layout> class basic_strides { public: using base_type = std::vector<__int_type>; static_assert( std::numeric_limits<typename base_type::value_type>::is_integer, "Static error in boost::numeric::ublas::basic_strides: type must be of type integer."); static_assert(!std::numeric_limits<typename base_type::value_type>::is_signed, "Static error in boost::numeric::ublas::basic_strides: type must be of type unsigned integer."); static_assert(std::is_same<__layout,first_order>::value || std::is_same<__layout,last_order>::value, "Static error in boost::numeric::ublas::basic_strides: layout type must either first or last order"); using layout_type = __layout; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using size_type = typename base_type::size_type; using const_pointer = typename base_type::const_pointer; using const_iterator = typename base_type::const_iterator; /** @brief Default constructs basic_strides * * @code auto ex = basic_strides<unsigned>{}; */ constexpr explicit basic_strides() : _base{} { } /** @brief Constructs basic_strides from basic_extents for the first- and last-order storage formats * * @code auto strides = basic_strides<unsigned>( basic_extents<std::size_t>{2,3,4} ); * */ template <class T> basic_strides(basic_extents<T> const& s) : _base(s.size(),1) { if(s.empty()) return; if(!s.valid()) throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : shape is not valid."); if(s.is_vector() || s.is_scalar()) return; if(this->size() < 2) throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : size of strides must be greater or equal 2."); if constexpr (std::is_same<layout_type,first_order>::value){ size_type k = 1ul, kend = this->size(); for(; k < kend; ++k) _base[k] = _base[k-1] * s[k-1]; } else { size_type k = this->size()-2, kend = 0ul; for(; k > kend; --k) _base[k] = _base[k+1] * s[k+1]; _base[0] = _base[1] * s[1]; } } basic_strides(basic_strides const& l) : _base(l._base) {} basic_strides(basic_strides && l ) : _base(std::move(l._base)) {} basic_strides(base_type const& l ) : _base(l) {} basic_strides(base_type && l ) : _base(std::move(l)) {} ~basic_strides() = default; basic_strides& operator=(basic_strides other) { swap (*this, other); return *this; } friend void swap(basic_strides& lhs, basic_strides& rhs) { std::swap(lhs._base , rhs._base); } const_reference operator[] (size_type p) const{ return _base[p]; } const_pointer data() const{ return _base.data(); } const_reference at (size_type p) const{ return _base.at(p); } bool empty() const{ return _base.empty(); } size_type size() const{ return _base.size(); } template<class other_layout> bool operator == (basic_strides<value_type, other_layout> const& b) const{ return b.base() == this->base(); } template<class other_layout> bool operator != (basic_strides<value_type, other_layout> const& b) const{ return b.base() != this->base(); } bool operator == (basic_strides const& b) const{ return b._base == _base; } bool operator != (basic_strides const& b) const{ return b._base != _base; } const_iterator begin() const{ return _base.begin(); } const_iterator end() const{ return _base.end(); } void clear() { this->_base.clear(); } base_type const& base() const{ return this->_base; } protected: base_type _base; }; template<class layout_type> using strides = basic_strides<std::size_t, layout_type>; namespace detail { /** @brief Returns relative memory index with respect to a multi-index * * @code auto j = access(std::vector{3,4,5}, strides{shape{4,2,3},first_order}); @endcode * * @param[in] i multi-index of length p * @param[in] w stride vector of length p * @returns relative memory location depending on \c i and \c w */ BOOST_UBLAS_INLINE template<class size_type, class layout_type> auto access(std::vector<size_type> const& i, basic_strides<size_type,layout_type> const& w) { const auto p = i.size(); size_type sum = 0u; for(auto r = 0u; r < p; ++r) sum += i[r]*w[r]; return sum; } /** @brief Returns relative memory index with respect to a multi-index * * @code auto j = access(0, strides{shape{4,2,3},first_order}, 2,3,4); @endcode * * @param[in] i first element of the partial multi-index * @param[in] is the following elements of the partial multi-index * @param[in] sum the current relative memory index * @returns relative memory location depending on \c i and \c w */ BOOST_UBLAS_INLINE template<std::size_t r, class layout_type, class ... size_types> auto access(std::size_t sum, basic_strides<std::size_t, layout_type> const& w, std::size_t i, size_types ... is) { sum+=i*w[r]; if constexpr (sizeof...(is) == 0) return sum; else return detail::access<r+1>(sum,w,std::forward<size_types>(is)...); } } } } } #endif ublas/tensor/algorithms.hpp 0000644 00000026005 15125237305 0012054 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP #define _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP #include <stdexcept> #include <complex> #include <functional> namespace boost { namespace numeric { namespace ublas { /** @brief Copies a tensor to another tensor with different layouts * * Implements C[i1,i2,...,ip] = A[i1,i2,...,ip] * * @param[in] p rank of input and output tensor * @param[in] n pointer to the extents of input or output tensor of length p * @param[in] pi pointer to a one-based permutation tuple of length p * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a */ template <class PointerOut, class PointerIn, class SizeType> void copy(const SizeType p, SizeType const*const n, PointerOut c, SizeType const*const wc, PointerIn a, SizeType const*const wa) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value, "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types."); if( p == 0 ) return; if(c == nullptr || a == nullptr) throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); if(wc == nullptr || wa == nullptr) throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); if(n == nullptr) throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda; lambda = [&lambda, n, wc, wa](SizeType r, PointerOut c, PointerIn a) { if(r > 0) for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d) lambda(r-1, c, a ); else for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d) *c = *a; }; lambda( p-1, c, a ); } /** @brief Copies a tensor to another tensor with different layouts applying a unary operation * * Implements C[i1,i2,...,ip] = op ( A[i1,i2,...,ip] ) * * @param[in] p rank of input and output tensor * @param[in] n pointer to the extents of input or output tensor of length p * @param[in] pi pointer to a one-based permutation tuple of length p * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a * @param[in] op unary operation */ template <class PointerOut, class PointerIn, class SizeType, class UnaryOp> void transform(const SizeType p, SizeType const*const n, PointerOut c, SizeType const*const wc, PointerIn a, SizeType const*const wa, UnaryOp op) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value, "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) return; if(c == nullptr || a == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(wc == nullptr || wa == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(n == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda; lambda = [&lambda, n, wc, wa, op](SizeType r, PointerOut c, PointerIn a) { if(r > 0) for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d) lambda(r-1, c, a); else for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d) *c = op(*a); }; lambda( p-1, c, a ); } /** @brief Performs a reduce operation with all elements of the tensor and an initial value * * Implements k = sum_{i1,..,ip} A[i1,i2,...,ip] * * @param[in] r zero-based recursion level starting with r=p-1 * @param[in] n pointer to the extents of input or output tensor * @param[in] a pointer to the first input tensor * @param[in] w pointer to the strides of input tensor a * @param[in] k accumulated value */ template <class PointerIn, class ValueType, class SizeType> ValueType accumulate(SizeType const p, SizeType const*const n, PointerIn a, SizeType const*const w, ValueType k) { static_assert(std::is_pointer<PointerIn>::value, "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) return k; if(a == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(w == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(n == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); std::function<ValueType(SizeType r, PointerIn a, ValueType k)> lambda; lambda = [&lambda, n, w](SizeType r, PointerIn a, ValueType k) { if(r > 0u) for(auto d = 0u; d < n[r]; a += w[r], ++d) k = lambda(r-1, a, k); else for(auto d = 0u; d < n[0]; a += w[0], ++d) k += *a; return k; }; return lambda( p-1, a, k ); } /** @brief Performs a reduce operation with all elements of the tensor and an initial value * * Implements k = op ( k , A[i1,i2,...,ip] ), for all ir * * @param[in] r zero-based recursion level starting with r=p-1 * @param[in] n pointer to the extents of input or output tensor * @param[in] a pointer to the first input tensor * @param[in] w pointer to the strides of input tensor a * @param[in] k accumulated value * @param[in] op binary operation */ template <class PointerIn, class ValueType, class SizeType, class BinaryOp> ValueType accumulate(SizeType const p, SizeType const*const n, PointerIn a, SizeType const*const w, ValueType k, BinaryOp op) { static_assert(std::is_pointer<PointerIn>::value, "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) return k; if(a == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(w == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); if(n == nullptr) throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); std::function<ValueType(SizeType r, PointerIn a, ValueType k)> lambda; lambda = [&lambda, n, w, op](SizeType r, PointerIn a, ValueType k) { if(r > 0u) for(auto d = 0u; d < n[r]; a += w[r], ++d) k = lambda(r-1, a, k); else for(auto d = 0u; d < n[0]; a += w[0], ++d) k = op ( k, *a ); return k; }; return lambda( p-1, a, k ); } /** @brief Transposes a tensor * * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip] * * @note is used in function trans * * @param[in] p rank of input and output tensor * @param[in] na pointer to the extents of the input tensor a of length p * @param[in] pi pointer to a one-based permutation tuple of length p * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a */ template <class PointerOut, class PointerIn, class SizeType> void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, PointerOut c, SizeType const*const wc, PointerIn a, SizeType const*const wa) { static_assert( std::is_pointer<PointerOut>::value & std::is_pointer<PointerIn>::value, "Static error in boost::numeric::ublas::trans: Argument types for pointers are not pointer types."); if( p < 2) return; if(c == nullptr || a == nullptr) throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(na == nullptr) throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null."); if(wc == nullptr || wa == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(na == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(pi == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); std::function<void(SizeType r, PointerOut c, PointerIn a)> lambda; lambda = [&lambda, na, wc, wa, pi](SizeType r, PointerOut c, PointerIn a) { if(r > 0) for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d) lambda(r-1, c, a); else for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d) *c = *a; }; lambda( p-1, c, a ); } /** @brief Transposes a tensor * * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip] * * @note is used in function trans * * @param[in] p rank of input and output tensor * @param[in] na pointer to the extents of the input tensor a of length p * @param[in] pi pointer to a one-based permutation tuple of length p * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a */ template <class ValueType, class SizeType> void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, std::complex<ValueType>* c, SizeType const*const wc, std::complex<ValueType>* a, SizeType const*const wa) { if( p < 2) return; if(c == nullptr || a == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(wc == nullptr || wa == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(na == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); if(pi == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); std::function<void(SizeType r, std::complex<ValueType>* c, std::complex<ValueType>* a)> lambda; lambda = [&lambda, na, wc, wa, pi](SizeType r, std::complex<ValueType>* c, std::complex<ValueType>* a) { if(r > 0) for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d) lambda(r-1, c, a); else for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d) *c = std::conj(*a); }; lambda( p-1, c, a ); } } } } #endif ublas/tensor/expression_evaluation.hpp 0000644 00000021375 15125237305 0014336 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_ #define _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_ #include <type_traits> #include <stdexcept> namespace boost::numeric::ublas { template<class element_type, class storage_format, class storage_type> class tensor; template<class size_type> class basic_extents; } namespace boost::numeric::ublas::detail { template<class T, class D> struct tensor_expression; template<class T, class EL, class ER, class OP> struct binary_tensor_expression; template<class T, class E, class OP> struct unary_tensor_expression; } namespace boost::numeric::ublas::detail { template<class T, class E> struct has_tensor_types { static constexpr bool value = false; }; template<class T> struct has_tensor_types<T,T> { static constexpr bool value = true; }; template<class T, class D> struct has_tensor_types<T, tensor_expression<T,D>> { static constexpr bool value = std::is_same<T,D>::value || has_tensor_types<T,D>::value; }; template<class T, class EL, class ER, class OP> struct has_tensor_types<T, binary_tensor_expression<T,EL,ER,OP>> { static constexpr bool value = std::is_same<T,EL>::value || std::is_same<T,ER>::value || has_tensor_types<T,EL>::value || has_tensor_types<T,ER>::value; }; template<class T, class E, class OP> struct has_tensor_types<T, unary_tensor_expression<T,E,OP>> { static constexpr bool value = std::is_same<T,E>::value || has_tensor_types<T,E>::value; }; } // namespace boost::numeric::ublas::detail namespace boost::numeric::ublas::detail { /** @brief Retrieves extents of the tensor * */ template<class T, class F, class A> auto retrieve_extents(tensor<T,F,A> const& t) { return t.extents(); } /** @brief Retrieves extents of the tensor expression * * @note tensor expression must be a binary tree with at least one tensor type * * @returns extents of the child expression if it is a tensor or extents of one child of its child. */ template<class T, class D> auto retrieve_extents(tensor_expression<T,D> const& expr) { static_assert(detail::has_tensor_types<T,tensor_expression<T,D>>::value, "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); auto const& cast_expr = static_cast<D const&>(expr); if constexpr ( std::is_same<T,D>::value ) return cast_expr.extents(); else return retrieve_extents(cast_expr); } /** @brief Retrieves extents of the binary tensor expression * * @note tensor expression must be a binary tree with at least one tensor type * * @returns extents of the (left and if necessary then right) child expression if it is a tensor or extents of a child of its (left and if necessary then right) child. */ template<class T, class EL, class ER, class OP> auto retrieve_extents(binary_tensor_expression<T,EL,ER,OP> const& expr) { static_assert(detail::has_tensor_types<T,binary_tensor_expression<T,EL,ER,OP>>::value, "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); if constexpr ( std::is_same<T,EL>::value ) return expr.el.extents(); if constexpr ( std::is_same<T,ER>::value ) return expr.er.extents(); else if constexpr ( detail::has_tensor_types<T,EL>::value ) return retrieve_extents(expr.el); else if constexpr ( detail::has_tensor_types<T,ER>::value ) return retrieve_extents(expr.er); } /** @brief Retrieves extents of the binary tensor expression * * @note tensor expression must be a binary tree with at least one tensor type * * @returns extents of the child expression if it is a tensor or extents of a child of its child. */ template<class T, class E, class OP> auto retrieve_extents(unary_tensor_expression<T,E,OP> const& expr) { static_assert(detail::has_tensor_types<T,unary_tensor_expression<T,E,OP>>::value, "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); if constexpr ( std::is_same<T,E>::value ) return expr.e.extents(); else if constexpr ( detail::has_tensor_types<T,E>::value ) return retrieve_extents(expr.e); } } // namespace boost::numeric::ublas::detail /////////////// namespace boost::numeric::ublas::detail { template<class T, class F, class A, class S> auto all_extents_equal(tensor<T,F,A> const& t, basic_extents<S> const& extents) { return extents == t.extents(); } template<class T, class D, class S> auto all_extents_equal(tensor_expression<T,D> const& expr, basic_extents<S> const& extents) { static_assert(detail::has_tensor_types<T,tensor_expression<T,D>>::value, "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); auto const& cast_expr = static_cast<D const&>(expr); if constexpr ( std::is_same<T,D>::value ) if( extents != cast_expr.extents() ) return false; if constexpr ( detail::has_tensor_types<T,D>::value ) if ( !all_extents_equal(cast_expr, extents)) return false; return true; } template<class T, class EL, class ER, class OP, class S> auto all_extents_equal(binary_tensor_expression<T,EL,ER,OP> const& expr, basic_extents<S> const& extents) { static_assert(detail::has_tensor_types<T,binary_tensor_expression<T,EL,ER,OP>>::value, "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); if constexpr ( std::is_same<T,EL>::value ) if(extents != expr.el.extents()) return false; if constexpr ( std::is_same<T,ER>::value ) if(extents != expr.er.extents()) return false; if constexpr ( detail::has_tensor_types<T,EL>::value ) if(!all_extents_equal(expr.el, extents)) return false; if constexpr ( detail::has_tensor_types<T,ER>::value ) if(!all_extents_equal(expr.er, extents)) return false; return true; } template<class T, class E, class OP, class S> auto all_extents_equal(unary_tensor_expression<T,E,OP> const& expr, basic_extents<S> const& extents) { static_assert(detail::has_tensor_types<T,unary_tensor_expression<T,E,OP>>::value, "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); if constexpr ( std::is_same<T,E>::value ) if(extents != expr.e.extents()) return false; if constexpr ( detail::has_tensor_types<T,E>::value ) if(!all_extents_equal(expr.e, extents)) return false; return true; } } // namespace boost::numeric::ublas::detail namespace boost::numeric::ublas::detail { /** @brief Evaluates expression for a tensor * * Assigns the results of the expression to the tensor. * * \note Checks if shape of the tensor matches those of all tensors within the expression. */ template<class tensor_type, class derived_type> void eval(tensor_type& lhs, tensor_expression<tensor_type, derived_type> const& expr) { if constexpr (detail::has_tensor_types<tensor_type, tensor_expression<tensor_type,derived_type> >::value ) if(!detail::all_extents_equal(expr, lhs.extents() )) throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); #pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) lhs(i) = expr()(i); } /** @brief Evaluates expression for a tensor * * Applies a unary function to the results of the expressions before the assignment. * Usually applied needed for unary operators such as A += C; * * \note Checks if shape of the tensor matches those of all tensors within the expression. */ template<class tensor_type, class derived_type, class unary_fn> void eval(tensor_type& lhs, tensor_expression<tensor_type, derived_type> const& expr, unary_fn const fn) { if constexpr (detail::has_tensor_types< tensor_type, tensor_expression<tensor_type,derived_type> >::value ) if(!detail::all_extents_equal( expr, lhs.extents() )) throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); #pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) fn(lhs(i), expr()(i)); } /** @brief Evaluates expression for a tensor * * Applies a unary function to the results of the expressions before the assignment. * Usually applied needed for unary operators such as A += C; * * \note Checks if shape of the tensor matches those of all tensors within the expression. */ template<class tensor_type, class unary_fn> void eval(tensor_type& lhs, unary_fn const fn) { #pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) fn(lhs(i)); } } #endif ublas/tensor/tensor.hpp 0000644 00000046302 15125237305 0011217 0 ustar 00 // Copyright (c) 2018-2019 // Cem Bassoy // // 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 // Fraunhofer and Google in producing this work // which started as a Google Summer of Code project. // /// \file tensor.hpp Definition for the tensor template class #ifndef BOOST_UBLAS_TENSOR_IMPL_HPP #define BOOST_UBLAS_TENSOR_IMPL_HPP #include <boost/config.hpp> #include <initializer_list> #include "algorithms.hpp" #include "expression.hpp" #include "expression_evaluation.hpp" #include "extents.hpp" #include "strides.hpp" #include "index.hpp" namespace boost { namespace numeric { namespace ublas { template<class T, class F, class A> class tensor; template<class T, class F, class A> class matrix; template<class T, class A> class vector; ///** \brief Base class for Tensor container models // * // * it does not model the Tensor concept but all derived types should. // * The class defines a common base type and some common interface for all // * statically derived Tensor classes // * We implement the casts to the statically derived type. // */ //template<class C> //class tensor_container: // public detail::tensor_expression<C> //{ //public: // static const unsigned complexity = 0; // typedef C container_type; // typedef tensor_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); // } //}; /** @brief A dense tensor of values of type \c T. * * For a \f$n\f$-dimensional tensor \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 tensor (like int, double, complex,...) * @tparam A The type of the storage array of the tensor. Default is \c unbounded_array<T>. \c <bounded_array<T> and \c std::vector<T> can also be used */ template<class T, class F = first_order, class A = std::vector<T,std::allocator<T>> > class tensor: public detail::tensor_expression<tensor<T, F, A>,tensor<T, F, A>> { static_assert( std::is_same<F,first_order>::value || std::is_same<F,last_order >::value, "boost::numeric::tensor template class only supports first- or last-order storage formats."); using self_type = tensor<T, F, A>; public: template<class derived_type> using tensor_expression_type = detail::tensor_expression<self_type,derived_type>; template<class derived_type> using matrix_expression_type = matrix_expression<derived_type>; template<class derived_type> using vector_expression_type = vector_expression<derived_type>; using super_type = tensor_expression_type<self_type>; // static_assert(std::is_same_v<tensor_expression_type<self_type>, detail::tensor_expression<tensor<T,F,A>,tensor<T,F,A>>>, "tensor_expression_type<self_type>"); using array_type = A; using layout_type = F; using size_type = typename array_type::size_type; using difference_type = typename array_type::difference_type; using value_type = typename array_type::value_type; using reference = typename array_type::reference; using const_reference = typename array_type::const_reference; using pointer = typename array_type::pointer; using const_pointer = typename array_type::const_pointer; using iterator = typename array_type::iterator; using const_iterator = typename array_type::const_iterator; using reverse_iterator = typename array_type::reverse_iterator; using const_reverse_iterator = typename array_type::const_reverse_iterator; using tensor_temporary_type = self_type; using storage_category = dense_tag; using strides_type = basic_strides<std::size_t,layout_type>; using extents_type = shape; using matrix_type = matrix<value_type,layout_type,array_type>; using vector_type = vector<value_type,array_type>; /** @brief Constructs a tensor. * * @note the tensor is empty. * @note the tensor needs to reshaped for further use. * */ BOOST_UBLAS_INLINE constexpr tensor () : tensor_expression_type<self_type>() // container_type , extents_() , strides_() , data_() { } /** @brief Constructs a tensor with an initializer list * * By default, its elements are initialized to 0. * * @code tensor<float> A{4,2,3}; @endcode * * @param l initializer list for setting the dimension extents of the tensor */ explicit BOOST_UBLAS_INLINE tensor (std::initializer_list<size_type> l) : tensor_expression_type<self_type>() , extents_ (std::move(l)) , strides_ (extents_) , data_ (extents_.product()) { } /** @brief Constructs a tensor with a \c shape * * By default, its elements are initialized to 0. * * @code tensor<float> A{extents{4,2,3}}; @endcode * * @param s initial tensor dimension extents */ explicit BOOST_UBLAS_INLINE tensor (extents_type const& s) : tensor_expression_type<self_type>() //tensor_container<self_type>() , extents_ (s) , strides_ (extents_) , data_ (extents_.product()) {} /** @brief Constructs a tensor with a \c shape and initiates it with one-dimensional data * * @code tensor<float> A{extents{4,2,3}, array }; @endcode * * * @param s initial tensor dimension extents * @param a container of \c array_type that is copied according to the storage layout */ BOOST_UBLAS_INLINE tensor (extents_type const& s, const array_type &a) : tensor_expression_type<self_type>() //tensor_container<self_type>() , extents_ (s) , strides_ (extents_) , data_ (a) { if(this->extents_.product() != this->data_.size()) throw std::runtime_error("Error in boost::numeric::ublas::tensor: size of provided data and specified extents do not match."); } /** @brief Constructs a tensor using a shape tuple and initiates it with a value. * * @code tensor<float> A{extents{4,2,3}, 1 }; @endcode * * @param e initial tensor dimension extents * @param i initial value of all elements of type \c value_type */ BOOST_UBLAS_INLINE tensor (extents_type const& e, const value_type &i) : tensor_expression_type<self_type>() //tensor_container<self_type> () , extents_ (e) , strides_ (extents_) , data_ (extents_.product(), i) {} /** @brief Constructs a tensor from another tensor * * @param v tensor to be copied. */ BOOST_UBLAS_INLINE tensor (const tensor &v) : tensor_expression_type<self_type>() , extents_ (v.extents_) , strides_ (v.strides_) , data_ (v.data_ ) {} /** @brief Constructs a tensor from another tensor * * @param v tensor to be moved. */ BOOST_UBLAS_INLINE tensor (tensor &&v) : tensor_expression_type<self_type>() //tensor_container<self_type> () , extents_ (std::move(v.extents_)) , strides_ (std::move(v.strides_)) , data_ (std::move(v.data_ )) {} /** @brief Constructs a tensor with a matrix * * \note Initially the tensor will be two-dimensional. * * @param v matrix to be copied. */ BOOST_UBLAS_INLINE tensor (const matrix_type &v) : tensor_expression_type<self_type>() , extents_ () , strides_ () , data_ (v.data()) { if(!data_.empty()){ extents_ = extents_type{v.size1(),v.size2()}; strides_ = strides_type(extents_); } } /** @brief Constructs a tensor with a matrix * * \note Initially the tensor will be two-dimensional. * * @param v matrix to be moved. */ BOOST_UBLAS_INLINE tensor (matrix_type &&v) : tensor_expression_type<self_type>() , extents_ {} , strides_ {} , data_ {} { if(v.size1()*v.size2() != 0){ extents_ = extents_type{v.size1(),v.size2()}; strides_ = strides_type(extents_); data_ = std::move(v.data()); } } /** @brief Constructs a tensor using a \c vector * * @note It is assumed that vector is column vector * @note Initially the tensor will be one-dimensional. * * @param v vector to be copied. */ BOOST_UBLAS_INLINE tensor (const vector_type &v) : tensor_expression_type<self_type>() , extents_ () , strides_ () , data_ (v.data()) { if(!data_.empty()){ extents_ = extents_type{data_.size(),1}; strides_ = strides_type(extents_); } } /** @brief Constructs a tensor using a \c vector * * @param v vector to be moved. */ BOOST_UBLAS_INLINE tensor (vector_type &&v) : tensor_expression_type<self_type>() , extents_ {} , strides_ {} , data_ {} { if(v.size() != 0){ extents_ = extents_type{v.size(),1}; strides_ = strides_type(extents_); data_ = std::move(v.data()); } } /** @brief Constructs a tensor with another tensor with a different layout * * @param other tensor with a different layout to be copied. */ BOOST_UBLAS_INLINE template<class other_layout> tensor (const tensor<value_type, other_layout> &other) : tensor_expression_type<self_type> () , extents_ (other.extents()) , strides_ (other.extents()) , data_ (other.extents().product()) { copy(this->rank(), this->extents().data(), this->data(), this->strides().data(), other.data(), other.strides().data()); } /** @brief Constructs a tensor with an tensor expression * * @code tensor<float> A = B + 3 * C; @endcode * * @note type must be specified of tensor must be specified. * @note dimension extents are extracted from tensors within the expression. * * @param expr tensor expression */ BOOST_UBLAS_INLINE template<class derived_type> tensor (const tensor_expression_type<derived_type> &expr) : tensor_expression_type<self_type> () , extents_ ( detail::retrieve_extents(expr) ) , strides_ ( extents_ ) , data_ ( extents_.product() ) { static_assert( detail::has_tensor_types<self_type, tensor_expression_type<derived_type>>::value, "Error in boost::numeric::ublas::tensor: expression does not contain a tensor. cannot retrieve shape."); detail::eval( *this, expr ); } /** @brief Constructs a tensor with a matrix expression * * @code tensor<float> A = B + 3 * C; @endcode * * @note matrix expression is evaluated and pushed into a temporary matrix before assignment. * @note extents are automatically extracted from the temporary matrix * * @param expr matrix expression */ BOOST_UBLAS_INLINE template<class derived_type> tensor (const matrix_expression_type<derived_type> &expr) : tensor( matrix_type ( expr ) ) { } /** @brief Constructs a tensor with a vector expression * * @code tensor<float> A = b + 3 * b; @endcode * * @note matrix expression is evaluated and pushed into a temporary matrix before assignment. * @note extents are automatically extracted from the temporary matrix * * @param expr vector expression */ BOOST_UBLAS_INLINE template<class derived_type> tensor (const vector_expression_type<derived_type> &expr) : tensor( vector_type ( expr ) ) { } /** @brief Evaluates the tensor_expression and assigns the results to the tensor * * @code A = B + C * 2; @endcode * * @note rank and dimension extents of the tensors in the expressions must conform with this tensor. * * @param expr expression that is evaluated. */ BOOST_UBLAS_INLINE template<class derived_type> tensor &operator = (const tensor_expression_type<derived_type> &expr) { detail::eval(*this, expr); return *this; } tensor& operator=(tensor other) { swap (*this, other); return *this; } tensor& operator=(const_reference v) { std::fill(this->begin(), this->end(), v); return *this; } /** @brief Returns true if the tensor is empty (\c size==0) */ BOOST_UBLAS_INLINE bool empty () const { return this->data_.empty(); } /** @brief Returns the size of the tensor */ BOOST_UBLAS_INLINE size_type size () const { return this->data_.size (); } /** @brief Returns the size of the tensor */ BOOST_UBLAS_INLINE size_type size (size_type r) const { return this->extents_.at(r); } /** @brief Returns the number of dimensions/modes of the tensor */ BOOST_UBLAS_INLINE size_type rank () const { return this->extents_.size(); } /** @brief Returns the number of dimensions/modes of the tensor */ BOOST_UBLAS_INLINE size_type order () const { return this->extents_.size(); } /** @brief Returns the strides of the tensor */ BOOST_UBLAS_INLINE strides_type const& strides () const { return this->strides_; } /** @brief Returns the extents of the tensor */ BOOST_UBLAS_INLINE extents_type const& extents () const { return this->extents_; } /** @brief Returns a \c const reference to the container. */ BOOST_UBLAS_INLINE const_pointer data () const { return this->data_.data(); } /** @brief Returns a \c const reference to the container. */ BOOST_UBLAS_INLINE pointer data () { return this->data_.data(); } /** @brief Element access using a single index. * * @code auto a = A[i]; @endcode * * @param i zero-based index where 0 <= i < this->size() */ BOOST_UBLAS_INLINE const_reference operator [] (size_type i) const { return this->data_[i]; } /** @brief Element access using a single index. * * * @code A[i] = a; @endcode * * @param i zero-based index where 0 <= i < this->size() */ BOOST_UBLAS_INLINE reference operator [] (size_type i) { return this->data_[i]; } /** @brief Element access using a multi-index or single-index. * * * @code auto a = A.at(i,j,k); @endcode or * @code auto a = A.at(i); @endcode * * @param i zero-based index where 0 <= i < this->size() if sizeof...(is) == 0, else 0<= i < this->size(0) * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank() */ template<class ... size_types> BOOST_UBLAS_INLINE const_reference at (size_type i, size_types ... is) const { if constexpr (sizeof...(is) == 0) return this->data_[i]; else return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)]; } /** @brief Element access using a multi-index or single-index. * * * @code A.at(i,j,k) = a; @endcode or * @code A.at(i) = a; @endcode * * @param i zero-based index where 0 <= i < this->size() if sizeof...(is) == 0, else 0<= i < this->size(0) * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank() */ BOOST_UBLAS_INLINE template<class ... size_types> reference at (size_type i, size_types ... is) { if constexpr (sizeof...(is) == 0) return this->data_[i]; else return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)]; } /** @brief Element access using a single index. * * * @code A(i) = a; @endcode * * @param i zero-based index where 0 <= i < this->size() */ BOOST_UBLAS_INLINE const_reference operator()(size_type i) const { return this->data_[i]; } /** @brief Element access using a single index. * * @code A(i) = a; @endcode * * @param i zero-based index where 0 <= i < this->size() */ BOOST_UBLAS_INLINE reference operator()(size_type i){ return this->data_[i]; } /** @brief Generates a tensor index for tensor contraction * * * @code auto Ai = A(_i,_j,k); @endcode * * @param i placeholder * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank() */ BOOST_UBLAS_INLINE template<std::size_t I, class ... index_types> decltype(auto) operator() (index::index_type<I> p, index_types ... ps) const { constexpr auto N = sizeof...(ps)+1; if( N != this->rank() ) throw std::runtime_error("Error in boost::numeric::ublas::operator(): size of provided index_types does not match with the rank."); return std::make_pair( std::cref(*this), std::make_tuple( p, std::forward<index_types>(ps)... ) ); } /** @brief Reshapes the tensor * * * (1) @code A.reshape(extents{m,n,o}); @endcode or * (2) @code A.reshape(extents{m,n,o},4); @endcode * * If the size of this smaller than the specified extents than * default constructed (1) or specified (2) value is appended. * * @note rank of the tensor might also change. * * @param e extents with which the tensor is reshaped. * @param v value which is appended if the tensor is enlarged. */ BOOST_UBLAS_INLINE void reshape (extents_type const& e, value_type v = value_type{}) { this->extents_ = e; this->strides_ = strides_type(this->extents_); if(e.product() != this->size()) this->data_.resize (this->extents_.product(), v); } friend void swap(tensor& lhs, tensor& rhs) { std::swap(lhs.data_ , rhs.data_ ); std::swap(lhs.extents_, rhs.extents_); std::swap(lhs.strides_, rhs.strides_); } /// \brief return an iterator on the first element of the tensor BOOST_UBLAS_INLINE const_iterator begin () const { return data_.begin (); } /// \brief return an iterator on the first element of the tensor BOOST_UBLAS_INLINE const_iterator cbegin () const { return data_.cbegin (); } /// \brief return an iterator after the last element of the tensor BOOST_UBLAS_INLINE const_iterator end () const { return data_.end(); } /// \brief return an iterator after the last element of the tensor BOOST_UBLAS_INLINE const_iterator cend () const { return data_.cend (); } /// \brief Return an iterator on the first element of the tensor BOOST_UBLAS_INLINE iterator begin () { return data_.begin(); } /// \brief Return an iterator at the end of the tensor BOOST_UBLAS_INLINE iterator end () { return data_.end(); } /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor) BOOST_UBLAS_INLINE const_reverse_iterator rbegin () const { return data_.rbegin(); } /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor) BOOST_UBLAS_INLINE const_reverse_iterator crbegin () const { return data_.crbegin(); } /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor) BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return data_.rend(); } /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor) BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return data_.crend(); } /// \brief Return a const reverse iterator before the first element of the reversed tensor (i.e. end() of normal tensor) BOOST_UBLAS_INLINE reverse_iterator rbegin () { return data_.rbegin(); } /// \brief Return a const reverse iterator on the end of the reverse tensor (i.e. first element of the normal tensor) BOOST_UBLAS_INLINE reverse_iterator rend () { return data_.rend(); } #if 0 // ------------- // Serialization // ------------- /// Serialize a tensor 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_); } #endif private: extents_type extents_; strides_type strides_; array_type data_; }; }}} // namespaces #endif ublas/tensor/operators_arithmetic.hpp 0000644 00000023572 15125237305 0014140 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP #define BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP #include "expression.hpp" #include "expression_evaluation.hpp" #include "multi_index_utility.hpp" #include "functions.hpp" #include <type_traits> #include <functional> #include <algorithm> namespace boost{ namespace numeric{ namespace ublas { template<class element_type, class storage_format, class storage_type> class tensor; template<class E> class matrix_expression; template<class E> class vector_expression; } } } #define FIRST_ORDER_OPERATOR_RIGHT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \ template<class T, class L, class R> \ auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <T,L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <R> const& rhs) { \ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \ [](auto const& l, auto const& r){ return l OP r; }); \ } \ FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , vector_expression) FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , vector_expression) FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , vector_expression) FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , vector_expression) FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , matrix_expression) FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , matrix_expression) FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , matrix_expression) FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , matrix_expression) #define FIRST_ORDER_OPERATOR_LEFT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \ template<class T, class L, class R> \ auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <T,R> const& rhs) { \ return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \ [](auto const& l, auto const& r){ return l OP r; }); \ } \ FIRST_ORDER_OPERATOR_LEFT (*, vector_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (+, vector_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (-, vector_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (/, vector_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (*, matrix_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (+, matrix_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (-, matrix_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (/, matrix_expression, detail:: tensor_expression) template<class T, class L, class R> auto operator+( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l + r; }); } template<class T, class L, class R> auto operator-( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l - r; }); // return boost::numeric::ublas::detail::make_lambda<T>([&lhs,&rhs](std::size_t i){ return lhs(i) - rhs(i);}); } template<class T, class L, class R> auto operator*( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l * r; }); } template<class T, class L, class R> auto operator/( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l / r; }); } // Overloaded Arithmetic Operators with Scalars template<class T, class R> auto operator+(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs + r; }); //return boost::numeric::ublas::detail::make_lambda<T>( [&lhs,&rhs](std::size_t i) {return lhs + rhs(i); } ); } template<class T, class R> auto operator-(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs - r; }); } template<class T, class R> auto operator*(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs * r; }); } template<class T, class R> auto operator/(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs / r; }); } template<class T, class L> auto operator+(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l + rhs; } ); } template<class T, class L> auto operator-(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l - rhs; } ); } template<class T, class L> auto operator*(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l * rhs; } ); } template<class T, class L> auto operator/(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l / rhs; } ); } template<class T, class D> auto& operator += (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) { boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l+=r; } ); return lhs; } template<class T, class D> auto& operator -= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) { boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l-=r; } ); return lhs; } template<class T, class D> auto& operator *= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) { boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l*=r; } ); return lhs; } template<class T, class D> auto& operator /= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) { boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l/=r; } ); return lhs; } template<class E, class F, class A> auto& operator += (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) { boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l+=r; } ); return lhs; } template<class E, class F, class A> auto& operator -= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) { boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l-=r; } ); return lhs; } template<class E, class F, class A> auto& operator *= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) { boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l*=r; } ); return lhs; } template<class E, class F, class A> auto& operator /= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) { boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l/=r; } ); return lhs; } template<class T, class D> auto const& operator +(const boost::numeric::ublas::detail::tensor_expression<T,D>& lhs) { return lhs; } template<class T, class D> auto operator -(boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs) { return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [] (auto const& l) { return -l; } ); } /** @brief Performs a tensor contraction, not an elementwise multiplication * */ template<class tensor_type_left, class tuple_type_left, class tensor_type_right, class tuple_type_right> auto operator*( std::pair< tensor_type_left const&, tuple_type_left > lhs, std::pair< tensor_type_right const&, tuple_type_right > rhs) { using namespace boost::numeric::ublas; auto const& tensor_left = lhs.first; auto const& tensor_right = rhs.first; auto multi_index_left = lhs.second; auto multi_index_right = rhs.second; static constexpr auto num_equal_ind = number_equal_indexes<tuple_type_left, tuple_type_right>::value; if constexpr ( num_equal_ind == 0 ){ return tensor_left * tensor_right; } else if constexpr ( num_equal_ind==std::tuple_size<tuple_type_left>::value && std::is_same<tuple_type_left, tuple_type_right>::value ){ return boost::numeric::ublas::inner_prod( tensor_left, tensor_right ); } else { auto array_index_pairs = index_position_pairs(multi_index_left,multi_index_right); auto index_pairs = array_to_vector( array_index_pairs ); return boost::numeric::ublas::prod( tensor_left, tensor_right, index_pairs.first, index_pairs.second ); } } #endif ublas/tensor/operators_comparison.hpp 0000644 00000016066 15125237305 0014161 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP #define BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP #include <boost/numeric/ublas/tensor/expression.hpp> #include <boost/numeric/ublas/tensor/expression_evaluation.hpp> #include <type_traits> #include <functional> namespace boost::numeric::ublas { template<class element_type, class storage_format, class storage_type> class tensor; } namespace boost::numeric::ublas::detail { template<class T, class F, class A, class BinaryPred> bool compare(tensor<T,F,A> const& lhs, tensor<T,F,A> const& rhs, BinaryPred pred) { if(lhs.extents() != rhs.extents()){ if constexpr(!std::is_same<BinaryPred,std::equal_to<>>::value && !std::is_same<BinaryPred,std::not_equal_to<>>::value) throw std::runtime_error("Error in boost::numeric::ublas::detail::compare: cannot compare tensors with different shapes."); else return false; } if constexpr(std::is_same<BinaryPred,std::greater<>>::value || std::is_same<BinaryPred,std::less<>>::value) if(lhs.empty()) return false; for(auto i = 0u; i < lhs.size(); ++i) if(!pred(lhs(i), rhs(i))) return false; return true; } template<class T, class F, class A, class UnaryPred> bool compare(tensor<T,F,A> const& rhs, UnaryPred pred) { for(auto i = 0u; i < rhs.size(); ++i) if(!pred(rhs(i))) return false; return true; } template<class T, class L, class R, class BinaryPred> bool compare(tensor_expression<T,L> const& lhs, tensor_expression<T,R> const& rhs, BinaryPred pred) { constexpr bool lhs_is_tensor = std::is_same<T,L>::value; constexpr bool rhs_is_tensor = std::is_same<T,R>::value; if constexpr (lhs_is_tensor && rhs_is_tensor) return compare(static_cast<T const&>( lhs ), static_cast<T const&>( rhs ), pred); else if constexpr (lhs_is_tensor && !rhs_is_tensor) return compare(static_cast<T const&>( lhs ), T( rhs ), pred); else if constexpr (!lhs_is_tensor && rhs_is_tensor) return compare(T( lhs ), static_cast<T const&>( rhs ), pred); else return compare(T( lhs ), T( rhs ), pred); } template<class T, class D, class UnaryPred> bool compare(tensor_expression<T,D> const& expr, UnaryPred pred) { if constexpr (std::is_same<T,D>::value) return compare(static_cast<T const&>( expr ), pred); else return compare(T( expr ), pred); } } template<class T, class L, class R> bool operator==( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::equal_to<>{} ); } template<class T, class L, class R> auto operator!=(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::not_equal_to<>{} ); } template<class T, class L, class R> auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::less<>{} ); } template<class T, class L, class R> auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::less_equal<>{} ); } template<class T, class L, class R> auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater<>{} ); } template<class T, class L, class R> auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) { return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater_equal<>{} ); } template<class T, class D> bool operator==( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs == r; } ); } template<class T, class D> auto operator!=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs != r; } ); } template<class T, class D> auto operator< ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs < r; } ); } template<class T, class D> auto operator<=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs <= r; } ); } template<class T, class D> auto operator> ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs > r; } ); } template<class T, class D> auto operator>=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) { return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs >= r; } ); } template<class T, class D> bool operator==( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l == rhs; } ); } template<class T, class D> auto operator!=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l != rhs; } ); } template<class T, class D> auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l < rhs; } ); } template<class T, class D> auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l <= rhs; } ); } template<class T, class D> auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l > rhs; } ); } template<class T, class D> auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) { return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l >= rhs; } ); } #endif ublas/tensor/extents.hpp 0000644 00000017057 15125237305 0011404 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_NUMERIC_UBLAS_TENSOR_EXTENTS_HPP #define BOOST_NUMERIC_UBLAS_TENSOR_EXTENTS_HPP #include <algorithm> #include <initializer_list> #include <limits> #include <numeric> #include <stdexcept> #include <vector> #include <cassert> namespace boost { namespace numeric { namespace ublas { /** @brief Template class for storing tensor extents with runtime variable size. * * Proxy template class of std::vector<int_type>. * */ template<class int_type> class basic_extents { static_assert( std::numeric_limits<typename std::vector<int_type>::value_type>::is_integer, "Static error in basic_layout: type must be of type integer."); static_assert(!std::numeric_limits<typename std::vector<int_type>::value_type>::is_signed, "Static error in basic_layout: type must be of type unsigned integer."); public: using base_type = std::vector<int_type>; using value_type = typename base_type::value_type; using const_reference = typename base_type::const_reference; using reference = typename base_type::reference; using size_type = typename base_type::size_type; using const_pointer = typename base_type::const_pointer; using const_iterator = typename base_type::const_iterator; /** @brief Default constructs basic_extents * * @code auto ex = basic_extents<unsigned>{}; */ constexpr explicit basic_extents() : _base{} { } /** @brief Copy constructs basic_extents from a one-dimensional container * * @code auto ex = basic_extents<unsigned>( std::vector<unsigned>(3u,3u) ); * * @note checks if size > 1 and all elements > 0 * * @param b one-dimensional std::vector<int_type> container */ explicit basic_extents(base_type const& b) : _base(b) { if (!this->valid()){ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements."); } } /** @brief Move constructs basic_extents from a one-dimensional container * * @code auto ex = basic_extents<unsigned>( std::vector<unsigned>(3u,3u) ); * * @note checks if size > 1 and all elements > 0 * * @param b one-dimensional container of type std::vector<int_type> */ explicit basic_extents(base_type && b) : _base(std::move(b)) { if (!this->valid()){ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements."); } } /** @brief Constructs basic_extents from an initializer list * * @code auto ex = basic_extents<unsigned>{3,2,4}; * * @note checks if size > 1 and all elements > 0 * * @param l one-dimensional list of type std::initializer<int_type> */ basic_extents(std::initializer_list<value_type> l) : basic_extents( base_type(std::move(l)) ) { } /** @brief Constructs basic_extents from a range specified by two iterators * * @code auto ex = basic_extents<unsigned>(a.begin(), a.end()); * * @note checks if size > 1 and all elements > 0 * * @param first iterator pointing to the first element * @param last iterator pointing to the next position after the last element */ basic_extents(const_iterator first, const_iterator last) : basic_extents ( base_type( first,last ) ) { } /** @brief Copy constructs basic_extents */ basic_extents(basic_extents const& l ) : _base(l._base) { } /** @brief Move constructs basic_extents */ basic_extents(basic_extents && l ) noexcept : _base(std::move(l._base)) { } ~basic_extents() = default; basic_extents& operator=(basic_extents other) noexcept { swap (*this, other); return *this; } friend void swap(basic_extents& lhs, basic_extents& rhs) { std::swap(lhs._base , rhs._base ); } /** @brief Returns true if this has a scalar shape * * @returns true if (1,1,[1,...,1]) */ bool is_scalar() const { return _base.size() != 0 && std::all_of(_base.begin(), _base.end(), [](const_reference a){ return a == 1;}); } /** @brief Returns true if this has a vector shape * * @returns true if (1,n,[1,...,1]) or (n,1,[1,...,1]) with n > 1 */ bool is_vector() const { if(_base.size() == 0){ return false; } if(_base.size() == 1){ return _base.at(0) > 1; } auto greater_one = [](const_reference a){ return a > 1;}; auto equal_one = [](const_reference a){ return a == 1;}; return std::any_of(_base.begin(), _base.begin()+2, greater_one) && std::any_of(_base.begin(), _base.begin()+2, equal_one ) && std::all_of(_base.begin()+2, _base.end(), equal_one); } /** @brief Returns true if this has a matrix shape * * @returns true if (m,n,[1,...,1]) with m > 1 and n > 1 */ bool is_matrix() const { if(_base.size() < 2){ return false; } auto greater_one = [](const_reference a){ return a > 1;}; auto equal_one = [](const_reference a){ return a == 1;}; return std::all_of(_base.begin(), _base.begin()+2, greater_one) && std::all_of(_base.begin()+2, _base.end(), equal_one ); } /** @brief Returns true if this is has a tensor shape * * @returns true if !empty() && !is_scalar() && !is_vector() && !is_matrix() */ bool is_tensor() const { if(_base.size() < 3){ return false; } auto greater_one = [](const_reference a){ return a > 1;}; return std::any_of(_base.begin()+2, _base.end(), greater_one); } const_pointer data() const { return this->_base.data(); } const_reference operator[] (size_type p) const { return this->_base[p]; } const_reference at (size_type p) const { return this->_base.at(p); } reference operator[] (size_type p) { return this->_base[p]; } reference at (size_type p) { return this->_base.at(p); } bool empty() const { return this->_base.empty(); } size_type size() const { return this->_base.size(); } /** @brief Returns true if size > 1 and all elements > 0 */ bool valid() const { return this->size() > 1 && std::none_of(_base.begin(), _base.end(), [](const_reference a){ return a == value_type(0); }); } /** @brief Returns the number of elements a tensor holds with this */ size_type product() const { if(_base.empty()){ return 0; } return std::accumulate(_base.begin(), _base.end(), 1ul, std::multiplies<>()); } /** @brief Eliminates singleton dimensions when size > 2 * * squeeze { 1,1} -> { 1,1} * squeeze { 2,1} -> { 2,1} * squeeze { 1,2} -> { 1,2} * * squeeze {1,2,3} -> { 2,3} * squeeze {2,1,3} -> { 2,3} * squeeze {1,3,1} -> { 3,1} * */ basic_extents squeeze() const { if(this->size() <= 2){ return *this; } auto new_extent = basic_extents{}; auto insert_iter = std::back_insert_iterator<typename basic_extents::base_type>(new_extent._base); std::remove_copy(this->_base.begin(), this->_base.end(), insert_iter ,value_type{1}); return new_extent; } void clear() { this->_base.clear(); } bool operator == (basic_extents const& b) const { return _base == b._base; } bool operator != (basic_extents const& b) const { return !( _base == b._base ); } const_iterator begin() const { return _base.begin(); } const_iterator end() const { return _base.end(); } base_type const& base() const { return _base; } private: base_type _base; }; using shape = basic_extents<std::size_t>; } // namespace ublas } // namespace numeric } // namespace boost #endif ublas/tensor/functions.hpp 0000644 00000041546 15125237305 0011722 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_FUNCTIONS_HPP #define BOOST_UBLAS_TENSOR_FUNCTIONS_HPP #include <stdexcept> #include <vector> #include <algorithm> #include <numeric> #include "multiplication.hpp" #include "algorithms.hpp" #include "expression.hpp" #include "expression_evaluation.hpp" #include "storage_traits.hpp" namespace boost { namespace numeric { namespace ublas { template<class Value, class Format, class Allocator> class tensor; template<class Value, class Format, class Allocator> class matrix; template<class Value, class Allocator> class vector; /** @brief Computes the m-mode tensor-times-vector product * * Implements C[i1,...,im-1,im+1,...,ip] = A[i1,i2,...,ip] * b[im] * * @note calls ublas::ttv * * @param[in] m contraction dimension with 1 <= m <= p * @param[in] a tensor object A with order p * @param[in] b vector object B * * @returns tensor object C with order p-1, the same storage format and allocator type as A */ template<class V, class F, class A1, class A2> auto prod(tensor<V,F,A1> const& a, vector<V,A2> const& b, const std::size_t m) { using tensor_type = tensor<V,F,A1>; using extents_type = typename tensor_type::extents_type; using ebase_type = typename extents_type::base_type; using value_type = typename tensor_type::value_type; using size_type = typename extents_type::value_type; auto const p = std::size_t(a.rank()); if( m == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttv): contraction mode must be greater than zero."); if( p < m ) throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than or equal to the modus."); if( p == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than zero."); if( a.empty() ) throw std::length_error("error in boost::numeric::ublas::prod(ttv): first argument tensor should not be empty."); if( b.size() == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttv): second argument vector should not be empty."); auto nc = ebase_type(std::max(p-1, size_type(2)) , size_type(1)); auto nb = ebase_type{b.size(),1}; for(auto i = 0u, j = 0u; i < p; ++i) if(i != m-1) nc[j++] = a.extents().at(i); auto c = tensor_type(extents_type(nc),value_type{}); auto bb = &(b(0)); ttv(m, p, c.data(), c.extents().data(), c.strides().data(), a.data(), a.extents().data(), a.strides().data(), bb, nb.data(), nb.data()); return c; } /** @brief Computes the m-mode tensor-times-matrix product * * Implements C[i1,...,im-1,j,im+1,...,ip] = A[i1,i2,...,ip] * B[j,im] * * @note calls ublas::ttm * * @param[in] a tensor object A with order p * @param[in] b vector object B * @param[in] m contraction dimension with 1 <= m <= p * * @returns tensor object C with order p, the same storage format and allocator type as A */ template<class V, class F, class A1, class A2> auto prod(tensor<V,F,A1> const& a, matrix<V,F,A2> const& b, const std::size_t m) { using tensor_type = tensor<V,F,A1>; using extents_type = typename tensor_type::extents_type; using strides_type = typename tensor_type::strides_type; using value_type = typename tensor_type::value_type; auto const p = a.rank(); if( m == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttm): contraction mode must be greater than zero."); if( p < m || m > a.extents().size()) throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater equal the modus."); if( p == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater than zero."); if( a.empty() ) throw std::length_error("error in boost::numeric::ublas::prod(ttm): first argument tensor should not be empty."); if( b.size1()*b.size2() == 0) throw std::length_error("error in boost::numeric::ublas::prod(ttm): second argument matrix should not be empty."); auto nc = a.extents().base(); auto nb = extents_type {b.size1(),b.size2()}; auto wb = strides_type (nb); nc[m-1] = nb[0]; auto c = tensor_type(extents_type(nc),value_type{}); auto bb = &(b(0,0)); ttm(m, p, c.data(), c.extents().data(), c.strides().data(), a.data(), a.extents().data(), a.strides().data(), bb, nb.data(), wb.data()); return c; } /** @brief Computes the q-mode tensor-times-tensor product * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * @note calls ublas::ttt * * na[phia[x]] = nb[phib[x]] for 1 <= x <= q * * @param[in] phia one-based permutation tuple of length q for the first input tensor a * @param[in] phib one-based permutation tuple of length q for the second input tensor b * @param[in] a left-hand side tensor with order r+q * @param[in] b right-hand side tensor with order s+q * @result tensor with order r+s */ template<class V, class F, class A1, class A2> auto prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b, std::vector<std::size_t> const& phia, std::vector<std::size_t> const& phib) { using tensor_type = tensor<V,F,A1>; using extents_type = typename tensor_type::extents_type; using value_type = typename tensor_type::value_type; using size_type = typename extents_type::value_type; auto const pa = a.rank(); auto const pb = b.rank(); auto const q = size_type(phia.size()); if(pa == 0ul) throw std::runtime_error("error in ublas::prod: order of left-hand side tensor must be greater than 0."); if(pb == 0ul) throw std::runtime_error("error in ublas::prod: order of right-hand side tensor must be greater than 0."); if(pa < q) throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the left-hand side tensor."); if(pb < q) throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the right-hand side tensor."); if(q != phib.size()) throw std::runtime_error("error in ublas::prod: permutation tuples must have the same length."); if(pa < phia.size()) throw std::runtime_error("error in ublas::prod: permutation tuple for the left-hand side tensor cannot be greater than the corresponding order."); if(pb < phib.size()) throw std::runtime_error("error in ublas::prod: permutation tuple for the right-hand side tensor cannot be greater than the corresponding order."); auto const& na = a.extents(); auto const& nb = b.extents(); for(auto i = 0ul; i < q; ++i) if( na.at(phia.at(i)-1) != nb.at(phib.at(i)-1)) throw std::runtime_error("error in ublas::prod: permutations of the extents are not correct."); auto const r = pa - q; auto const s = pb - q; std::vector<std::size_t> phia1(pa), phib1(pb); std::iota(phia1.begin(), phia1.end(), 1ul); std::iota(phib1.begin(), phib1.end(), 1ul); std::vector<std::size_t> nc( std::max ( r+s , size_type(2) ), size_type(1) ); for(auto i = 0ul; i < phia.size(); ++i) * std::remove(phia1.begin(), phia1.end(), phia.at(i)) = phia.at(i); //phia1.erase( std::remove(phia1.begin(), phia1.end(), phia.at(i)), phia1.end() ) ; assert(phia1.size() == pa); for(auto i = 0ul; i < r; ++i) nc[ i ] = na[ phia1[ i ] - 1 ]; for(auto i = 0ul; i < phib.size(); ++i) * std::remove(phib1.begin(), phib1.end(), phib.at(i)) = phib.at(i) ; //phib1.erase( std::remove(phib1.begin(), phib1.end(), phia.at(i)), phib1.end() ) ; assert(phib1.size() == pb); for(auto i = 0ul; i < s; ++i) nc[ r + i ] = nb[ phib1[ i ] - 1 ]; // std::copy( phib.begin(), phib.end(), phib1.end() ); assert( phia1.size() == pa ); assert( phib1.size() == pb ); auto c = tensor_type(extents_type(nc), value_type{}); ttt(pa, pb, q, phia1.data(), phib1.data(), c.data(), c.extents().data(), c.strides().data(), a.data(), a.extents().data(), a.strides().data(), b.data(), b.extents().data(), b.strides().data()); return c; } //template<class V, class F, class A1, class A2, std::size_t N, std::size_t M> //auto operator*( tensor_index<V,F,A1,N> const& lhs, tensor_index<V,F,A2,M> const& rhs) /** @brief Computes the q-mode tensor-times-tensor product * * Implements C[i1,...,ir,j1,...,js] = sum( A[i1,...,ir+q] * B[j1,...,js+q] ) * * @note calls ublas::ttt * * na[phi[x]] = nb[phi[x]] for 1 <= x <= q * * @param[in] phi one-based permutation tuple of length q for bot input tensors * @param[in] a left-hand side tensor with order r+q * @param[in] b right-hand side tensor with order s+q * @result tensor with order r+s */ template<class V, class F, class A1, class A2> auto prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b, std::vector<std::size_t> const& phi) { return prod(a, b, phi, phi); } /** @brief Computes the inner product of two tensors * * Implements c = sum(A[i1,i2,...,ip] * B[i1,i2,...,jp]) * * @note calls inner function * * @param[in] a tensor object A * @param[in] b tensor object B * * @returns a value type. */ template<class V, class F, class A1, class A2> auto inner_prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b) { using value_type = typename tensor<V,F,A1>::value_type; if( a.rank() != b.rank() ) throw std::length_error("error in boost::numeric::ublas::inner_prod: Rank of both tensors must be the same."); if( a.empty() || b.empty()) throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensors should not be empty."); if( a.extents() != b.extents()) throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensor extents should be the same."); return inner(a.rank(), a.extents().data(), a.data(), a.strides().data(), b.data(), b.strides().data(), value_type{0}); } /** @brief Computes the outer product of two tensors * * Implements C[i1,...,ip,j1,...,jq] = A[i1,i2,...,ip] * B[j1,j2,...,jq] * * @note calls outer function * * @param[in] a tensor object A * @param[in] b tensor object B * * @returns tensor object C with the same storage format F and allocator type A1 */ template<class V, class F, class A1, class A2> auto outer_prod(tensor<V,F,A1> const& a, tensor<V,F,A2> const& b) { using tensor_type = tensor<V,F,A1>; using extents_type = typename tensor_type::extents_type; if( a.empty() || b.empty() ) throw std::runtime_error("error in boost::numeric::ublas::outer_prod: tensors should not be empty."); auto nc = typename extents_type::base_type(a.rank() + b.rank()); for(auto i = 0u; i < a.rank(); ++i) nc.at(i) = a.extents().at(i); for(auto i = 0u; i < b.rank(); ++i) nc.at(a.rank()+i) = b.extents().at(i); auto c = tensor_type(extents_type(nc)); outer(c.data(), c.rank(), c.extents().data(), c.strides().data(), a.data(), a.rank(), a.extents().data(), a.strides().data(), b.data(), b.rank(), b.extents().data(), b.strides().data()); return c; } /** @brief Transposes a tensor according to a permutation tuple * * Implements C[tau[i1],tau[i2]...,tau[ip]] = A[i1,i2,...,ip] * * @note calls trans function * * @param[in] a tensor object of rank p * @param[in] tau one-based permutation tuple of length p * @returns a transposed tensor object with the same storage format F and allocator type A */ template<class V, class F, class A> auto trans(tensor<V,F,A> const& a, std::vector<std::size_t> const& tau) { using tensor_type = tensor<V,F,A>; using extents_type = typename tensor_type::extents_type; // using strides_type = typename tensor_type::strides_type; if( a.empty() ) return tensor<V,F,A>{}; auto const p = a.rank(); auto const& na = a.extents(); auto nc = typename extents_type::base_type (p); for(auto i = 0u; i < p; ++i) nc.at(tau.at(i)-1) = na.at(i); // auto wc = strides_type(extents_type(nc)); auto c = tensor_type(extents_type(nc)); trans( a.rank(), a.extents().data(), tau.data(), c.data(), c.strides().data(), a.data(), a.strides().data()); // auto wc_pi = typename strides_type::base_type (p); // for(auto i = 0u; i < p; ++i) // wc_pi.at(tau.at(i)-1) = c.strides().at(i); //copy(a.rank(), // a.extents().data(), // c.data(), wc_pi.data(), // a.data(), a.strides().data() ); return c; } /** @brief Computes the frobenius norm of a tensor expression * * @note evaluates the tensor expression and calls the accumulate function * * * Implements the two-norm with * k = sqrt( sum_(i1,...,ip) A(i1,...,ip)^2 ) * * @param[in] a tensor object of rank p * @returns the frobenius norm of the tensor */ //template<class V, class F, class A> //auto norm(tensor<V,F,A> const& a) template<class T, class D> auto norm(detail::tensor_expression<T,D> const& expr) { using tensor_type = typename detail::tensor_expression<T,D>::tensor_type; using value_type = typename tensor_type::value_type; auto a = tensor_type( expr ); if( a.empty() ) throw std::runtime_error("error in boost::numeric::ublas::norm: tensors should not be empty."); return std::sqrt( accumulate( a.order(), a.extents().data(), a.data(), a.strides().data(), value_type{}, [](auto const& l, auto const& r){ return l + r*r; } ) ) ; } /** @brief Extract the real component of tensor elements within a tensor expression * * @param[in] lhs tensor expression * @returns unary tensor expression */ template<class T, class D> auto real(detail::tensor_expression<T,D> const& expr) { return detail::make_unary_tensor_expression<T> (expr(), [] (auto const& l) { return std::real( l ); } ); } /** @brief Extract the real component of tensor elements within a tensor expression * * @param[in] lhs tensor expression * @returns unary tensor expression */ template<class V, class F, class A, class D> auto real(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr) { using tensor_complex_type = tensor<std::complex<V>,F,A>; using tensor_type = tensor<V,F,typename storage_traits<A>::template rebind<V>>; if( detail::retrieve_extents( expr ).empty() ) throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty."); auto a = tensor_complex_type( expr ); auto c = tensor_type( a.extents() ); std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::real(l) ; } ); return c; } /** @brief Extract the imaginary component of tensor elements within a tensor expression * * @param[in] lhs tensor expression * @returns unary tensor expression */ template<class T, class D> auto imag(detail::tensor_expression<T,D> const& lhs) { return detail::make_unary_tensor_expression<T> (lhs(), [] (auto const& l) { return std::imag( l ); } ); } /** @brief Extract the imag component of tensor elements within a tensor expression * * @param[in] lhs tensor expression * @returns unary tensor expression */ template<class V, class A, class F, class D> auto imag(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr) { using tensor_complex_type = tensor<std::complex<V>,F,A>; using tensor_type = tensor<V,F,typename storage_traits<A>::template rebind<V>>; if( detail::retrieve_extents( expr ).empty() ) throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty."); auto a = tensor_complex_type( expr ); auto c = tensor_type( a.extents() ); std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::imag(l) ; } ); return c; } /** @brief Computes the complex conjugate component of tensor elements within a tensor expression * * @param[in] expr tensor expression * @returns complex tensor */ template<class T, class D> auto conj(detail::tensor_expression<T,D> const& expr) { using tensor_type = T; using value_type = typename tensor_type::value_type; using layout_type = typename tensor_type::layout_type; using array_type = typename tensor_type::array_type; using new_value_type = std::complex<value_type>; using new_array_type = typename storage_traits<array_type>::template rebind<new_value_type>; using tensor_complex_type = tensor<new_value_type,layout_type, new_array_type>; if( detail::retrieve_extents( expr ).empty() ) throw std::runtime_error("error in boost::numeric::ublas::conj: tensors should not be empty."); auto a = tensor_type( expr ); auto c = tensor_complex_type( a.extents() ); std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::conj(l) ; } ); return c; } /** @brief Computes the complex conjugate component of tensor elements within a tensor expression * * @param[in] lhs tensor expression * @returns unary tensor expression */ template<class V, class A, class F, class D> auto conj(detail::tensor_expression<tensor<std::complex<V>,F,A>,D> const& expr) { return detail::make_unary_tensor_expression<tensor<std::complex<V>,F,A>> (expr(), [] (auto const& l) { return std::conj( l ); } ); } } } } #endif ublas/tensor/multi_index.hpp 0000644 00000005146 15125237305 0012227 0 ustar 00 // // Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // 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 // Fraunhofer IOSB, Ettlingen, Germany // #ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP #define BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP #include <cstddef> #include <array> #include <vector> #include "multi_index_utility.hpp" namespace boost { namespace numeric { namespace ublas { namespace index { template<std::size_t I> struct index_type; } // namespace indices } } } namespace boost { namespace numeric { namespace ublas { /** @brief Proxy class for the einstein summation notation * * Denotes an array of index_type types ::_a for 0<=K<=16 is used in tensor::operator() */ template<std::size_t N> class multi_index { public: multi_index() = delete; template<std::size_t I, class ... indexes> constexpr multi_index(index::index_type<I> const& i, indexes ... is ) : _base{i(), is()... } { static_assert( sizeof...(is)+1 == N, "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." ); static_assert( valid_multi_index<std::tuple<index::index_type<I>, indexes ...> >::value, "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." ); } multi_index(multi_index const& other) : _base(other._base) { } multi_index& operator=(multi_index const& other) { this->_base = other._base; return *this; } ~multi_index() = default; auto const& base() const { return _base; } constexpr auto size() const { return _base.size(); } constexpr auto at(std::size_t i) const { return _base.at(i); } constexpr auto operator[](std::size_t i) const { return _base.at(i); } private: std::array<std::size_t, N> _base; }; template<std::size_t K, std::size_t N> constexpr auto get(multi_index<N> const& m) { return std::get<K>(m.base()); } template<std::size_t M, std::size_t N> auto array_to_vector(multi_index<M> const& lhs, multi_index<N> const& rhs) { using vtype = std::vector<std::size_t>; auto pair_of_vector = std::make_pair( vtype {}, vtype{} ); for(auto i = 0u; i < N; ++i) for(auto j = 0u; j < M; ++j) if ( lhs.at(i) == rhs.at(j) && lhs.at(i) != boost::numeric::ublas::index::_()) pair_of_vector.first .push_back( i+1 ), pair_of_vector.second.push_back( j+1 ); return pair_of_vector; } } // namespace ublas } // namespace numeric } // namespace boost #endif // MULTI_INDEX_HPP ublas/storage_sparse.hpp 0000644 00000046540 15125237305 0011420 0 ustar 00 // // 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 template<class I, class T, class ALLOC> class map_std : public std::map<I, T, std::less<I>, 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, std::less<I>, 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return data_ + size_; } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 ublas/storage.hpp 0000644 00000204312 15125237305 0010034 0 ustar 00 // // 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/core/allocator_access.hpp> #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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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_); //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (! detail::has_trivial_constructor<T>::value) { #ifdef _MSC_VER #pragma warning(pop) #endif for (pointer d = data_; d != data_ + size_; ++d) boost::allocator_construct(alloc_, d); } } 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; } #ifdef BOOST_UBLAS_CPP_GE_2011 BOOST_UBLAS_INLINE unbounded_array (unbounded_array &&c) : storage_array<unbounded_array<T, ALLOC> >(), alloc_ (std::move(c.alloc_)), size_ (c.size_), data_(c.data_) { c.size_ = 0; c.data_ = nullptr; } #endif BOOST_UBLAS_INLINE ~unbounded_array () { if (size_) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (! detail::has_trivial_destructor<T>::value) { #ifdef _MSC_VER #pragma warning(pop) #endif // 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) { boost::allocator_construct(alloc_, di, *si); ++si; } } else { for (; si != p_data + size_; ++si) { boost::allocator_construct(alloc_, di, *si); ++di; } for (; di != data_ + size; ++di) { boost::allocator_construct(alloc_, di, init); } } } else { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (! detail::has_trivial_constructor<T>::value) { #ifdef _MSC_VER #pragma warning(pop) #endif for (pointer di = data_; di != data_ + size; ++di) boost::allocator_construct(alloc_, di); } } } if (size_) { //Disabled warning C4127 because the conditional expression is constant #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (! detail::has_trivial_destructor<T>::value) { #ifdef _MSC_VER #pragma warning(pop) #endif for (pointer si = p_data; si != p_data + size_; ++si) boost::allocator_destroy(alloc_, 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 boost::allocator_max_size(alloc_); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return data_ + size_; } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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) { (void)(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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 N; } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return data_ + size_; } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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_; // MSVC does not like arrays of size 0 in base classes. Hence, this conditionally changes the size to 1 #ifdef _MSC_VER BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [(N>0)?N:1]; #else BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N]; #endif }; // 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) {} template <size_t N> BOOST_UBLAS_INLINE array_adaptor (T (&data)[N]): size_ (N), 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); } template <size_t N> BOOST_UBLAS_INLINE void resize (T (&data)[N]) { resize_internal (N, data, value_type (), false); } template <size_t N> BOOST_UBLAS_INLINE void resize (T (&data)[N], value_type init) { resize_internal (N, 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return data_ + size_; } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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> ()) {} template <size_t N> BOOST_UBLAS_INLINE shallow_array_adaptor (T (&data)[N]): size_ (N), 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; own_ = true; 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; own_ = false; data_.reset(data, leaker<value_type> ()); } 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); } template <size_t N> BOOST_UBLAS_INLINE void resize (T (&data)[N]) { resize_internal (N, data, value_type (), false); } template <size_t N> BOOST_UBLAS_INLINE void resize (T (&data)[N], value_type init) { resize_internal (N, 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return data_.get () + size_; } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this, start_ + size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this, size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end () const { return const_iterator (*this, size_); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE const_reverse_iterator crend () const { return rend (); } 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 : 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); } friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator( (*this), size()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 : 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); } friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 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 cbegin () const { return begin (); } BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator( (*this), size()); } BOOST_UBLAS_INLINE const_iterator cend () const { return end (); } // 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 ublas/matrix.hpp 0000644 00000646174 15125237305 0007714 0 ustar 00 // // Copyright (c) 2000-2010 // Joerg Walter, Mathias Koch, Gunter Winkler, David Bellot // Copyright (c) 2014, Athanasios Iliopoulos // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // 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/config.hpp> #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 /** Access a matrix element. Here we return a const reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a const reference to the element */ BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { return data () [layout_type::element (i, size1_, j, size2_)]; } /** Access a matrix element. Here we return a reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a reference to the element */ BOOST_UBLAS_INLINE reference at_element (size_type i, size_type j) { return data () [layout_type::element (i, size1_, j, size2_)]; } /** Access a matrix element. Here we return a reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a reference to the element */ BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { return at_element (i, j); } /** Access a matrix element. Here we return a reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a reference to the element */ BOOST_UBLAS_INLINE reference operator () (size_type i) { return data()[i]; } BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { return data()[i]; } // /** Access a matrix element. Here we return a reference // * \param i the first coordinate of the element. By default it's the row // * \param j the second coordinate of the element. By default it's the column // * \return a reference to the element // */ // BOOST_UBLAS_INLINE // const_reference operator () const (size_type i) { // return data()[i]; // } // Element assignment /** Change the value of a matrix element. Return back a reference to it * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \param t the new value of the element * \return a reference to the newly changed element */ BOOST_UBLAS_INLINE reference insert_element (size_type i, size_type j, const_reference t) { return (at_element (i, j) = t); } /** Erase the element * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact. * For user-defined types, it could be another value if you decided it. Your type in that case must * contain a default null value. * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column */ void erase_element (size_type i, size_type j) { at_element (i, j) = value_type/*zero*/(); } // Zeroing /** Erase all elements in the matrix * For most types (int, double, etc...) it means writing 0 (zero) everywhere. * For user-defined types, it could be another value if you decided it. Your type in that case must * contain a default null value. */ 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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_; }; #ifdef BOOST_UBLAS_CPP_GE_2011 /** \brief A fixed size dense matrix of values of type \c T. Equivalent to a c-style 2 dimensional array. * * For a \f$(m \times n)\f$-dimensional fixed_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 \c row_major and \c std::array are used. It is \b not * required by the storage container to initialize elements of the matrix. * * \tparam T the type of object stored in the matrix (like double, float, std::complex<double>, 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 std::array<T, M*N> */ template<class T, std::size_t M, std::size_t N, class L, class A> class fixed_matrix: public matrix_container<fixed_matrix<T, M, N, L, A> > { typedef T *pointer; typedef L layout_type; typedef fixed_matrix<T, M, N, 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 fixed_matrix constructor. Make a dense fixed_matrix of size M x N BOOST_UBLAS_INLINE fixed_matrix (): matrix_container<self_type> (), data_ () {} /** Dense fixed_matrix constructor with defined initial value for all the matrix elements * \param init initial value assigned to all elements */ fixed_matrix (const value_type &init): matrix_container<self_type> (), data_ ( ) { data_.fill(init); } /** Dense matrix constructor with defined initial data array * \param data array to copy into the matrix. Must have the same dimension as the matrix */ BOOST_UBLAS_INLINE fixed_matrix (const array_type &data): matrix_container<self_type> (), data_ (data) {} /** Copy-constructor of a dense fixed_matrix * \param m is a dense fixed_matrix */ BOOST_UBLAS_INLINE fixed_matrix (const fixed_matrix &m): matrix_container<self_type> (), 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 fixed_matrix (const matrix_expression<AE> &ae): matrix_container<self_type> (), data_ () { matrix_assign<scalar_assign> (*this, ae); } /// \brief Construct a fixed_matrix from a list of values /// The list may be included in curly braces. Typical syntax is choices are : /// fixed_matrix<double, 2,2> v = { 1, 2, 3, 4 } or fixed_matrix<double,4> v( {1, 2, 3, 4} ) or fixed_matrix<double,2,2> v( 1, 2, 3, 4 ) template <typename... Types> BOOST_UBLAS_INLINE fixed_matrix(value_type v0, Types... vrest) : matrix_container<self_type> (), data_( array_type{ v0, vrest... } ) {} // Accessors /** Return the number of rows of the fixed_matrix * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a fixed_matrix */ BOOST_UBLAS_INLINE BOOST_CONSTEXPR size_type size1 () const { return M; } /** Return the number of colums of the fixed_matrix * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a fixed_matrix */ BOOST_UBLAS_INLINE BOOST_CONSTEXPR size_type size2 () const { return N; } // 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 fixed_matrix, i.e. the raw data * It's type depends on the type used by the fixed_matrix to store its data */ BOOST_UBLAS_INLINE array_type &data () { return data_; } // Element access /** Access a fixed_matrix element. Here we return a const reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a const reference to the element */ BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { return data () [layout_type::element (i, M, j, N)]; // Fixme: add static lookup for element(...) i.e.: element<M, N>(i,j) } /** Access a fixed_matrix element. Here we return a reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a reference to the element */ BOOST_UBLAS_INLINE reference at_element (size_type i, size_type j) { return data () [layout_type::element (i, M, j, N)]; } /** Access a fixed_matrix element. Here we return a reference * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \return a reference to the element */ BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { return at_element (i, j); } // Element assignment /** Change the value of a fixed_matrix element. Return back a reference to it * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column * \param t the new value of the element * \return a reference to the newly changed element */ BOOST_UBLAS_INLINE reference insert_element (size_type i, size_type j, const_reference t) { return (at_element (i, j) = t); } /** Erase the element * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact. * For user-defined types, it could be another value if you decided it. Your type in that case must * contain a default null value. * \param i the first coordinate of the element. By default it's the row * \param j the second coordinate of the element. By default it's the column */ void erase_element (size_type i, size_type j) { at_element (i, j) = value_type/*zero*/(); } // Zeroing /** Erase all elements in the fixed_matrix * For most types (int, double, etc...) it means writing 0 (zero) everywhere. * For user-defined types, it could be another value if you decided it. Your type in that case must * contain a default null value. */ 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 fixed_matrix &operator = (fixed_matrix m) { assign_temporary(m); return *this; } #else BOOST_UBLAS_INLINE fixed_matrix &operator = (const fixed_matrix &m) { data () = m.data (); return *this; } #endif template<class C> // Container assignment without temporary BOOST_UBLAS_INLINE fixed_matrix &operator = (const matrix_container<C> &m) { resize (m ().size1 (), m ().size2 (), false); assign (m); return *this; } BOOST_UBLAS_INLINE fixed_matrix &assign_temporary (fixed_matrix &m) { swap (m); return *this; } template<class AE> BOOST_UBLAS_INLINE fixed_matrix &operator = (const matrix_expression<AE> &ae) { self_type temporary (ae); return assign_temporary (temporary); } template<class AE> BOOST_UBLAS_INLINE fixed_matrix &assign (const matrix_expression<AE> &ae) { matrix_assign<scalar_assign> (*this, ae); return *this; } template<class AE> BOOST_UBLAS_INLINE fixed_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 fixed_matrix &operator += (const matrix_container<C> &m) { plus_assign (m); return *this; } template<class AE> BOOST_UBLAS_INLINE fixed_matrix &plus_assign (const matrix_expression<AE> &ae) { matrix_assign<scalar_plus_assign> (*this, ae); return *this; } template<class AE> BOOST_UBLAS_INLINE fixed_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 fixed_matrix &operator -= (const matrix_container<C> &m) { minus_assign (m); return *this; } template<class AE> BOOST_UBLAS_INLINE fixed_matrix &minus_assign (const matrix_expression<AE> &ae) { matrix_assign<scalar_minus_assign> (*this, ae); return *this; } template<class AT> BOOST_UBLAS_INLINE fixed_matrix& operator *= (const AT &at) { matrix_assign_scalar<scalar_multiplies_assign> (*this, at); return *this; } template<class AT> BOOST_UBLAS_INLINE fixed_matrix& operator /= (const AT &at) { matrix_assign_scalar<scalar_divides_assign> (*this, at); return *this; } // Swapping BOOST_UBLAS_INLINE void swap (fixed_matrix &m) { if (this != &m) { data ().swap (m.data ()); } } BOOST_UBLAS_INLINE friend void swap (fixed_matrix &m1, fixed_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, M, j, N)); #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, M, j, N)); #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, M, j, N)); #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, M, j, N)); #endif } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference<fixed_matrix>, public random_access_iterator_base<dense_random_access_iterator_tag, const_iterator1, value_type> { public: typedef typename fixed_matrix::value_type value_type; typedef typename fixed_matrix::difference_type difference_type; typedef typename fixed_matrix::const_reference reference; typedef const typename fixed_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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, M, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator1: public container_reference<fixed_matrix>, public random_access_iterator_base<dense_random_access_iterator_tag, iterator1, value_type> { public: typedef typename fixed_matrix::value_type value_type; typedef typename fixed_matrix::difference_type difference_type; typedef typename fixed_matrix::reference reference; typedef typename fixed_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, M, 0); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference<fixed_matrix>, public random_access_iterator_base<dense_random_access_iterator_tag, const_iterator2, value_type> { public: typedef typename fixed_matrix::value_type value_type; typedef typename fixed_matrix::difference_type difference_type; typedef typename fixed_matrix::const_reference reference; typedef const typename fixed_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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, N); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator2: public container_reference<fixed_matrix>, public random_access_iterator_base<dense_random_access_iterator_tag, iterator2, value_type> { public: typedef typename fixed_matrix::value_type value_type; typedef typename fixed_matrix::difference_type difference_type; typedef typename fixed_matrix::reference reference; typedef typename fixed_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, N); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 */){ ar & serialization::make_nvp("data",data_); } private: array_type data_; }; #endif // BOOST_UBLAS_CPP_GE_2011 /** \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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return const_iterator1 (*this); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } // 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 boost::allocator_size_type<ALLOC>::type size_type; typedef typename boost::allocator_difference_type<ALLOC>::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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return const_iterator1 (*this, size_common_); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } 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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return const_iterator2 (*this, size_common_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 ublas/traits.hpp 0000644 00000060570 15125237305 0007704 0 ustar 00 // // 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> #ifdef BOOST_UBLAS_USE_INTERVAL #include <boost/numeric/interval.hpp> #endif #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/type_traits/is_unsigned.hpp> #include <boost/mpl/and.hpp> #include <boost/mpl/if.hpp> #include <boost/typeof/typeof.hpp> // anonymous namespace to avoid ADL issues namespace { template<class T> typename boost::mpl::if_c<boost::is_integral<T>::value, double, T>::type 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<typename T> inline typename boost::disable_if< boost::is_unsigned<T>, T >::type boost_numeric_ublas_abs (const T &t ) { using namespace std; // force a type conversion back to T for char and short types return static_cast<T>(abs( t )); } template<typename T> inline typename boost::enable_if< boost::is_unsigned<T>, T >::type boost_numeric_ublas_abs (const T &t ) { return t; } } namespace boost { namespace numeric { namespace ublas { template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) { return R (in1) + in2; } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) { return in1 + R (in2); } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) { return R (in1) - in2; } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) { return in1 - R (in2); } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) { return R (in1) * in2; } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) { return in1 * R(in2); } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) { return R(in1) / in2; } template<typename R, typename I> typename boost::enable_if< mpl::and_< boost::is_float<R>, boost::is_integral<I> >, std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) { return in1 / R (in2); } // uBLAS assumes a common return type for all binary arithmetic operators template<class X, class Y> struct promote_traits { typedef BOOST_TYPEOF_TPL(X() + Y()) promote_type; }; // 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 has_trivial_constructor<FLT> {}; template<typename FLT> struct has_trivial_destructor<std::complex<FLT> > : public has_trivial_destructor<FLT> {}; } /** \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 ublas/operation.hpp 0000644 00000076556 15125237305 0010411 0 ustar 00 // // 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 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 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 E2 expression2_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 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 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; 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 typename M::size_type size_type; #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 TRI triangular_restriction; typedef const E1 expression1_type; typedef const E2 expression2_type; #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 typename M::size_type size_type; #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 TRI triangular_restriction; typedef const E1 expression1_type; typedef const E2 expression2_type; #if BOOST_UBLAS_TYPE_CHECK typedef typename M::value_type value_type; 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 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 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 ublas/lu.hpp 0000644 00000033334 15125237305 0007014 0 ustar 00 // // 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; 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; 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 typename M::size_type size_type; typedef typename M::value_type value_type; #if BOOST_UBLAS_TYPE_CHECK typedef M matrix_type; 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 typename M::size_type size_type; typedef typename M::value_type value_type; #if BOOST_UBLAS_TYPE_CHECK typedef M matrix_type; 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) { #if BOOST_UBLAS_TYPE_CHECK typedef const M const_matrix_type; typedef vector<typename E::value_type> vector_type; 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) { #if BOOST_UBLAS_TYPE_CHECK typedef const M const_matrix_type; typedef matrix<typename E::value_type> matrix_type; 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) { #if BOOST_UBLAS_TYPE_CHECK typedef const M const_matrix_type; typedef vector<typename E::value_type> vector_type; 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) { #if BOOST_UBLAS_TYPE_CHECK typedef const M const_matrix_type; typedef matrix<typename E::value_type> matrix_type; 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 ublas/assignment.hpp 0000644 00000105654 15125237305 0010551 0 ustar 00 // // 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::ptrdiff_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 { // With the equivalent expression using '+=' operator, mscv reports waring C4245: // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch k = 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::ptrdiff_t I> 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::ptrdiff_t I, std::ptrdiff_t J> class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > { public: template <typename V, typename K> BOOST_UBLAS_INLINE void manip(V &k, K &l) const { // With the equivalent expression using '+=' operator, mscv reports waring C4245: // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch k = k + I; l = 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::ptrdiff_t I, std::ptrdiff_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() */ 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 */ 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() */ 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 * */ 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 progresses only using this function from within // an assigner object. // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been // outside the if statement. 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 progresses only using this function from within // an assigner object. // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been // outside the if statement. 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 { inline by_row_policy<DEFAULT_WRAP_POLICY> by_row() { return by_row_policy<DEFAULT_WRAP_POLICY>(); } inline by_row_policy<wrap> by_row_wrap() { return by_row_policy<wrap>(); } inline by_row_policy<no_wrap> by_row_no_wrap() { return by_row_policy<no_wrap>(); } inline by_column_policy<DEFAULT_WRAP_POLICY> by_column() { return by_column_policy<DEFAULT_WRAP_POLICY>(); } inline by_column_policy<wrap> by_column_wrap() { return by_column_policy<wrap>(); } inline 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 ublas/symmetric.hpp 0000644 00000254167 15125237305 0010421 0 ustar 00 // // 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size_, 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size_); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 cbegin () const { return begin (); } 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_iterator2 cend () const { return 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 crend () const { return rend (); } #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 cbegin1 () const { return begin1 (); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } BOOST_UBLAS_INLINE const_iterator1 cend1 () const { return end1 (); } #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 cbegin () const { return begin (); } 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_iterator1 cend () const { return end (); } 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 crbegin () const { return rbegin (); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 crend () const { return rend (); } #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 cbegin2 () const { return begin2 (); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } BOOST_UBLAS_INLINE const_iterator2 cend2 () const { return end2 (); } #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 crbegin1 () const { return rbegin1 (); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 crend1 () const { return rend1 (); } 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 crbegin2 () const { return rbegin2 (); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 crend2 () const { return rend2 (); } 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 odeint.hpp 0000644 00000006506 15125237305 0006551 0 ustar 00 /* [auto_generated] boost/numeric/odeint.hpp [begin_description] Forward include for odeint. Includes nearly everything. [end_description] Copyright 2009-2013 Karsten Ahnert Copyright 2010-2013 Mario Mulansky 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_ODEINT_HPP_INCLUDED #define BOOST_NUMERIC_ODEINT_HPP_INCLUDED #include <boost/numeric/odeint/version.hpp> #include <boost/numeric/odeint/config.hpp> // start with ublas wrapper because we need its specializations before including state_wrapper.hpp #include <boost/numeric/odeint/util/ublas_wrapper.hpp> #include <boost/numeric/odeint/stepper/euler.hpp> #include <boost/numeric/odeint/stepper/runge_kutta4_classic.hpp> #include <boost/numeric/odeint/stepper/runge_kutta4.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_cash_karp54_classic.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp> #include <boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp> #include <boost/numeric/odeint/stepper/controlled_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp> #include <boost/numeric/odeint/stepper/bulirsch_stoer.hpp> #ifndef __CUDACC__ /* Bulirsch Stoer with Dense Output does not compile with nvcc * because of the binomial library used there which relies on unsupported SSE functions */ #include <boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp> #endif #include <boost/numeric/odeint/stepper/symplectic_euler.hpp> #include <boost/numeric/odeint/stepper/symplectic_rkn_sb3a_mclachlan.hpp> #include <boost/numeric/odeint/stepper/velocity_verlet.hpp> #include <boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp> #include <boost/numeric/odeint/stepper/implicit_euler.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4_controller.hpp> #include <boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp> #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> #include <boost/numeric/odeint/algebra/multi_array_algebra.hpp> #include <boost/numeric/odeint/util/multi_array_adaption.hpp> /* * Including this algebra slows down the compilation time */ // #include <boost/numeric/odeint/algebra/fusion_algebra.hpp> #include <boost/numeric/odeint/integrate/integrate.hpp> #include <boost/numeric/odeint/integrate/integrate_adaptive.hpp> #include <boost/numeric/odeint/integrate/integrate_const.hpp> #include <boost/numeric/odeint/integrate/integrate_n_steps.hpp> #include <boost/numeric/odeint/integrate/integrate_times.hpp> #include <boost/numeric/odeint/integrate/observer_collection.hpp> #include <boost/numeric/odeint/integrate/max_step_checker.hpp> #include <boost/numeric/odeint/stepper/generation.hpp> #include <boost/numeric/odeint/iterator/adaptive_iterator.hpp> #include <boost/numeric/odeint/iterator/adaptive_time_iterator.hpp> #include <boost/numeric/odeint/iterator/const_step_iterator.hpp> #include <boost/numeric/odeint/iterator/const_step_time_iterator.hpp> #endif // BOOST_NUMERIC_ODEINT_HPP_INCLUDED interval/hw_rounding.hpp 0000644 00000004611 15125237305 0011431 0 ustar 00 /* 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(__clang__) || defined(_M_X64) # include <boost/numeric/interval/detail/x86_rounding_control.hpp> #elif defined(__i386) && defined(__SUNPRO_CC) # 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 interval/compare/lexicographic.hpp 0000644 00000007431 15125237305 0013360 0 ustar 00 /* 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 interval/compare/explicit.hpp 0000644 00000013736 15125237305 0012365 0 ustar 00 /* 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 interval/compare/possible.hpp 0000644 00000006527 15125237305 0012364 0 ustar 00 /* 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 interval/compare/set.hpp 0000644 00000005066 15125237305 0011334 0 ustar 00 /* 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>& , const T& ) { 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>& , const T& ) { 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>& , const T& ) { 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>& , const T& ) { 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>& , const T& ) { 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>& , const T& ) { throw comparison_error(); } } // namespace set } // namespace compare } // namespace interval_lib } // namespace numeric } // namespace boost #endif // BOOST_NUMERIC_INTERVAL_COMPARE_SET_HPP interval/compare/tribool.hpp 0000644 00000011011 15125237305 0012176 0 ustar 00 /* 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 interval/compare/certain.hpp 0000644 00000006515 15125237305 0012166 0 ustar 00 /* 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 interval/arith2.hpp 0000644 00000023554 15125237305 0010306 0 ustar 00 /* 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 interval/utility.hpp 0000644 00000024765 15125237305 0010625 0 ustar 00 /* 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/numeric/interval/utility_fwd.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) { 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 interval/policies.hpp 0000644 00000003353 15125237305 0010717 0 ustar 00 /* 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 interval/rounding.hpp 0000644 00000005043 15125237305 0010733 0 ustar 00 /* 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 interval/transc.hpp 0000644 00000017355 15125237305 0010411 0 ustar 00 /* 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 interval/io.hpp 0000644 00000002226 15125237305 0007515 0 ustar 00 /* 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 interval/arith3.hpp 0000644 00000004146 15125237305 0010303 0 ustar 00 /* 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 interval/detail/c99_rounding_control.hpp 0000644 00000002414 15125237305 0014420 0 ustar 00 /* 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 interval/detail/x86gcc_rounding_control.hpp 0000644 00000002504 15125237305 0015116 0 ustar 00 /* 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 #if !defined(__GNUC__) && !(defined(__BORLANDC__) && defined(__clang__)) # error This header only works with GNU CC. #endif #if !defined(__i386__) && !defined(__x86_64__) # 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 */ interval/detail/alpha_rounding_control.hpp 0000644 00000007027 15125237305 0015106 0 ustar 00 /* 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 */ interval/detail/ia64_rounding_control.hpp 0000644 00000004145 15125237305 0014562 0 ustar 00 /* 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 */ interval/detail/c99sub_rounding_control.hpp 0000644 00000002530 15125237305 0015131 0 ustar 00 /* 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 interval/detail/division.hpp 0000644 00000016513 15125237305 0012200 0 ustar 00 /* 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 interval/detail/test_input.hpp 0000644 00000004426 15125237305 0012552 0 ustar 00 /* 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 interval/detail/sparc_rounding_control.hpp 0000644 00000005766 15125237305 0015141 0 ustar 00 /* 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 */ interval/detail/msvc_rounding_control.hpp 0000644 00000006527 15125237305 0014775 0 ustar 00 /* 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 #if !defined(_M_AMD64) && !defined(_M_ARM) && !defined(_M_ARM64) // x64 ignores _MCW_PC and _MCW_IC, and the Debug CRT library actually // asserts when these are passed to _control87. // MSDN says on '_control87' that changing precision (_MCW_PC) or // infinity (_MCW_IC) handling is not supported on the ARM and x64 // architectures and that _control87 raises an assertion // and the invalid parameter handler is invoked. | _MCW_PC | _MCW_IC #endif ); } 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 */ interval/detail/interval_prototype.hpp 0000644 00000002013 15125237305 0014313 0 ustar 00 /* 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 interval/detail/bcc_rounding_control.hpp 0000644 00000003110 15125237305 0014535 0 ustar 00 /* 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 #if !defined(__BORLANDC__) || defined(__clang__) # 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 */ interval/detail/bugs.hpp 0000644 00000002751 15125237305 0011313 0 ustar 00 /* 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 #endif // BOOST_NUMERIC_INTERVAL_DETAIL_BUGS interval/detail/x86_rounding_control.hpp 0000644 00000006174 15125237305 0014450 0 ustar 00 /* 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 #if defined(__GNUC__) || defined(__BORLANDC__) && defined(__clang__) # 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 */ interval/detail/ppc_rounding_control.hpp 0000644 00000005613 15125237305 0014602 0 ustar 00 /* 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 */ interval/rounded_arith.hpp 0000644 00000011257 15125237305 0011741 0 ustar 00 /* 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 this->to_int(x); } T int_up (const T& x) { this->upward(); return this->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 -this->to_int(-x); } T int_up (const T& x) { return this->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 interval/interval.hpp 0000644 00000027646 15125237305 0010747 0 ustar 00 /* 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 interval/constants.hpp 0000644 00000006151 15125237305 0011123 0 ustar 00 /* 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 interval/limits.hpp 0000644 00000003323 15125237305 0010406 0 ustar 00 /* 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 #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 () BOOST_NOEXCEPT_OR_NOTHROW { return I((bl::min)(), (bl::min)()); } static I max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT_OR_NOTHROW { return I((bl::max)(), (bl::max)()); } static I epsilon() BOOST_NOEXCEPT_OR_NOTHROW { 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 () BOOST_NOEXCEPT_OR_NOTHROW { return I::whole(); } static I quiet_NaN() BOOST_NOEXCEPT_OR_NOTHROW { return I::empty(); } static I signaling_NaN() BOOST_NOEXCEPT_OR_NOTHROW { return I(bl::signaling_NaN(), bl::signaling_Nan()); } static I denorm_min() BOOST_NOEXCEPT_OR_NOTHROW { return I(bl::denorm_min(), bl::denorm_min()); } private: static I round_error(); // hide this on purpose, not yet implemented }; } // namespace std #endif // BOOST_NUMERIC_INTERVAL_LIMITS_HPP interval/ext/x86_fast_rounding_control.hpp 0000644 00000005326 15125237305 0015021 0 ustar 00 /* 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 interval/ext/integer.hpp 0000644 00000003431 15125237305 0011342 0 ustar 00 /* 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 interval/checking.hpp 0000644 00000005410 15125237305 0010657 0 ustar 00 /* 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 interval/arith.hpp 0000644 00000024161 15125237305 0010217 0 ustar 00 /* 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 interval/rounded_transc.hpp 0000644 00000012225 15125237305 0012120 0 ustar 00 /* 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 interval/utility_fwd.hpp 0000644 00000010755 15125237305 0011457 0 ustar 00 /* Boost interval/utility.hpp template interface file * * Copyright 2013 Cromwell D. Enage * * 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_FWD_HPP #define BOOST_NUMERIC_INTERVAL_UTILITY_FWD_HPP #include <boost/config.hpp> #include <boost/numeric/interval/detail/interval_prototype.hpp> #include <utility> /* * Interface of simple functions */ namespace boost { namespace numeric { /* * Utility Functions */ template<class T, class Policies> const T& lower(const interval<T,Policies>& x); template<class T, class Policies> const T& upper(const interval<T,Policies>& x); template<class T, class Policies> T checked_lower(const interval<T,Policies>& x); template<class T, class Policies> T width(const interval<T,Policies>& x); template<class T, class Policies> T median(const interval<T,Policies>& x); template<class T, class Policies> interval<T,Policies> widen(const interval<T,Policies>& x, const T& v); /* * Set-like operations */ template <class T, class Policies> bool empty(const interval<T,Policies>& x); template <class T, class Policies> bool zero_in(const interval<T,Policies>& x); template <class T, class Policies> bool in_zero(const interval<T,Policies>& x); // DEPRECATED template <class T, class Policies> bool in(const T& x, const interval<T,Policies>& y); template <class T, class Policies> bool subset( const interval<T,Policies>& x , const interval<T,Policies>& y ); template <class T, class Policies1, class Policies2> bool proper_subset( const interval<T,Policies1>& x , const interval<T,Policies2>& y ); template <class T, class Policies1, class Policies2> bool overlap( const interval<T,Policies1>& x , const interval<T,Policies2>& y ); template <class T, class Policies> bool singleton(const interval<T, Policies>& x); template <class T, class Policies1, class Policies2> bool equal( const interval<T,Policies1>& x , const interval<T,Policies2>& y ); template <class T, class Policies> interval<T, Policies> intersect( const interval<T,Policies>& x , const interval<T,Policies>& y ); template <class T, class Policies> interval<T, Policies> hull(const interval<T,Policies>& x, const interval<T,Policies>& y); template <class T, class Policies> interval<T, Policies> hull(const interval<T,Policies>& x, const T& y); template <class T, class Policies> interval<T, Policies> hull(const T& x, const interval<T,Policies>& y); template <class T> interval<T> hull(const T& x, const T& y); template <class T, class Policies> std::pair<interval<T,Policies>,interval<T,Policies> > bisect(const interval<T,Policies>& x); /* * Elementary functions */ template <class T, class Policies> T norm(const interval<T,Policies>& x); template <class T, class Policies> interval<T,Policies> abs(const interval<T,Policies>& x); template <class T, class Policies> interval<T,Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION ( const interval<T,Policies>& x , const interval<T,Policies>& y ); template <class T, class Policies> interval<T,Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION ( const interval<T,Policies>& x , const T& y ); template <class T, class Policies> interval<T,Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION ( const T& x , const interval<T,Policies>& y ); template <class T, class Policies> interval<T,Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION ( const interval<T,Policies>& x , const interval<T,Policies>& y ); template <class T, class Policies> interval<T,Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION ( const interval<T,Policies>& x , const T& y ); template <class T, class Policies> interval<T,Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION ( const T& x , const interval<T,Policies>& y ); }} // namespace boost::numeric #endif // include guard interval/compare.hpp 0000644 00000001301 15125237305 0010525 0 ustar 00 /* 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
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0.13 |
proxy
|
phpinfo
|
???????????